@@ -510,6 +510,16 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
510
510
def nonStaticModuleToMethod (module : Symbol ): Unit =
511
511
if (! module.isStatic) module setFlag METHOD | STABLE
512
512
513
+ // scala/scala-dev#219, scala/scala-dev#268
514
+ // Cast to avoid spurious mismatch in paths containing trait vals that have
515
+ // not been rebound to accessors in the subclass we're in now.
516
+ // For example, for a lazy val mixed into a class, the lazy var's info
517
+ // will not refer to symbols created during our info transformer,
518
+ // so if its type depends on a val that is now implemented after the info transformer,
519
+ // we'll get a mismatch when assigning `rhs` to `lazyVarOf(getter)`.
520
+ // TODO: could we rebind more aggressively? consider overriding in type equality?
521
+ def castHack (tree : Tree , pt : Type ) = gen.mkAsInstanceOf(tree, pt)
522
+
513
523
class FieldsTransformer (unit : CompilationUnit ) extends TypingTransformer (unit) with CheckedAccessorTreeSynthesis {
514
524
protected def typedPos (pos : Position )(tree : Tree ): Tree = localTyper.typedPos(pos)(tree)
515
525
@@ -596,15 +606,6 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
596
606
597
607
// synth trees for accessors/fields and trait setters when they are mixed into a class
598
608
def fieldsAndAccessors (clazz : Symbol ): List [Tree ] = {
599
- // scala/scala-dev#219
600
- // Cast to avoid spurious mismatch in paths containing trait vals that have
601
- // not been rebound to accessors in the subclass we're in now.
602
- // For example, for a lazy val mixed into a class, the lazy var's info
603
- // will not refer to symbols created during our info transformer,
604
- // so if its type depends on a val that is now implemented after the info transformer,
605
- // we'll get a mismatch when assigning `rhs` to `lazyVarOf(getter)`.
606
- // TODO: could we rebind more aggressively? consider overriding in type equality?
607
- def cast (tree : Tree , pt : Type ) = gen.mkAsInstanceOf(tree, pt)
608
609
609
610
// Could be NoSymbol, which denotes an error, but it's refchecks' job to report it (this fallback is for robustness).
610
611
// This is the result of overriding a val with a def, so that no field is found in the subclass.
@@ -615,14 +616,14 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
615
616
// accessor created by newMatchingModuleAccessor for a static module that does need an accessor
616
617
// (because there's a matching member in a super class)
617
618
if (getter.asTerm.referenced.isModule)
618
- mkAccessor(getter)(cast (Select (This (clazz), getter.asTerm.referenced), getter.info.resultType))
619
+ mkAccessor(getter)(castHack (Select (This (clazz), getter.asTerm.referenced), getter.info.resultType))
619
620
else {
620
621
val fieldMemoization = fieldMemoizationIn(getter, clazz)
621
622
// TODO: drop getter for constant? (when we no longer care about producing identical bytecode?)
622
623
if (fieldMemoization.constantTyped) mkAccessor(getter)(gen.mkAttributedQualifier(fieldMemoization.tp))
623
624
else fieldAccess(getter) match {
624
625
case NoSymbol => EmptyTree
625
- case fieldSel => mkAccessor(getter)(cast (Select (This (clazz), fieldSel), getter.info.resultType))
626
+ case fieldSel => mkAccessor(getter)(castHack (Select (This (clazz), fieldSel), getter.info.resultType))
626
627
}
627
628
}
628
629
@@ -636,7 +637,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
636
637
else fieldAccess(setter) match {
637
638
case NoSymbol => EmptyTree
638
639
case fieldSel => afterOwnPhase { // the assign only type checks after our phase (assignment to val)
639
- mkAccessor(setter)(Assign (Select (This (clazz), fieldSel), cast (Ident (setter.firstParam), fieldSel.info)))
640
+ mkAccessor(setter)(Assign (Select (This (clazz), fieldSel), castHack (Ident (setter.firstParam), fieldSel.info)))
640
641
}
641
642
}
642
643
@@ -657,7 +658,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
657
658
val selectSuper = Select (Super (This (clazz), tpnme.EMPTY ), getter.name)
658
659
659
660
val lazyVar = lazyVarOf(getter)
660
- val rhs = cast (Apply (selectSuper, Nil ), lazyVar.info)
661
+ val rhs = castHack (Apply (selectSuper, Nil ), lazyVar.info)
661
662
662
663
synthAccessorInClass.expandLazyClassMember(lazyVar, getter, rhs)
663
664
}
@@ -708,7 +709,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor
708
709
val transformedRhs = atOwner(statSym)(transform(rhs))
709
710
710
711
if (rhs == EmptyTree ) mkAccessor(statSym)(EmptyTree )
711
- else if (currOwner.isTrait) mkAccessor(statSym)(transformedRhs)
712
+ else if (currOwner.isTrait) mkAccessor(statSym)(castHack( transformedRhs, statSym.info.resultType) )
712
713
else if (! currOwner.isClass) mkLazyLocalDef(vd.symbol, transformedRhs)
713
714
else {
714
715
// TODO: make `synthAccessorInClass` a field and update it in atOwner?
0 commit comments