Open p4veI opened 2 years ago
What are the types of Key and DataSource in your example? Are those interfaces? Classes? What are the relation between the two?
What are the types of Key and DataSource in your example? Are those interfaces? Classes? What are the relation between the two?
ah sorry, I updated the example, DataSource was supposed to be => Key in the original example/message. I tried to simplify the error for reporting purposes.
In my code I'm using DataSource which is an enum class, so Key
here refers to a class used as the Map key.
Unfortunately, I have zero experience with DS\Map and I have no idea how to use it. In addition to not having a reproducer, this makes resolving this quite difficult.
Could you try to create a small repo that can show the issue please?
Unfortunately, I have zero experience with DS\Map and I have no idea how to use it. In addition to not having a reproducer, this makes resolving this quite difficult.
Could you try to create a small repo that can show the issue please?
Sure, prepared it here: https://github.com/p4veI/test-ds-psalm , hope it works.
sidenote: feels like it's gonna be an issue with the generics on the mapFromIterable function perhaps - it's from an internal library of ours, but I added the function to the repo. While I was making the repository I tried to include the function as a public static method of a class rather than a plain function, and it didn't produce the error.
e.g Functions::mapFromIterable(...)
.
Simplified: https://psalm.dev/r/cccd83fa0f
I found these snippets:
Psalm inference has limitation.
During collection instantiation: new Collection([createBar(), createBaz()])
Psalm don't find most common type for Bar
and Baz
and infer Bar|Baz
instead Foo
.
Perhaps #4564 may fix it.
P.S. Collections from Ds are invariant. With covariant collections there is not issue: https://psalm.dev/r/91c7770c59
I found these snippets:
With covariant collections there is not issue
Ah, that makes sense. Since the template is invariant Collection<Bar|Baz>
can't be assigned to Collection<Foo>
.
Psalm don't find most common type for
Bar
andBaz
and inferBar|Baz
insteadFoo
.
I don't think we want to change how the inference works though, Collection<Bar|Baz>
is the correct type there, I'd rather not have less-specific inference. I think what needs to change is something about the invariance check, maybe somehow allowing covariance only for inferred types?
This also has the issue without adding a union into the mix: https://psalm.dev/r/5ed7d169db
Just trying to assign an inferred Collection<Bar>
to a Collection<Foo>
is the problem, and I don't think changing inference can fix it correctly anyway.
Psalm did find the common type but if the template is not covariant, it will prevent you to use a subtype here.
So, for me, it's not a bug
I was thinking Rust might infer the type automatically, but it looks like at least for the example I was able to throw together it requires you to explicitly state the type: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=50b7009a382f2fbc3595cdba7a05c180 https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=99b51f18688e2fc1e4f37451c9dad764
See lines 45-46. The explicit Box<dyn Animal>
is required, which is equivalent to us saying to do this you need to stick @var Collection<Foo>
before the new Collection(...)
.
I think we could support this if we really wanted to: https://psalm.dev/r/9fbf6e84bc
It might be possible to do something like an implicit @param-out
and make it work without the argument actually being a reference: https://psalm.dev/r/dbe060609b
I don't particularly care to try it, but unless there are other issues I'm not seeing it might not be too difficult to support.
On a related note, it would be good to add an issue for this: https://psalm.dev/r/53c059464e
I found these snippets:
Anyway, it seems like maybe templates on Ds classes should be covariant? Some of them already are, but not all of them. It looks like they're originally taken from PHPStan, it would be nice to know why they weren't covariant to begin with.
Hello I came across this issue recently, but unfortunately I was unable to replicate with the online tool at psalm.dev
Consider this example:
I'm instantiating Map with a helper function with two instances of Provider, both implementing the
Provider
interface. Unfortunately psalm reports:For more details I'm including the internals of
mapFromIterable
: