Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cgen bug when using generics with C types #23374

Open
dy-tea opened this issue Jan 4, 2025 · 3 comments
Open

cgen bug when using generics with C types #23374

dy-tea opened this issue Jan 4, 2025 · 3 comments
Labels
Bug This tag is applied to issues which reports bugs. Status: Confirmed This bug has been confirmed to be valid by a contributor. Unit: cgen Bugs/feature requests, that are related to the default C generating backend.

Comments

@dy-tea
Copy link

dy-tea commented Jan 4, 2025

V doctor:

|V full version      |V 0.4.9 de3b184.495adc9
|:-------------------|:-------------------
|OS                  |linux, "CachyOS"
|Processor           |12 cpus, 64bit, little endian, 13th Gen Intel(R) Core(TM) i5-1335U
|Memory              |4.62GB/15.31GB
|                    |
|V executable        |/home/dylan/Repos/v/v
|V last modified time|2025-01-04 19:40:15
|                    |
|V home dir          |OK, value: /home/dylan/Repos/v
|VMODULES            |OK, value: /home/dylan/.vmodules
|VTMP                |OK, value: /tmp/v_1000
|Current working dir |OK, value: /home/dylan
|                    |
|Git version         |git version 2.47.1
|V git status        |weekly.2024.53-29-g495adc9c
|.git/config present |true
|                    |
|cc version          |cc (GCC) 14.2.1 20240910
|gcc version         |gcc (GCC) 14.2.1 20240910
|clang version       |clang version 18.1.8
|tcc version         |tcc version 0.9.28rc 2024-07-31 HEAD@1cee0908 (x86_64 Linux)
|tcc git status      |thirdparty-linux-amd64 0134e9b9
|emcc version        |N/A
|glibc version       |ldd (GNU libc) 2.40

What did you do?
./v -g -o vdbg cmd/v && ./vdbg test.v && test

#include <libudev.h>

struct C.udev {}

fn generic[T](val T) &T {
  return &val
}

fn main() {
  u := C.udev{}
  r := generic(u) 
}

What did you see?

test.v:11:3: warning: unused variable: `r`
    9 | fn main() {
   10 |   u := C.udev{}
   11 |   r := generic(u) 
      |   ^
   12 | }
================== C compilation error (from tcc): ==============
cc: /tmp/v_1000/test.01JGSDAPXA9BGCPGMVHHYATA85.tmp.c:1333: error: ';' expected (got "udev")
=================================================================
(You can pass `-cg`, or `-show-c-output` as well, to print all the C error messages).
builder error: 
==================
C error found. It should never happen, when compiling pure V code.
This is a V compiler bug, please report it using `v bug file.v`,
or goto https://github.com/vlang/v/issues/new/choose .
You can also use #help on Discord: https://discord.gg/vlang .

What did you expect to see?

compile successfully

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Huly®: V_0.6-21805

@dy-tea dy-tea changed the title cgen bug whene using generics with C types cgen bug when using generics with C types Jan 4, 2025
@jorgeluismireles
Copy link

