Skip to content

Crash when extending a type alias to a trait with implicit parameter #4837

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

Closed
Medowhill opened this issue Jul 25, 2018 · 3 comments
Closed

Comments

@Medowhill
Copy link
Contributor

I found this issue while trying to write some tests for issue #4582. PR #4827 is related.

trait T[X]
type Foo[X, Y] = T[X]
class D[X] extends Foo[X, Unit]
trait T[X: Numeric]
type Foo[X] = T[X]
class D[X: Numeric] extends Foo[X]

Two above examples were compiled.

trait T[X: Numeric]
type Foo[X, Y] = T[X]
class D[X: Numeric] extends Foo[X, Unit]

However, this one resulted the following crash:

Exception in thread "main" java.lang.AssertionError: assertion failed: missing parameters for trait T from ($outer: C, implicit evidence$2: scala.math.Numeric) extends Object() with T {
  private implicit val evidence$2: scala.math.Numeric
  private val $outer: C
  private <accessor> def $outer(): C = this.$outer
  final def C$D$$$outer(): C = D.this.$outer()
} should have been caught in typer
	at scala.Predef$.assert(Predef.scala:219)
	at dotty.tools.dotc.transform.Mixin.nextArgument$1(Mixin.scala:209)
	at dotty.tools.dotc.transform.Mixin.$anonfun$transformTemplate$12(Mixin.scala:235)
	at scala.collection.TraversableLike$WithFilter.$anonfun$map$2(TraversableLike.scala:739)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:738)
	at dotty.tools.dotc.transform.Mixin.traitInits$1(Mixin.scala:217)
	at dotty.tools.dotc.transform.Mixin.$anonfun$transformTemplate$17(Mixin.scala:263)
	at scala.collection.immutable.List.flatMap(List.scala:335)
	at dotty.tools.dotc.transform.Mixin.transformTemplate(Mixin.scala:262)
	at dotty.tools.dotc.transform.Mixin.transformTemplate(Mixin.scala:98)
	at dotty.tools.dotc.transform.MegaPhase.goTemplate(MegaPhase.scala:922)
@Medowhill
Copy link
Contributor Author

Medowhill commented Jul 25, 2018

Further investigation

1st code:

// after frontend
class D[X >: Nothing <: Any]() extends Object() with C.this.Foo[D.this.X, Unit] {
// after erasure
class D($outer: C) extends Object() with T {

2nd code:

// after frontend
class D[X >: Nothing <: Any](implicit evidence$2: Numeric[X])
  extends Object() with T[D.this.X]()(evidence$2) {
// after erasure
class D($outer: C, implicit evidence$2: scala.math.Numeric) extends Object() with T(evidence$2) {

3rd code:

// after frontend
class D[X >: Nothing <: Any](implicit evidence$2: Numeric[X])
  extends Object () with C.this.Foo[D.this.X, Unit] {
// after erasure
class D($outer: C, implicit evidence$2: scala.math.Numeric) extends Object() with T {

and another crash

trait T(x: Int)
type Foo[X] = T
class D extends Foo[Int]

It should be rejected by the typer but it passed the phase and resulted the same crash.

@Medowhill
Copy link
Contributor Author

Medowhill commented Jul 25, 2018

I think changing Typer.scala as the following would be a valid fix for this issue.

diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index da66c5b62..c37d0d419 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -1475,7 +1475,7 @@ class Typer extends Namer
      */
     def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo.stripPoly match {
       case cinfo @ MethodType(Nil) if cinfo.resultType.isImplicitMethod =>
-        typedExpr(untpd.New(ref, Nil))(superCtx)
+        typedExpr(untpd.New(untpd.TypedSplice(ref), Nil))(superCtx)
       case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] =>
         ref
       case cinfo: MethodType =>
@@ -1492,7 +1492,7 @@ class Typer extends Namer
 
     def typedParent(tree: untpd.Tree): Tree = {
       var result = if (tree.isType) typedType(tree)(superCtx) else typedExpr(tree)(superCtx)
-      val psym = result.tpe.typeSymbol
+      val psym = result.tpe.dealias.typeSymbol
       if (seenParents.contains(psym) && !cls.isRefinementClass)
         ctx.error(i"$psym is extended twice", tree.pos)
       seenParents += psym

However, it needs a correct implementation of untpd.New. Therefore, I'll make a PR after #4798 is merged to the master branch.

@allanrenucci
Copy link
Contributor

However, it needs a correct implementation of untpd.New. Therefore, I'll make a PR after #4798 is merged to the master branch.

You can make a PR based on the #4798 branch and rebase once it's merged. Or wait, up to you! 😄

allanrenucci added a commit that referenced this issue Jul 30, 2018
Fix #4837: use dealiased type for parent symbol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants