From 1300311067c2e3b21658bb3351b044d9e662103f Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 8 Feb 2019 17:09:32 +0100 Subject: [PATCH 1/3] Fix the source of inlined trees after Erasure To ensure that the sources change, the trees need to be copied with the new source rather than preserving it. --- compiler/src/dotty/tools/dotc/Driver.scala | 5 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 185 +++++++++--------- compiler/src/dotty/tools/dotc/ast/tpd.scala | 48 ++--- .../dotty/tools/dotc/core/SymbolLoaders.scala | 3 + .../src/dotty/tools/dotc/typer/Inliner.scala | 52 +++-- 5 files changed, 162 insertions(+), 131 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/Driver.scala b/compiler/src/dotty/tools/dotc/Driver.scala index 9170cfd0af55..5fbb6853752d 100644 --- a/compiler/src/dotty/tools/dotc/Driver.scala +++ b/compiler/src/dotty/tools/dotc/Driver.scala @@ -6,7 +6,7 @@ import dotty.tools.FatalError import config.CompilerCommand import core.Comments.{ContextDoc, ContextDocstrings} import core.Contexts.{Context, ContextBase} -import core.Mode +import core.{Mode, TypeError} import reporting._ import scala.util.control.NonFatal @@ -37,6 +37,9 @@ class Driver { case ex: FatalError => ctx.error(ex.getMessage) // signals that we should fail compilation. ctx.reporter + case ex: TypeError => + println(s"${ex.toMessage} while compiling ${fileNames.mkString(", ")}") + throw ex case ex: Throwable => println(s"$ex while compiling ${fileNames.mkString(", ")}") throw ex diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index d5cac688b835..26626d177e8f 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -981,6 +981,11 @@ object Trees { protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] + /** Soucre of the copied tree */ + protected def sourceFile(tree: Tree): SourceFile = tree.source + + protected def sameSourceFile(tree: Tree): Boolean = tree.source == sourceFile(tree) + protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = postProcess(tree, copied.withSpan(tree.span).withAttachmentsFrom(tree)) @@ -989,17 +994,17 @@ object Trees { def Ident(tree: Tree)(name: Name)(implicit ctx: Context): Ident = tree match { case tree: BackquotedIdent => - if (name == tree.name) tree - else finalize(tree, new BackquotedIdent(name)(tree.source)) - case tree: Ident if name == tree.name => tree - case _ => finalize(tree, untpd.Ident(name)(tree.source)) + if (name == tree.name && sameSourceFile(tree)) tree + else finalize(tree, new BackquotedIdent(name)(sourceFile(tree))) + case tree: Ident if name == tree.name && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Ident(name)(sourceFile(tree))) } def Select(tree: Tree)(qualifier: Tree, name: Name)(implicit ctx: Context): Select = tree match { case tree: SelectWithSig => if ((qualifier eq tree.qualifier) && (name == tree.name)) tree - else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(tree.source)) - case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)(tree.source)) + else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(sourceFile(tree))) + case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Select(qualifier, name)(sourceFile(tree))) } /** Copy Ident or Select trees */ def Ref(tree: RefTree)(name: Name)(implicit ctx: Context): RefTree = tree match { @@ -1007,170 +1012,170 @@ object Trees { case Select(qual, _) => Select(tree)(qual, name) } def This(tree: Tree)(qual: untpd.Ident)(implicit ctx: Context): This = tree match { - case tree: This if qual eq tree.qual => tree - case _ => finalize(tree, untpd.This(qual)(tree.source)) + case tree: This if (qual eq tree.qual) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.This(qual)(sourceFile(tree))) } def Super(tree: Tree)(qual: Tree, mix: untpd.Ident)(implicit ctx: Context): Super = tree match { - case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree - case _ => finalize(tree, untpd.Super(qual, mix)(tree.source)) + case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Super(qual, mix)(sourceFile(tree))) } def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { - case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.Apply(fun, args)(tree.source)) + case tree: Apply if (fun eq tree.fun) && (args eq tree.args) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Apply(fun, args)(sourceFile(tree))) } def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { - case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.TypeApply(fun, args)(tree.source)) + case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.TypeApply(fun, args)(sourceFile(tree))) } def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal = tree match { - case tree: Literal if const == tree.const => tree - case _ => finalize(tree, untpd.Literal(const)(tree.source)) + case tree: Literal if const == tree.const && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Literal(const)(sourceFile(tree))) } def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New = tree match { - case tree: New if tpt eq tree.tpt => tree - case _ => finalize(tree, untpd.New(tpt)(tree.source)) + case tree: New if (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.New(tpt)(sourceFile(tree))) } def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { - case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree - case tree => finalize(tree, untpd.Typed(expr, tpt)(tree.source)) + case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case tree => finalize(tree, untpd.Typed(expr, tpt)(sourceFile(tree))) //.ensuring(res => res.uniqueId != 1471, s"source = $tree, ${tree.uniqueId}") } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { - case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree - case _ => finalize(tree, untpd.NamedArg(name, arg)(tree.source)) + case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.NamedArg(name, arg)(sourceFile(tree))) } def Assign(tree: Tree)(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = tree match { - case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.Assign(lhs, rhs)(tree.source)) + case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Assign(lhs, rhs)(sourceFile(tree))) } def Block(tree: Tree)(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = tree match { - case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Block(stats, expr)(tree.source)) + case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Block(stats, expr)(sourceFile(tree))) } def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { - case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree - case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(tree.source)) - case _ => finalize(tree, untpd.If(cond, thenp, elsep)(tree.source)) + case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) && sameSourceFile(tree) => tree + case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(sourceFile(tree))) + case _ => finalize(tree, untpd.If(cond, thenp, elsep)(sourceFile(tree))) } def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = tree match { - case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) => tree - case _ => finalize(tree, untpd.Closure(env, meth, tpt)(tree.source)) + case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Closure(env, meth, tpt)(sourceFile(tree))) } def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { - case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree - case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(tree.source)) - case _ => finalize(tree, untpd.Match(selector, cases)(tree.source)) + case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) && sameSourceFile(tree) => tree + case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(sourceFile(tree))) + case _ => finalize(tree, untpd.Match(selector, cases)(sourceFile(tree))) } def CaseDef(tree: Tree)(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = tree match { - case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(tree.source)) + case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(sourceFile(tree))) } def Labeled(tree: Tree)(bind: Bind, expr: Tree)(implicit ctx: Context): Labeled = tree match { - case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) => tree - case _ => finalize(tree, untpd.Labeled(bind, expr)(tree.source)) + case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Labeled(bind, expr)(sourceFile(tree))) } def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return = tree match { - case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree - case _ => finalize(tree, untpd.Return(expr, from)(tree.source)) + case tree: Return if (expr eq tree.expr) && (from eq tree.from) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Return(expr, from)(sourceFile(tree))) } def WhileDo(tree: Tree)(cond: Tree, body: Tree)(implicit ctx: Context): WhileDo = tree match { - case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.WhileDo(cond, body)(tree.source)) + case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.WhileDo(cond, body)(sourceFile(tree))) } def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match { - case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree - case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(tree.source)) + case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(sourceFile(tree))) } def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = tree match { case tree: JavaSeqLiteral => - if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt)) tree + if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt) && sameSourceFile(tree)) tree else finalize(tree, new JavaSeqLiteral(elems, elemtpt)) - case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree - case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(tree.source)) + case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(sourceFile(tree))) } def Inlined(tree: Tree)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined = tree match { - case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree - case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(tree.source)) + case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(sourceFile(tree))) } def SingletonTypeTree(tree: Tree)(ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { - case tree: SingletonTypeTree if ref eq tree.ref => tree - case _ => finalize(tree, untpd.SingletonTypeTree(ref)(tree.source)) + case tree: SingletonTypeTree if (ref eq tree.ref) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.SingletonTypeTree(ref)(sourceFile(tree))) } def AndTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { - case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.AndTypeTree(left, right)(tree.source)) + case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.AndTypeTree(left, right)(sourceFile(tree))) } def OrTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { - case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree - case _ => finalize(tree, untpd.OrTypeTree(left, right)(tree.source)) + case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.OrTypeTree(left, right)(sourceFile(tree))) } def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { - case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree - case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(tree.source)) + case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(sourceFile(tree))) } def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { - case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree - case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(tree.source)) + case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(sourceFile(tree))) } def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = tree match { - case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(tree.source)) + case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(sourceFile(tree))) } def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match { - case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree - case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(tree.source)) + case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(sourceFile(tree))) } def ByNameTypeTree(tree: Tree)(result: Tree)(implicit ctx: Context): ByNameTypeTree = tree match { - case tree: ByNameTypeTree if result eq tree.result => tree - case _ => finalize(tree, untpd.ByNameTypeTree(result)(tree.source)) + case tree: ByNameTypeTree if (result eq tree.result) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.ByNameTypeTree(result)(sourceFile(tree))) } def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { - case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree - case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(tree.source)) + case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(sourceFile(tree))) } def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { - case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree - case _ => finalize(tree, untpd.Bind(name, body)(tree.source)) + case tree: Bind if (name eq tree.name) && (body eq tree.body) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Bind(name, body)(sourceFile(tree))) } def Alternative(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Alternative = tree match { - case tree: Alternative if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Alternative(trees)(tree.source)) + case tree: Alternative if (trees eq tree.trees) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Alternative(trees)(sourceFile(tree))) } def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = tree match { - case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree - case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(tree.source)) + case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(sourceFile(tree))) } def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match { - case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(tree.source)) + case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(sourceFile(tree))) } def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match { - case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree - case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(tree.source)) + case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(sourceFile(tree))) } def TypeDef(tree: Tree)(name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = tree match { - case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree - case _ => finalize(tree, untpd.TypeDef(name, rhs)(tree.source)) + case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.TypeDef(name, rhs)(sourceFile(tree))) } def Template(tree: Tree)(constr: DefDef, parents: List[Tree], derived: List[untpd.Tree], self: ValDef, body: LazyTreeList)(implicit ctx: Context): Template = tree match { - case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) => tree - case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(tree.source)) + case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) && sameSourceFile(tree) => tree + case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(sourceFile(tree))) } def Import(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { - case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree - case _ => finalize(tree, untpd.Import(impliedOnly, expr, selectors)(tree.source)) + case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Import(impliedOnly, expr, selectors)(sourceFile(tree))) } def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { - case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree - case _ => finalize(tree, untpd.PackageDef(pid, stats)(tree.source)) + case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.PackageDef(pid, stats)(sourceFile(tree))) } def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = tree match { - case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree - case _ => finalize(tree, untpd.Annotated(arg, annot)(tree.source)) + case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Annotated(arg, annot)(sourceFile(tree))) } def Thicket(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Thicket = tree match { - case tree: Thicket if trees eq tree.trees => tree - case _ => finalize(tree, untpd.Thicket(trees)(tree.source)) + case tree: Thicket if (trees eq tree.trees) && sameSourceFile(tree) => tree + case _ => finalize(tree, untpd.Thicket(trees)(sourceFile(tree))) } // Copier methods with default arguments; these demand that the original tree diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 514377802e57..3db2d7cedb94 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -524,8 +524,10 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[Type] = copied.withTypeUnchecked(tree.tpe) + protected val untpdCpy = untpd.cpy + override def Select(tree: Tree)(qualifier: Tree, name: Name)(implicit ctx: Context): Select = { - val tree1 = untpd.cpy.Select(tree)(qualifier, name) + val tree1 = untpdCpy.Select(tree)(qualifier, name) tree match { case tree: Select if qualifier.tpe eq tree.qualifier.tpe => tree1.withTypeUnchecked(tree.tpe) @@ -539,7 +541,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = { - val tree1 = untpd.cpy.Apply(tree)(fun, args) + val tree1 = untpdCpy.Apply(tree)(fun, args) tree match { case tree: Apply if (fun.tpe eq tree.fun.tpe) && sameTypes(args, tree.args) => @@ -549,7 +551,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = { - val tree1 = untpd.cpy.TypeApply(tree)(fun, args) + val tree1 = untpdCpy.TypeApply(tree)(fun, args) tree match { case tree: TypeApply if (fun.tpe eq tree.fun.tpe) && sameTypes(args, tree.args) => @@ -559,22 +561,22 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal = - ta.assignType(untpd.cpy.Literal(tree)(const)) + ta.assignType(untpdCpy.Literal(tree)(const)) override def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New = - ta.assignType(untpd.cpy.New(tree)(tpt), tpt) + ta.assignType(untpdCpy.New(tree)(tpt), tpt) override def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = - ta.assignType(untpd.cpy.Typed(tree)(expr, tpt), tpt) + ta.assignType(untpdCpy.Typed(tree)(expr, tpt), tpt) override def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = - ta.assignType(untpd.cpy.NamedArg(tree)(name, arg), arg) + ta.assignType(untpdCpy.NamedArg(tree)(name, arg), arg) override def Assign(tree: Tree)(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = - ta.assignType(untpd.cpy.Assign(tree)(lhs, rhs)) + ta.assignType(untpdCpy.Assign(tree)(lhs, rhs)) override def Block(tree: Tree)(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = { - val tree1 = untpd.cpy.Block(tree)(stats, expr) + val tree1 = untpdCpy.Block(tree)(stats, expr) tree match { case tree: Block if expr.tpe eq tree.expr.tpe => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, stats, expr) @@ -582,7 +584,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = { - val tree1 = untpd.cpy.If(tree)(cond, thenp, elsep) + val tree1 = untpdCpy.If(tree)(cond, thenp, elsep) tree match { case tree: If if (thenp.tpe eq tree.thenp.tpe) && (elsep.tpe eq tree.elsep.tpe) => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, thenp, elsep) @@ -590,7 +592,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = { - val tree1 = untpd.cpy.Closure(tree)(env, meth, tpt) + val tree1 = untpdCpy.Closure(tree)(env, meth, tpt) tree match { case tree: Closure if sameTypes(env, tree.env) && (meth.tpe eq tree.meth.tpe) && (tpt.tpe eq tree.tpt.tpe) => tree1.withTypeUnchecked(tree.tpe) @@ -599,7 +601,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = { - val tree1 = untpd.cpy.Match(tree)(selector, cases) + val tree1 = untpdCpy.Match(tree)(selector, cases) tree match { case tree: Match if sameTypes(cases, tree.cases) => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, selector, cases) @@ -607,7 +609,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def CaseDef(tree: Tree)(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = { - val tree1 = untpd.cpy.CaseDef(tree)(pat, guard, body) + val tree1 = untpdCpy.CaseDef(tree)(pat, guard, body) tree match { case tree: CaseDef if body.tpe eq tree.body.tpe => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, pat, body) @@ -615,16 +617,16 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Labeled(tree: Tree)(bind: Bind, expr: Tree)(implicit ctx: Context): Labeled = - ta.assignType(untpd.cpy.Labeled(tree)(bind, expr)) + ta.assignType(untpdCpy.Labeled(tree)(bind, expr)) override def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return = - ta.assignType(untpd.cpy.Return(tree)(expr, from)) + ta.assignType(untpdCpy.Return(tree)(expr, from)) override def WhileDo(tree: Tree)(cond: Tree, body: Tree)(implicit ctx: Context): WhileDo = - ta.assignType(untpd.cpy.WhileDo(tree)(cond, body)) + ta.assignType(untpdCpy.WhileDo(tree)(cond, body)) override def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = { - val tree1 = untpd.cpy.Try(tree)(expr, cases, finalizer) + val tree1 = untpdCpy.Try(tree)(expr, cases, finalizer) tree match { case tree: Try if (expr.tpe eq tree.expr.tpe) && sameTypes(cases, tree.cases) => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, expr, cases) @@ -632,7 +634,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Inlined(tree: Tree)(call: Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined = { - val tree1 = untpd.cpy.Inlined(tree)(call, bindings, expansion) + val tree1 = untpdCpy.Inlined(tree)(call, bindings, expansion) tree match { case tree: Inlined if sameTypes(bindings, tree.bindings) && (expansion.tpe eq tree.expansion.tpe) => tree1.withTypeUnchecked(tree.tpe) @@ -641,7 +643,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = { - val tree1 = untpd.cpy.SeqLiteral(tree)(elems, elemtpt) + val tree1 = untpdCpy.SeqLiteral(tree)(elems, elemtpt) tree match { case tree: SeqLiteral if sameTypes(elems, tree.elems) && (elemtpt.tpe eq tree.elemtpt.tpe) => @@ -652,7 +654,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } override def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = { - val tree1 = untpd.cpy.Annotated(tree)(arg, annot) + val tree1 = untpdCpy.Annotated(tree)(arg, annot) tree match { case tree: Annotated if (arg.tpe eq tree.arg.tpe) && (annot eq tree.annot) => tree1.withTypeUnchecked(tree.tpe) case _ => ta.assignType(tree1, arg, annot) @@ -671,18 +673,18 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { class TimeTravellingTreeCopier extends TypedTreeCopier { override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = - ta.assignType(untpd.cpy.Apply(tree)(fun, args), fun, args) + ta.assignType(untpdCpy.Apply(tree)(fun, args), fun, args) // Note: Reassigning the original type if `fun` and `args` have the same types as before // does not work here: The computed type depends on the widened function type, not // the function type itself. A treetransform may keep the function type the // same but its widened type might change. override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = - ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args) + ta.assignType(untpdCpy.TypeApply(tree)(fun, args), fun, args) // Same remark as for Apply override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = - ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt) + ta.assignType(untpdCpy.Closure(tree)(env, meth, tpt), meth, tpt) override def Closure(tree: Closure)(env: List[Tree] = tree.env, meth: Tree = tree.meth, tpt: Tree = tree.tpt)(implicit ctx: Context): Closure = Closure(tree: Tree)(env, meth, tpt) diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 90106a393f54..c33248e6a59d 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -334,6 +334,9 @@ abstract class SymbolLoader extends LazyType { } catch { case ex: IOException => signalError(ex) + case NonFatal(ex: TypeError) => + println(s"exception caught when loading $root: ${ex.toMessage}") + throw ex case NonFatal(ex) => println(s"exception caught when loading $root: $ex") throw ex diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 72685aeadead..d3b127c168b9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -20,13 +20,11 @@ import SymDenotations.SymDenotation import Inferencing.fullyDefinedType import config.Printers.inlining import ErrorReporting.errorTree -import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet} +import dotty.tools.dotc.util.{SimpleIdentityMap, SimpleIdentitySet, SourceFile, SourcePosition} import collection.mutable import reporting.trace import util.Spans.Span -import util.SourcePosition -import ast.TreeInfo object Inliner { import tpd._ @@ -122,28 +120,48 @@ object Inliner { def dropInlined(inlined: Inlined)(implicit ctx: Context): Tree = { if (enclosingInlineds.nonEmpty) inlined // Remove in the outer most inlined call else { - val inlinedAtPos = inlined.call.sourcePos + val inlinedAtSpan = inlined.call.span val curSource = ctx.compilationUnit.source + // Tree copier that changes the source of all trees to `curSource` + val cpyWithNewSource = new TypedTreeCopier { + override protected def sourceFile(tree: tpd.Tree): SourceFile = curSource + override protected val untpdCpy: untpd.UntypedTreeCopier = new untpd.UntypedTreeCopier { + override protected def sourceFile(tree: untpd.Tree): SourceFile = curSource + } + } + /** Removes all Inlined trees, replacing them with blocks. * Repositions all trees directly inside an inlined expansion of a non empty call to the position of the call. * Any tree directly inside an empty call (inlined in the inlined code) retains their position. */ - class Reposition extends TreeMap { - override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match { - case tree: Inlined => transformInline(tree) - case _ => - val transformed = super.transform(tree) - enclosingInlineds match { - case call :: _ if call.symbol.source != curSource => - // Until we implement JSR-45, we cannot represent in output positions in other source files. - // So, reposition inlined code from other files with the call position: - transformed.withSpan(inlined.call.span) - case _ => transformed - } + class Reposition extends TreeMap(cpyWithNewSource) { + override def transform(tree: Tree)(implicit ctx: Context): Tree = { + val transformed = tree match { + case tree: Inlined => transformInline(tree) + case tree: Ident => cpy.Ident(tree)(tree.name) + case tree: This => cpy.This(tree)(tree.qual) + case tree: Literal => cpy.Literal(tree)(tree.const) + case tree: JavaSeqLiteral => cpy.SeqLiteral(tree)(tree.elems, tree.elemtpt)(ctx.withSource(curSource)) + case tree: TypeTree => tpd.TypeTree(tree.tpe)(ctx.withSource(curSource)).withSpan(tree.span) + case _ => super.transform(tree) + } + val transformed2 = enclosingInlineds match { + case call :: _ if call.symbol.source != curSource => + transformed match { + case _: EmptyTree[_] | _: EmptyValDef[_] => transformed + case _ => + // Until we implement JSR-45, we cannot represent in output positions in other source files. + // So, reposition inlined code from other files with the call position: + transformed.withSpan(inlinedAtSpan) + } + case _ => transformed + } + assert(transformed2.isInstanceOf[EmptyTree[_]] || transformed2.isInstanceOf[EmptyValDef[_]] || transformed2.source == curSource) + transformed2 } def transformInline(tree: Inlined)(implicit ctx: Context): Tree = { - tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call))) + tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call)))(ctx.withSource(curSource)) } } From 983eb87072d58edf7b3e10151eae08769555f29a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 12 Feb 2019 11:54:21 +0100 Subject: [PATCH 2/3] Avoid checking for sourcefile changes --- compiler/src/dotty/tools/dotc/ast/Trees.scala | 92 +++++++++---------- .../src/dotty/tools/dotc/typer/Inliner.scala | 44 +++++---- 2 files changed, 70 insertions(+), 66 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 26626d177e8f..b97974fe13eb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -984,8 +984,6 @@ object Trees { /** Soucre of the copied tree */ protected def sourceFile(tree: Tree): SourceFile = tree.source - protected def sameSourceFile(tree: Tree): Boolean = tree.source == sourceFile(tree) - protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = postProcess(tree, copied.withSpan(tree.span).withAttachmentsFrom(tree)) @@ -994,16 +992,16 @@ object Trees { def Ident(tree: Tree)(name: Name)(implicit ctx: Context): Ident = tree match { case tree: BackquotedIdent => - if (name == tree.name && sameSourceFile(tree)) tree + if (name == tree.name) tree else finalize(tree, new BackquotedIdent(name)(sourceFile(tree))) - case tree: Ident if name == tree.name && sameSourceFile(tree) => tree + case tree: Ident if name == tree.name => tree case _ => finalize(tree, untpd.Ident(name)(sourceFile(tree))) } def Select(tree: Tree)(qualifier: Tree, name: Name)(implicit ctx: Context): Select = tree match { case tree: SelectWithSig => if ((qualifier eq tree.qualifier) && (name == tree.name)) tree else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(sourceFile(tree))) - case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) && sameSourceFile(tree) => tree + case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree case _ => finalize(tree, untpd.Select(qualifier, name)(sourceFile(tree))) } /** Copy Ident or Select trees */ @@ -1012,169 +1010,169 @@ object Trees { case Select(qual, _) => Select(tree)(qual, name) } def This(tree: Tree)(qual: untpd.Ident)(implicit ctx: Context): This = tree match { - case tree: This if (qual eq tree.qual) && sameSourceFile(tree) => tree + case tree: This if (qual eq tree.qual) => tree case _ => finalize(tree, untpd.This(qual)(sourceFile(tree))) } def Super(tree: Tree)(qual: Tree, mix: untpd.Ident)(implicit ctx: Context): Super = tree match { - case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) && sameSourceFile(tree) => tree + case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree case _ => finalize(tree, untpd.Super(qual, mix)(sourceFile(tree))) } def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match { - case tree: Apply if (fun eq tree.fun) && (args eq tree.args) && sameSourceFile(tree) => tree + case tree: Apply if (fun eq tree.fun) && (args eq tree.args) => tree case _ => finalize(tree, untpd.Apply(fun, args)(sourceFile(tree))) } def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = tree match { - case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) && sameSourceFile(tree) => tree + case tree: TypeApply if (fun eq tree.fun) && (args eq tree.args) => tree case _ => finalize(tree, untpd.TypeApply(fun, args)(sourceFile(tree))) } def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal = tree match { - case tree: Literal if const == tree.const && sameSourceFile(tree) => tree + case tree: Literal if const == tree.const => tree case _ => finalize(tree, untpd.Literal(const)(sourceFile(tree))) } def New(tree: Tree)(tpt: Tree)(implicit ctx: Context): New = tree match { - case tree: New if (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case tree: New if (tpt eq tree.tpt) => tree case _ => finalize(tree, untpd.New(tpt)(sourceFile(tree))) } def Typed(tree: Tree)(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed = tree match { - case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case tree: Typed if (expr eq tree.expr) && (tpt eq tree.tpt) => tree case tree => finalize(tree, untpd.Typed(expr, tpt)(sourceFile(tree))) //.ensuring(res => res.uniqueId != 1471, s"source = $tree, ${tree.uniqueId}") } def NamedArg(tree: Tree)(name: Name, arg: Tree)(implicit ctx: Context): NamedArg = tree match { - case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) && sameSourceFile(tree) => tree + case tree: NamedArg if (name == tree.name) && (arg eq tree.arg) => tree case _ => finalize(tree, untpd.NamedArg(name, arg)(sourceFile(tree))) } def Assign(tree: Tree)(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign = tree match { - case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) && sameSourceFile(tree) => tree + case tree: Assign if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree case _ => finalize(tree, untpd.Assign(lhs, rhs)(sourceFile(tree))) } def Block(tree: Tree)(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = tree match { - case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) && sameSourceFile(tree) => tree + case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree case _ => finalize(tree, untpd.Block(stats, expr)(sourceFile(tree))) } def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { - case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) && sameSourceFile(tree) => tree + case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(sourceFile(tree))) case _ => finalize(tree, untpd.If(cond, thenp, elsep)(sourceFile(tree))) } def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = tree match { - case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) && sameSourceFile(tree) => tree + case tree: Closure if (env eq tree.env) && (meth eq tree.meth) && (tpt eq tree.tpt) => tree case _ => finalize(tree, untpd.Closure(env, meth, tpt)(sourceFile(tree))) } def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { - case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) && sameSourceFile(tree) => tree + case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree case tree: InlineMatch => finalize(tree, untpd.InlineMatch(selector, cases)(sourceFile(tree))) case _ => finalize(tree, untpd.Match(selector, cases)(sourceFile(tree))) } def CaseDef(tree: Tree)(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef = tree match { - case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) && sameSourceFile(tree) => tree + case tree: CaseDef if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree case _ => finalize(tree, untpd.CaseDef(pat, guard, body)(sourceFile(tree))) } def Labeled(tree: Tree)(bind: Bind, expr: Tree)(implicit ctx: Context): Labeled = tree match { - case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) && sameSourceFile(tree) => tree + case tree: Labeled if (bind eq tree.bind) && (expr eq tree.expr) => tree case _ => finalize(tree, untpd.Labeled(bind, expr)(sourceFile(tree))) } def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return = tree match { - case tree: Return if (expr eq tree.expr) && (from eq tree.from) && sameSourceFile(tree) => tree + case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree case _ => finalize(tree, untpd.Return(expr, from)(sourceFile(tree))) } def WhileDo(tree: Tree)(cond: Tree, body: Tree)(implicit ctx: Context): WhileDo = tree match { - case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) && sameSourceFile(tree) => tree + case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree case _ => finalize(tree, untpd.WhileDo(cond, body)(sourceFile(tree))) } def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match { - case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) && sameSourceFile(tree) => tree + case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree case _ => finalize(tree, untpd.Try(expr, cases, finalizer)(sourceFile(tree))) } def SeqLiteral(tree: Tree)(elems: List[Tree], elemtpt: Tree)(implicit ctx: Context): SeqLiteral = tree match { case tree: JavaSeqLiteral => - if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt) && sameSourceFile(tree)) tree - else finalize(tree, new JavaSeqLiteral(elems, elemtpt)) - case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) && sameSourceFile(tree) => tree + if ((elems eq tree.elems) && (elemtpt eq tree.elemtpt)) tree + else finalize(tree, untpd.JavaSeqLiteral(elems, elemtpt)) + case tree: SeqLiteral if (elems eq tree.elems) && (elemtpt eq tree.elemtpt) => tree case _ => finalize(tree, untpd.SeqLiteral(elems, elemtpt)(sourceFile(tree))) } def Inlined(tree: Tree)(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined = tree match { - case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) && sameSourceFile(tree) => tree + case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree case _ => finalize(tree, untpd.Inlined(call, bindings, expansion)(sourceFile(tree))) } def SingletonTypeTree(tree: Tree)(ref: Tree)(implicit ctx: Context): SingletonTypeTree = tree match { - case tree: SingletonTypeTree if (ref eq tree.ref) && sameSourceFile(tree) => tree + case tree: SingletonTypeTree if (ref eq tree.ref) => tree case _ => finalize(tree, untpd.SingletonTypeTree(ref)(sourceFile(tree))) } def AndTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = tree match { - case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) && sameSourceFile(tree) => tree + case tree: AndTypeTree if (left eq tree.left) && (right eq tree.right) => tree case _ => finalize(tree, untpd.AndTypeTree(left, right)(sourceFile(tree))) } def OrTypeTree(tree: Tree)(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree = tree match { - case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) && sameSourceFile(tree) => tree + case tree: OrTypeTree if (left eq tree.left) && (right eq tree.right) => tree case _ => finalize(tree, untpd.OrTypeTree(left, right)(sourceFile(tree))) } def RefinedTypeTree(tree: Tree)(tpt: Tree, refinements: List[Tree])(implicit ctx: Context): RefinedTypeTree = tree match { - case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) && sameSourceFile(tree) => tree + case tree: RefinedTypeTree if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree case _ => finalize(tree, untpd.RefinedTypeTree(tpt, refinements)(sourceFile(tree))) } def AppliedTypeTree(tree: Tree)(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree = tree match { - case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) && sameSourceFile(tree) => tree + case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args)(sourceFile(tree))) } def LambdaTypeTree(tree: Tree)(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): LambdaTypeTree = tree match { - case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) && sameSourceFile(tree) => tree + case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(sourceFile(tree))) } def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match { - case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) && sameSourceFile(tree) => tree + case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(sourceFile(tree))) } def ByNameTypeTree(tree: Tree)(result: Tree)(implicit ctx: Context): ByNameTypeTree = tree match { - case tree: ByNameTypeTree if (result eq tree.result) && sameSourceFile(tree) => tree + case tree: ByNameTypeTree if (result eq tree.result) => tree case _ => finalize(tree, untpd.ByNameTypeTree(result)(sourceFile(tree))) } def TypeBoundsTree(tree: Tree)(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree = tree match { - case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) && sameSourceFile(tree) => tree + case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi)(sourceFile(tree))) } def Bind(tree: Tree)(name: Name, body: Tree)(implicit ctx: Context): Bind = tree match { - case tree: Bind if (name eq tree.name) && (body eq tree.body) && sameSourceFile(tree) => tree + case tree: Bind if (name eq tree.name) && (body eq tree.body) => tree case _ => finalize(tree, untpd.Bind(name, body)(sourceFile(tree))) } def Alternative(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Alternative = tree match { - case tree: Alternative if (trees eq tree.trees) && sameSourceFile(tree) => tree + case tree: Alternative if (trees eq tree.trees) => tree case _ => finalize(tree, untpd.Alternative(trees)(sourceFile(tree))) } def UnApply(tree: Tree)(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = tree match { - case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) && sameSourceFile(tree) => tree + case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns)(sourceFile(tree))) } def ValDef(tree: Tree)(name: TermName, tpt: Tree, rhs: LazyTree)(implicit ctx: Context): ValDef = tree match { - case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) && sameSourceFile(tree) => tree + case tree: ValDef if (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree case _ => finalize(tree, untpd.ValDef(name, tpt, rhs)(sourceFile(tree))) } def DefDef(tree: Tree)(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: LazyTree)(implicit ctx: Context): DefDef = tree match { - case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) && sameSourceFile(tree) => tree + case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs)(sourceFile(tree))) } def TypeDef(tree: Tree)(name: TypeName, rhs: Tree)(implicit ctx: Context): TypeDef = tree match { - case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) && sameSourceFile(tree) => tree + case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree case _ => finalize(tree, untpd.TypeDef(name, rhs)(sourceFile(tree))) } def Template(tree: Tree)(constr: DefDef, parents: List[Tree], derived: List[untpd.Tree], self: ValDef, body: LazyTreeList)(implicit ctx: Context): Template = tree match { - case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) && sameSourceFile(tree) => tree + case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (derived eq tree.derived) && (self eq tree.self) && (body eq tree.unforcedBody) => tree case tree => finalize(tree, untpd.Template(constr, parents, derived, self, body)(sourceFile(tree))) } def Import(tree: Tree)(impliedOnly: Boolean, expr: Tree, selectors: List[untpd.Tree])(implicit ctx: Context): Import = tree match { - case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) && sameSourceFile(tree) => tree + case tree: Import if (impliedOnly == tree.impliedOnly) && (expr eq tree.expr) && (selectors eq tree.selectors) => tree case _ => finalize(tree, untpd.Import(impliedOnly, expr, selectors)(sourceFile(tree))) } def PackageDef(tree: Tree)(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef = tree match { - case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) && sameSourceFile(tree) => tree + case tree: PackageDef if (pid eq tree.pid) && (stats eq tree.stats) => tree case _ => finalize(tree, untpd.PackageDef(pid, stats)(sourceFile(tree))) } def Annotated(tree: Tree)(arg: Tree, annot: Tree)(implicit ctx: Context): Annotated = tree match { - case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) && sameSourceFile(tree) => tree + case tree: Annotated if (arg eq tree.arg) && (annot eq tree.annot) => tree case _ => finalize(tree, untpd.Annotated(arg, annot)(sourceFile(tree))) } def Thicket(tree: Tree)(trees: List[Tree])(implicit ctx: Context): Thicket = tree match { - case tree: Thicket if (trees eq tree.trees) && sameSourceFile(tree) => tree + case tree: Thicket if (trees eq tree.trees) => tree case _ => finalize(tree, untpd.Thicket(trees)(sourceFile(tree))) } diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d3b127c168b9..26cba4766035 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -136,29 +136,35 @@ object Inliner { * Any tree directly inside an empty call (inlined in the inlined code) retains their position. */ class Reposition extends TreeMap(cpyWithNewSource) { + def finalize(tree: Tree, copied: untpd.Tree) = + copied.withSpan(tree.span).withAttachmentsFrom(tree).withTypeUnchecked(tree.tpe) + + def reposition(tree: Tree)(implicit ctx: Context): Tree = enclosingInlineds match { + case call :: _ if call.symbol.source != curSource => + tree match { + case _: EmptyTree[_] | _: EmptyValDef[_] => tree + case _ => + // Until we implement JSR-45, we cannot represent in output positions in other source files. + // So, reposition inlined code from other files with the call position: + tree.withSpan(inlinedAtSpan) + } + case _ => tree + } + override def transform(tree: Tree)(implicit ctx: Context): Tree = { - val transformed = tree match { + val transformed = reposition(tree match { case tree: Inlined => transformInline(tree) - case tree: Ident => cpy.Ident(tree)(tree.name) - case tree: This => cpy.This(tree)(tree.qual) - case tree: Literal => cpy.Literal(tree)(tree.const) - case tree: JavaSeqLiteral => cpy.SeqLiteral(tree)(tree.elems, tree.elemtpt)(ctx.withSource(curSource)) + case tree: Ident => finalize(tree, untpd.Ident(tree.name)(curSource)) + case tree: Literal => finalize(tree, untpd.Literal(tree.const)(curSource)) + case tree: This => finalize(tree, untpd.This(tree.qual)(curSource)) + case tree: JavaSeqLiteral => finalize(tree, untpd.JavaSeqLiteral(tree.elems, tree.elemtpt)(curSource)) + case tree: SeqLiteral => finalize(tree, untpd.SeqLiteral(tree.elems, tree.elemtpt)(curSource)) case tree: TypeTree => tpd.TypeTree(tree.tpe)(ctx.withSource(curSource)).withSpan(tree.span) + case tree: Bind => finalize(tree, untpd.Bind(tree.name, tree.body)(curSource)) case _ => super.transform(tree) - } - val transformed2 = enclosingInlineds match { - case call :: _ if call.symbol.source != curSource => - transformed match { - case _: EmptyTree[_] | _: EmptyValDef[_] => transformed - case _ => - // Until we implement JSR-45, we cannot represent in output positions in other source files. - // So, reposition inlined code from other files with the call position: - transformed.withSpan(inlinedAtSpan) - } - case _ => transformed - } - assert(transformed2.isInstanceOf[EmptyTree[_]] || transformed2.isInstanceOf[EmptyValDef[_]] || transformed2.source == curSource) - transformed2 + }) + assert(transformed.isInstanceOf[EmptyTree[_]] || transformed.isInstanceOf[EmptyValDef[_]] || transformed.source == curSource) + transformed } def transformInline(tree: Inlined)(implicit ctx: Context): Tree = { tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call)))(ctx.withSource(curSource)) From ec208695a8ec9989b5d3788ba8ecfb9f9f76e969 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 12 Feb 2019 12:02:50 +0100 Subject: [PATCH 3/3] Remove redundant abstraction --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 26cba4766035..0d5fb6d8a5d7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -153,7 +153,8 @@ object Inliner { override def transform(tree: Tree)(implicit ctx: Context): Tree = { val transformed = reposition(tree match { - case tree: Inlined => transformInline(tree) + case tree: Inlined => + tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call)))(ctx.withSource(curSource)) : Tree case tree: Ident => finalize(tree, untpd.Ident(tree.name)(curSource)) case tree: Literal => finalize(tree, untpd.Literal(tree.const)(curSource)) case tree: This => finalize(tree, untpd.This(tree.qual)(curSource)) @@ -166,12 +167,9 @@ object Inliner { assert(transformed.isInstanceOf[EmptyTree[_]] || transformed.isInstanceOf[EmptyValDef[_]] || transformed.source == curSource) transformed } - def transformInline(tree: Inlined)(implicit ctx: Context): Tree = { - tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call)))(ctx.withSource(curSource)) - } } - (new Reposition).transformInline(inlined) + (new Reposition).transform(inlined) } }