I got interest in your issue because I am working in a USB project which uses libudev. First, the problem is not related with generics but in the way you call C.udev wich is opaque (don't ask me why I am also still learning).

Your code reduced:

#include <libudev.h>

struct C.udev {}

fn main() {
  _ := C.udev{}
}

Produced this (with gcc which gives more info):

================== C compilation error (from gcc): ==============
cc: /tmp/v_1000/bug.01JGSRJSX21GSH58GE60STWZXW.tmp.c: In function ‘main__main’:
cc: /tmp/v_1000/bug.01JGSRJSX21GSH58GE60STWZXW.tmp.c:5620:17: error: variable ‘_’ has initializer but incomplete type
cc:  5620 |         {struct udev _ = ((struct udev){EMPTY_STRUCT_INITIALIZATION});}
cc:       |                 ^~~~
cc: /tmp/v_1000/bug.01JGSRJSX21GSH58GE60STWZXW.tmp.c:5620:40: error: invalid use of undefined type ‘struct udev’
cc:  5620 |         {struct udev _ = ((struct udev){EMPTY_STRUCT_INITIALIZATION});}
cc:       |                                        ^
cc: /tmp/v_1000/bug.01JGSRJSX21GSH58GE60STWZXW.tmp.c:5620:22: error: storage size of ‘_’ isn’t known
cc:  5620 |         {struct udev _ = ((struct udev){EMPTY_STRUCT_INITIALIZATION});}
cc:       |                      ^
=================================================================

Then I googled about the message has initializer but incomplete type, make tests and arrive to this:

module main

#pkgconfig libudev // -ludev
#include <libudev.h>

struct C.udev{}
type Udev = C.udev // make V's type

// _public_ struct udev *udev_new(void) {
fn C.udev_new() &C.udev

fn new_udev() &Udev { // V builder
	return C.udev_new()
}

fn generic[T](val T) &T {
  return &val
}

fn main() {
	u := new_udev()
	println('u ${u}')
	g := generic(u)
	println('g ${g}')
}

produces (gcc or tcc now):

u Udev(C.udev{})
g Udev(C.udev{})

The pkgconfig is for the linker. What I learned:

  • Seems a working C.udev should be created with C.udev_new() or other functions of the library.
  • Seems we need a V struct (not a C one) to be used in generics.

I expect more explanations from the team to learn more.

@dy-tea
Copy link
Author

dy-tea commented Jan 4, 2025

You method of creating the udev is indeed correct, I was trying to select a type that was easily accessible and missed the correct method.
Either way generics are not working on C structs which is the issue I was running into on my project.
Given the below code:

#pkgconfig libudev
#include <libudev.h>

struct C.udev {}

fn C.udev_new() &C.udev

fn new_udev() &C.udev {
  return C.udev_new()
}

fn generic[T](val T) &T {
  return &val
}

fn main() {
  u := new_udev()
  r := generic(u) 
}

This will produce:

test.v:18:3: warning: unused variable: `r`
   16 | fn main() {
   17 |   u := new_udev()
   18 |   r := generic(u)
      |   ^
   19 | }
======== Output of the C Compiler (/home/dylan/Repos/v/thirdparty/tcc/tcc.exe) ========
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:1337: error: ';' expected (got "udev")
=======================================================================================
======== Output of the C Compiler (cc) ========
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:1337:45: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘udev’
 1337 | struct udev** main__generic_T___ptr__struct udev(struct udev* _v_toheap_val);
      |                                             ^~~~
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:5676:45: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘udev’
 5676 | struct udev** main__generic_T___ptr__struct udev(struct udev* _v_toheap_val) {
      |                                             ^~~~
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c: In function ‘main__main’:
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:5682:27: error: ‘main__generic_T___ptr__struct’ undeclared (first use in this function)
 5682 |         struct udev** r = main__generic_T___ptr__struct udev(u);
      |                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:5682:27: note: each undeclared identifier is reported only once for each function it appears in
/tmp/v_1000/test.01JGSTFXTS1ZS9P3H66R430XWD.tmp.c:5682:57: error: expected ‘,’ or ‘;’ before ‘udev’
 5682 |         struct udev** r = main__generic_T___ptr__struct udev(u);
      |                                                         ^~~~
===============================================

Which makes the errors with generics more clear.

@jorgeluismireles
Copy link

Either way generics are not working on C structs which is the issue I was running into on my project.

You are right, any C error should be fixed. The alias conversion of C type to V is a workaround for now. Let see if the team decides to do the conversion for us or mark as invalid the use of structs coming from C, JS or the other backends for the generics.

@felipensp felipensp added Bug This tag is applied to issues which reports bugs. Status: Confirmed This bug has been confirmed to be valid by a contributor. Unit: cgen Bugs/feature requests, that are related to the default C generating backend. labels Jan 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug This tag is applied to issues which reports bugs. Status: Confirmed This bug has been confirmed to be valid by a contributor. Unit: cgen Bugs/feature requests, that are related to the default C generating backend.
Projects
None yet
Development

No branches or pull requests

3 participants