diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-11-17 17:57:13 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2016-11-21 22:12:07 +1000 |
commit | dde82ae61685698e66cb260ed1d66a0ba1b3c2da (patch) | |
tree | 6475a0ccc4fd5c8aa271c76bc0c6140f15d019dc /src | |
parent | 73678d4dafe250f0b38df2e953787af26b1a4ee3 (diff) | |
download | scala-dde82ae61685698e66cb260ed1d66a0ba1b3c2da.tar.gz scala-dde82ae61685698e66cb260ed1d66a0ba1b3c2da.tar.bz2 scala-dde82ae61685698e66cb260ed1d66a0ba1b3c2da.zip |
Fix more compiler crashes with fields, refinement types
In the same manner as scala/scala-dev#219, the placement of the fields
phase after uncurry is presenting some challenges in keeping our trees
type correct.
This commit whacks a few more moles by adding a casts in the body of
synthetic methods.
Fixes scala/scala-dev#268
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Fields.scala | 29 |
2 files changed, 16 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala b/src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala index a1923ead21..a0bba46398 100644 --- a/src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala +++ b/src/compiler/scala/tools/nsc/transform/AccessorSynthesis.scala @@ -332,7 +332,7 @@ trait AccessorSynthesis extends Transform with ast.TreeDSL { val isUnit = isUnitGetter(lazyAccessor) val selectVar = if (isUnit) UNIT else Select(thisRef, lazyVar) - val storeRes = if (isUnit) rhsAtSlowDef else Assign(selectVar, rhsAtSlowDef) + val storeRes = if (isUnit) rhsAtSlowDef else Assign(selectVar, fields.castHack(rhsAtSlowDef, lazyVar.info)) def needsInit = mkTest(lazyAccessor) val doInit = Block(List(storeRes), mkSetFlag(lazyAccessor)) diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index 0fe7a82b15..b09223110a 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -510,6 +510,16 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor def nonStaticModuleToMethod(module: Symbol): Unit = if (!module.isStatic) module setFlag METHOD | STABLE + // scala/scala-dev#219, scala/scala-dev#268 + // Cast to avoid spurious mismatch in paths containing trait vals that have + // not been rebound to accessors in the subclass we're in now. + // For example, for a lazy val mixed into a class, the lazy var's info + // will not refer to symbols created during our info transformer, + // so if its type depends on a val that is now implemented after the info transformer, + // we'll get a mismatch when assigning `rhs` to `lazyVarOf(getter)`. + // TODO: could we rebind more aggressively? consider overriding in type equality? + def castHack(tree: Tree, pt: Type) = gen.mkAsInstanceOf(tree, pt) + class FieldsTransformer(unit: CompilationUnit) extends TypingTransformer(unit) with CheckedAccessorTreeSynthesis { protected def typedPos(pos: Position)(tree: Tree): Tree = localTyper.typedPos(pos)(tree) @@ -596,15 +606,6 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor // synth trees for accessors/fields and trait setters when they are mixed into a class def fieldsAndAccessors(clazz: Symbol): List[Tree] = { - // scala/scala-dev#219 - // Cast to avoid spurious mismatch in paths containing trait vals that have - // not been rebound to accessors in the subclass we're in now. - // For example, for a lazy val mixed into a class, the lazy var's info - // will not refer to symbols created during our info transformer, - // so if its type depends on a val that is now implemented after the info transformer, - // we'll get a mismatch when assigning `rhs` to `lazyVarOf(getter)`. - // TODO: could we rebind more aggressively? consider overriding in type equality? - def cast(tree: Tree, pt: Type) = gen.mkAsInstanceOf(tree, pt) // Could be NoSymbol, which denotes an error, but it's refchecks' job to report it (this fallback is for robustness). // 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 // accessor created by newMatchingModuleAccessor for a static module that does need an accessor // (because there's a matching member in a super class) if (getter.asTerm.referenced.isModule) - mkAccessor(getter)(cast(Select(This(clazz), getter.asTerm.referenced), getter.info.resultType)) + mkAccessor(getter)(castHack(Select(This(clazz), getter.asTerm.referenced), getter.info.resultType)) else { val fieldMemoization = fieldMemoizationIn(getter, clazz) // TODO: drop getter for constant? (when we no longer care about producing identical bytecode?) if (fieldMemoization.constantTyped) mkAccessor(getter)(gen.mkAttributedQualifier(fieldMemoization.tp)) else fieldAccess(getter) match { case NoSymbol => EmptyTree - case fieldSel => mkAccessor(getter)(cast(Select(This(clazz), fieldSel), getter.info.resultType)) + case fieldSel => mkAccessor(getter)(castHack(Select(This(clazz), fieldSel), getter.info.resultType)) } } @@ -636,7 +637,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor else fieldAccess(setter) match { case NoSymbol => EmptyTree case fieldSel => afterOwnPhase { // the assign only type checks after our phase (assignment to val) - mkAccessor(setter)(Assign(Select(This(clazz), fieldSel), cast(Ident(setter.firstParam), fieldSel.info))) + mkAccessor(setter)(Assign(Select(This(clazz), fieldSel), castHack(Ident(setter.firstParam), fieldSel.info))) } } @@ -657,7 +658,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val selectSuper = Select(Super(This(clazz), tpnme.EMPTY), getter.name) val lazyVar = lazyVarOf(getter) - val rhs = cast(Apply(selectSuper, Nil), lazyVar.info) + val rhs = castHack(Apply(selectSuper, Nil), lazyVar.info) synthAccessorInClass.expandLazyClassMember(lazyVar, getter, rhs) } @@ -708,7 +709,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val transformedRhs = atOwner(statSym)(transform(rhs)) if (rhs == EmptyTree) mkAccessor(statSym)(EmptyTree) - else if (currOwner.isTrait) mkAccessor(statSym)(transformedRhs) + else if (currOwner.isTrait) mkAccessor(statSym)(castHack(transformedRhs, statSym.info.resultType)) else if (!currOwner.isClass) mkLazyLocalDef(vd.symbol, transformedRhs) else { // TODO: make `synthAccessorInClass` a field and update it in atOwner? |