diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e27f540a7d..e09a509839 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -876,8 +876,9 @@ trait Typers extends Modes with Adaptations with Tags { case SilentResultValue(result) => result case _ => - debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original)) - val tree1 = typed(resetAllAttrs(original), mode, WildcardType) + val resetTree = resetLocalAttrs(original) + debuglog(s"fallback on implicits: ${tree}/$resetTree") + val tree1 = typed(resetTree, mode, WildcardType) // Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that // we pass `EmptyTree` as the `original`. intended? added in 2009 (53d98e7d42) by martin. tree1.tpe = pluginsTyped(tree1.tpe, this, tree1, mode, pt) @@ -3268,6 +3269,28 @@ trait Typers extends Modes with Adaptations with Tags { // calls to the default getters. Example: // foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a)) checkNotMacro() + + // SI-8111 transformNamedApplication eagerly shuffles around the application to preserve + // evaluation order. During this process, it calls `changeOwner` on symbols that + // are transplanted underneath synthetic temporary vals. + // + // Here, we keep track of the symbols owned by `context.owner` to enable us to + // rollback, so that we don't end up with "orphaned" symbols. + // + // TODO: Find a better way! + // + // Note that duplicating trees would not be enough to fix this problem, we would also need to + // clone local symbols in the duplicated tree to truly isolate things (in the spirit of BodyDuplicator), + // or, better yet, disentangle the logic in `transformNamedApplication` so that we could + // determine whether names/defaults is viable *before* transforming trees. + def ownerOf(sym: Symbol) = if (sym == null || sym == NoSymbol) NoSymbol else sym.owner + val symsOwnedByContextOwner = tree.collect { + case t @ (_: DefTree | _: Function) if ownerOf(t.symbol) == context.owner => t.symbol + } + def rollbackNamesDefaultsOwnerChanges() { + symsOwnedByContextOwner foreach (_.owner = context.owner) + } + val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x) if (fun1.isErroneous) duplErrTree else { @@ -3296,6 +3319,7 @@ trait Typers extends Modes with Adaptations with Tags { if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt) } else { + rollbackNamesDefaultsOwnerChanges() tryTupleApply getOrElse duplErrorTree(NotEnoughArgsError(tree, fun, missing)) } } @@ -3825,7 +3849,7 @@ trait Typers extends Modes with Adaptations with Tags { val normalizeLocals = new TypeMap { def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, args) => - if (sym.isAliasType && containsLocal(tp)) apply(tp.dealias) + if (sym.isAliasType && containsLocal(tp) && (tp.dealias ne tp)) apply(tp.dealias) else { if (pre.isVolatile) InferTypeWithVolatileTypeSelectionError(tree, pre) @@ -3998,9 +4022,14 @@ trait Typers extends Modes with Adaptations with Tags { def typedNamedApply(orig: Tree, fun: Tree, args: List[Tree], mode: Int, pt: Type): Tree = { def argToBinding(arg: Tree): Tree = arg match { - case AssignOrNamedArg(Ident(name), rhs) => gen.mkTuple(List(CODE.LIT(name.toString), rhs)) - case _ => gen.mkTuple(List(CODE.LIT(""), arg)) + case AssignOrNamedArg(i @ Ident(name), rhs) => + atPos(i.pos.withEnd(rhs.pos.endOrPoint)) { + gen.mkTuple(List(atPos(i.pos)(CODE.LIT(name.toString)), rhs)) + } + case _ => + gen.mkTuple(List(CODE.LIT(""), arg)) } + val t = treeCopy.Apply(orig, fun, args map argToBinding) wrapErrors(t, _.typed(t, mode, pt)) } @@ -4060,7 +4089,10 @@ trait Typers extends Modes with Adaptations with Tags { case Some((opName, treeInfo.Applied(_, targs, _))) => val fun = gen.mkTypeApply(Select(qual, opName), targs) if (opName == nme.updateDynamic) suppressMacroExpansion(fun) // SI-7617 - atPos(qual.pos)(Apply(fun, Literal(Constant(name.decode)) :: Nil)) + val nameStringLit = atPos(treeSelection.pos.withStart(treeSelection.pos.point).makeTransparent) { + Literal(Constant(name.decode)) + } + atPos(qual.pos)(Apply(fun, List(nameStringLit))) case _ => setError(tree) } @@ -4264,7 +4296,9 @@ trait Typers extends Modes with Adaptations with Tags { } else if(dyna.isDynamicallyUpdatable(lhs1)) { val rhs1 = typed(rhs, EXPRmode | BYVALmode, WildcardType) - val t = Apply(lhs1, List(rhs1)) + val t = atPos(lhs1.pos.withEnd(rhs1.pos.endOrPoint)) { + Apply(lhs1, List(rhs1)) + } dyna.wrapErrors(t, _.typed1(t, mode, pt)) } else fail() |