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

Overriding an @varargs method fails under separate compilation #9463

Closed
martijnhoekstra opened this issue Jul 29, 2020 · 4 comments · Fixed by #9474
Closed

Overriding an @varargs method fails under separate compilation #9463

martijnhoekstra opened this issue Jul 29, 2020 · 4 comments · Fixed by #9474
Assignees

Comments

@martijnhoekstra
Copy link
Contributor

martijnhoekstra commented Jul 29, 2020

Minimized code

A.scala

import scala.annotation.varargs

trait FirstMixin {
  @varargs
  def counter(name: String*): Int = ???
}

B.scala:

trait Minimization extends FirstMixin {
    override def counter(name: String*): Int = 0
}

Output

Separate compilation of B.scala fails:

$ dotc A.scala
$ dotc -classpath . B.scala
-- [E037] Declaration Error: try/i9463b.scala:3:6 ------------------------------
3 |trait Minimization extends FirstMixin {
  |      ^
  |      method counter overrides nothing

Expectation

Compiles successfully.

@smarter smarter changed the title Overload resolution for varags annotated method fails in the presence of other unrelated mixins Overriding an @varargs method fails under separate compilation Jul 29, 2020
@smarter
Copy link
Member

smarter commented Jul 29, 2020

Thanks for the report, I've updated the issue with a simplified example.

@smarter
Copy link
Member

smarter commented Jul 29, 2020

The problem is that in ElimRepeated, we add the varargs forwarder in the tree transformer (transformDefDef) but not in the denotation transformer (transform). When compiling override def counter(name: String*): Int = 0 we correctly realize that a varargs forwarder is needed because it overrides a counter method marked @varargs, so we emit:

override def counter(name: Array[_ <: String]): Int = counter(name: _*)

But the compiler later fails thinking that this isn't actually overriding anything because under separate compilation we only run the denotation transformer for definitions coming from the classpath, so we don't see the forwarder generated for the original @varargs method.

I can think of two ways of fixing this: in addVarArgsForwarder we could simply drop the Override flag if we don't see an overridden definition, this is simple but a bit ad-hoc. Alternatively we could move the creation of the varargs forwarder symbols to the denotation transforme, this would be similar to the static methods we generate for value classes whose symbols are created in the denotation transformer (via createExtensionMethod) and later looked up when creating trees for them in the tree transformer (via extensionMethod), but this would be much more complicated and so probably not worth it. @TheElectronWill do you think you could have a look at this issue?

@TheElectronWill
Copy link
Contributor

Yes! I'll have a look.

@TheElectronWill
Copy link
Contributor

Okay, so I've tried both. Creating the symbol in transform seems better and isn't that complicated. I'll clean up the code and make a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants