metals
metals copied to clipboard
Type parameters from extension receiver not forwarded to completions in scala 3
Describe the bug
If the signature of a method added by an extension or an implicit conversion refers to a type parameter which should be fixed by the method receiver, the type is not substituted in code completions, e.g. for
extension[T](opt: Option[T])
def append(x: T): Seq[T] = opt.toSeq :+ x
val x = Some(1).app@@
or
implicit class FooOps[T](opt: Option[T]):
def append(x: T): Seq[T] = opt.toSeq :+ x
val x = Some(1).app@@
the suggested completion is
append(x: T): Seq[T]
Expected behavior
Type parameters from the extension receiver should be properly propagated, e.g. in the given example the suggested completion should be
append(x: Int): Seq[Int]
Operating system
No response
Editor/Extension
No response
Version of Metals
0.11.7+60-d9677cff-SNAPSHOT
Extra context or search terms
No response
@prolativ Thanks for reporting!
I think it might be fixed only on compiler side. I already did a similar work with providing a correct type for member completion - https://github.com/scalameta/metals/blob/d9677cff9df3cbd3af977470e3513334abd74b53/mtags/src/main/scala-3/scala/meta/internal/pc/completions/Completions.scala#L482-L502
However, after trying to do the same for extension methods and implicit conversion I realized that it's not possible to do on Metals side. The issue is that returned symbol from interactive.Completion
carries the detonation that provides only original symbol type with abstract types.
I think we could do 2 things:
- copy over the logic from https://github.com/lampepfl/dotty/pull/11187/files or try to reuse it in some way
- make the interface for completions a bit better (@prolativ already raised na issue): https://github.com/lampepfl/dotty/issues/15730. We can use it for the newer versions of compiler
@tgodzik @prolativ I would choose to not to change interfaces. Actually, the are good enough to use. The issue is that by some reason we are getting a symbol with not-precise denot or info. But it's possible to fix
We can reuse this thing that we have in metals: https://github.com/scalameta/metals/blob/d9677cff9df3cbd3af977470e3513334abd74b53/mtags/src/main/scala-3/scala/meta/internal/mtags/MtagsEnrichments.scala#L132-L146
The point is that in a case like this it's impossible to get the full type signature from a symbol - one needs the entire typed tree of the extension receiver
@prolativ but it's possible on dotty side. I only meant that it would be nice to change public interfaces
I would choose to not to change interfaces
it would be nice to change public interfaces
Now I'm quite confused which solution you would prefer 😕
opps :smile:
I mean do NOT to change
I think it wouldn't be a big problem to add a new endpoint in the compiler without removing the old one as that would be just splitting the logic into two parts and exposing the intermediate results of completions
This is actually fixed with https://github.com/lampepfl/dotty/pull/18914