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

Anonymous generic function inside of a generic function #19045

Open
Dracks opened this issue Aug 2, 2023 · 5 comments
Open

Anonymous generic function inside of a generic function #19045

Dracks opened this issue Aug 2, 2023 · 5 comments
Labels
Bug This tag is applied to issues which reports bugs. Generics[T] Bugs/feature requests, that are related to the V generics. Status: Confirmed This bug has been confirmed to be valid by a contributor.

Comments

@Dracks
Copy link
Contributor

Dracks commented Aug 2, 2023

Describe the bug

Code: https://vosca.dev/p/fb9c42f729

When you have a generic function that accepts two types, and has an anonymous function inside, If you put only one type (and not the second, as this case that is used both), it give you a weird error.

I hope the people that knew better V-lang, can explain better the problem

struct Test{
	something string
}

struct Dependency {}

struct Factory {
	build fn()!
}
fn  inject[T](mut serv T)!{
	$for field in T.fields {
		if field.typ is string {
			serv.$(field.name) = "Hello world!"
		}
	}
}

fn use_factory[F, E](factory fn(dep F) !E) Factory{
	return Factory{
		build: fn [factory][F]()!{
				mut dep := F{}
				inject[F](mut dep)!
				dump(factory(dep)!)
		}
	}
}

use_factory[Dependency, Test](fn (dep Dependency)!Test {
	return Test{
		something: 'daleks!'
	}
}).build()!

Expected Behavior

Complain that the anonymous function misses the second generic parameter

Current Behavior

Output:

code.v:11:16: error: unknown type `F`
    9 | }
   10 | fn  inject[T](mut serv T)!{
   11 |     $for field in T.fields {
      |                   ^
   12 |         if field.typ is string {
   13 |             serv.$(field.name) = "Hello world!"
If the code of your project is in multiple files, try with `v .` instead of `v code.v`
Exited with error status 1

Reproduction Steps

For what I found you need a function, that creates an anonymous function that handles both types

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.4.0 8ee1667

Environment details (OS name and version, etc.)

V full version: V 0.4.0 fc4c431.8ee1667
OS: linux, Ubuntu 22.04.2 LTS
Processor: 2 cpus, 64bit, little endian, Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz

getwd: /home/pmakhnev/playground
vexe: /home/pmakhnev/v/v
vexe mtime: 2023-08-02 12:00:10

vroot: OK, value: /home/pmakhnev/v
VMODULES: OK, value: /root/.vmodules
VTMP: OK, value: /tmp/v_0

Git version: git version 2.34.1
Git vroot status: weekly.2023.30-63-g8ee1667a
.git/config present: true

CC version: cc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
thirdparty/tcc status: thirdparty-linux-amd64 12f392c3
@Dracks Dracks added the Bug This tag is applied to issues which reports bugs. label Aug 2, 2023
@shove70
Copy link
Contributor

shove70 commented Aug 3, 2023

struct Test{
	something string
}

struct Dependency {}

// struct Factory {
//	build fn()!
//}

struct Factory[F, E] {
	build fn(F) !E       // NOTE: function signatures need to be consistent.
}

fn  inject[T](mut serv T)!{
	$for field in T.fields {
		if field.typ is string {
			serv.$(field.name) = "Hello world!"
		}
	}
}

fn use_factory[F, E](factory fn(dep F) !E) Factory{
	return Factory{
		build: fn [factory][F]()!{
				mut dep := F{}
				inject[F](mut dep)!
				dump(factory(dep)!)
		}
	}
}

use_factory[Dependency, Test](fn (dep Dependency)!Test {
	return Test{
		something: 'daleks!'
	}
}).build()!

@Dracks
Copy link
Contributor Author

Dracks commented Aug 4, 2023 via email

@KamkoAmoh
Copy link

I tried to reproduce, but now it works fine

Some test code:

fn (mut db Database[T]) remove_by_id(id int) {	
	db.data = db.data.filter(fn [id][T](ele T) bool {
		return ele.id != id
	})
}

@JalonSolov
Copy link
Contributor

With latest V, I see both a notice and an error (that doesn't make sense):

bug.v:8:2: notice: uninitialized `fn` struct fields are not allowed, since they can result in segfaults; use `?fn` or `[required]` or initialize the field with `=` (if you absolutely want to have unsafe function pointers, use `= unsafe { nil }`)
    6 | 
    7 | struct Factory {
    8 |     build fn()!
      |     ~~~~~~~~~~~
    9 | }
   10 | fn  inject[T](mut serv T)!{
bug.v:11:16: error: unknown type `F`
    9 | }
   10 | fn  inject[T](mut serv T)!{
   11 |     $for field in T.fields {
      |                   ^
   12 |         if field.typ is string {
   13 |             serv.$(field.name) = "Hello world!"
If the code of your project is in multiple files, try with `v .` instead of `v bug.v`

@JalonSolov JalonSolov added the Status: Confirmed This bug has been confirmed to be valid by a contributor. label Oct 23, 2023
@Dracks
Copy link
Contributor Author

Dracks commented Oct 24, 2023

@KamkoAmoh the problem is when you have multiple generics.

@JalonSolov yes there was this warning/error, but is missleading, as the problem is the caller that only has 1 generic parameter, when you put both works. (you can see this is the same as the original, with only adding second generic in the anonymous function: https://vosca.dev/p/074d669643 )

@felipensp felipensp added the Generics[T] Bugs/feature requests, that are related to the V generics. label Jul 24, 2024
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. Generics[T] Bugs/feature requests, that are related to the V generics. Status: Confirmed This bug has been confirmed to be valid by a contributor.
Projects
None yet
Development

No branches or pull requests

5 participants