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..b97974fe13eb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -981,6 +981,9 @@ 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 finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] = postProcess(tree, copied.withSpan(tree.span).withAttachmentsFrom(tree)) @@ -990,16 +993,16 @@ 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)) + else finalize(tree, new BackquotedIdent(name)(sourceFile(tree))) case tree: Ident if name == tree.name => tree - case _ => finalize(tree, untpd.Ident(name)(tree.source)) + 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)) + else finalize(tree, new SelectWithSig(qualifier, name, tree.sig)(sourceFile(tree))) case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree - case _ => finalize(tree, untpd.Select(qualifier, name)(tree.source)) + 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 +1010,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) => 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 _ => 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 _ => 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 _ => 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 _ => 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) => 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 => 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 _ => 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 _ => 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 _ => 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: 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 _ => 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: 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 _ => 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 _ => 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 _ => 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 _ => 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 _ => 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 - else finalize(tree, new JavaSeqLiteral(elems, elemtpt)) + 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)(tree.source)) + 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 _ => 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) => 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 _ => 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 _ => 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 _ => 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 _ => 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 _ => 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 _ => 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) => 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 _ => 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 _ => 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) => 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 _ => 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 _ => 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 _ => 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 _ => 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 => 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 _ => 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 _ => 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 _ => 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) => 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..0d5fb6d8a5d7 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,32 +120,56 @@ 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 => + 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: - transformed.withSpan(inlined.call.span) - case _ => transformed + tree.withSpan(inlinedAtSpan) } + case _ => tree } - def transformInline(tree: Inlined)(implicit ctx: Context): Tree = { - tpd.seq(transformSub(tree.bindings), transform(tree.expansion)(inlineContext(tree.call))) + + override def transform(tree: Tree)(implicit ctx: Context): Tree = { + val transformed = reposition(tree match { + 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)) + 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) + }) + assert(transformed.isInstanceOf[EmptyTree[_]] || transformed.isInstanceOf[EmptyValDef[_]] || transformed.source == curSource) + transformed } } - (new Reposition).transformInline(inlined) + (new Reposition).transform(inlined) } }