diff options
author | Martin Odersky <odersky@gmail.com> | 2013-08-29 14:44:49 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-08-29 14:44:49 +0200 |
commit | 28f8102d1b4e8c8fd2d2f1838b49e70844245a5f (patch) | |
tree | 066c90ced4254e96eb90cd13bc8b506b7ddc7e2e | |
parent | e47b840e7b3d4f77a32fe823dd2eaf703aff36b3 (diff) | |
download | dotty-28f8102d1b4e8c8fd2d2f1838b49e70844245a5f.tar.gz dotty-28f8102d1b4e8c8fd2d2f1838b49e70844245a5f.tar.bz2 dotty-28f8102d1b4e8c8fd2d2f1838b49e70844245a5f.zip |
Buf fixing of namer/typer interface.
Make sure that only expanded trees are passed to functions that require expanded trees.
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 33 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 139 | ||||
-rw-r--r-- | tests/pos/inferred.scala | 9 |
3 files changed, 105 insertions, 76 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 887970b67..97cc37cc3 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -62,7 +62,9 @@ class Namer { typer: Typer => /** A partial map from unexpanded member and pattern defs and to their expansions. * Populated during enterSyms, emptied during typer. */ - lazy val expandedTree = new mutable.HashMap[DefTree, Tree] + lazy val expandedTree = new mutable.HashMap[DefTree, Tree] { + override def default(tree: DefTree) = tree + } /** A map from expanded MemberDef, PatDef or Import trees to their symbols. * Populated during enterSyms, emptied at the point a typed tree @@ -91,9 +93,12 @@ class Namer { typer: Typer => val scope = newScope /** The symbol of the given expanded tree. */ - def symbolOfTree(tree: Tree)(implicit ctx: Context): Symbol = typedTree get tree match { - case Some(tree1) => tree1.denot.symbol - case _ => symOfTree(tree) + def symbolOfTree(tree: Tree)(implicit ctx: Context): Symbol = { + val xtree = expanded(tree) + typedTree get xtree match { + case Some(ttree) => ttree.denot.symbol + case _ => symOfTree(xtree) + } } /** The enclosing class with given name; error if none exists */ @@ -122,7 +127,7 @@ class Namer { typer: Typer => def privateWithinClass(mods: Modifiers) = enclosingClassNamed(mods.privateWithin, mods.pos) - def record(tree: Tree, sym: Symbol): Symbol = { + def record(sym: Symbol): Symbol = { symOfTree(tree) = sym sym } @@ -141,17 +146,17 @@ class Namer { typer: Typer => println(i"creating symbol for $tree") tree match { case tree: TypeDef if tree.isClassDef => - record(tree, ctx.newClassSymbol( + record(ctx.newClassSymbol( ctx.owner, tree.name, tree.mods.flags, adjustIfModule(new Completer(tree) withDecls newScope, tree), privateWithinClass(tree.mods), tree.pos, ctx.source.file)) case tree: MemberDef => - record(tree, ctx.newSymbol( + record(ctx.newSymbol( ctx.owner, tree.name, tree.mods.flags, adjustIfModule(new Completer(tree), tree), privateWithinClass(tree.mods), tree.pos)) - case imp: Import => - record(imp, ctx.newSymbol( + case tree: Import => + record(ctx.newSymbol( ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos)) case _ => NoSymbol @@ -193,6 +198,12 @@ class Namer { typer: Typer => expanded } + /** The expanded version of this tree, or tree itself if not expanded */ + def expanded(tree: Tree)(implicit ctx: Context): Tree = tree match { + case ddef: DefTree => expandedTree(ddef) + case _ => tree + } + /** A new context that summarizes an import statement */ def importContext(sym: Symbol, selectors: List[Tree])(implicit ctx: Context) = ctx.fresh.withImportInfo(new ImportInfo(sym, selectors)) @@ -328,8 +339,8 @@ class Namer { typer: Typer => } /** Typecheck tree during completion, and remember result in typedtree map */ - private def typedAheadImpl(tree: Tree, pt: Type)(implicit ctx: Context): tpd.Tree = - typedTree.getOrElseUpdate(tree, typer.typedExpanded(tree, pt)) + private def typedAheadImpl(tree: Tree, pt: Type)(implicit ctx: Context): tpd.Tree = + typedTree.getOrElseUpdate(expanded(tree), typer.typedUnadapted(tree, pt)) def typedAheadType(tree: Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = typedAheadImpl(tree, pt)(ctx retractMode Mode.PatternOrType addMode Mode.Type) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 32c7bbea4..dd07c921d 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -483,7 +483,7 @@ class Typer extends Namer with Applications with Implicits { def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context) = { val env1 = tree.env mapconserve (typed(_)) - val meth1 = typedExpanded(tree.meth) + val meth1 = typedUnadapted(tree.meth) val ownType = meth1.tpe.widen match { case mt: MethodType if !mt.isDependent => mt.toFunctionType @@ -767,72 +767,79 @@ class Typer extends Namer with Applications with Implicits { cpy.PackageDef(tree, pid1.asInstanceOf[RefTree], stats1) withType pkg.symRef } - def typedExpanded(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = { - val sym = symOfTree.remove(tree).getOrElse(NoSymbol) - sym.ensureCompleted() - def localContext = ctx.fresh.withOwner(sym) - typedTree remove tree match { - case Some(tree1) => tree1 - case none => tree match { - case tree: untpd.Ident => typedIdent(tree, pt) - case tree: untpd.Select => typedSelect(tree, pt) - case tree: untpd.This => typedThis(tree) - case tree: untpd.Super => typedSuper(tree) - case tree: untpd.Apply => typedApply(tree, pt) - case tree: untpd.TypeApply => typedTypeApply(tree, pt) - case tree: untpd.Literal => typedLiteral(tree) - case tree: untpd.New => typedNew(tree, pt) - case tree: untpd.Pair => typedPair(tree, pt) - case tree: untpd.Typed => typedTyped(tree, pt) - case tree: untpd.NamedArg => typedNamedArg(tree, pt) - case tree: untpd.Assign => typedAssign(tree, pt) - case tree: untpd.Block => typedBlock(tree, pt) - case tree: untpd.If => typedIf(tree, pt) - case tree: untpd.Function => typedFunction(tree, pt) - case tree: untpd.Closure => typedClosure(tree, pt) - case tree: untpd.Match => typedMatch(tree, pt) - case tree: untpd.Return => typedReturn(tree) - case tree: untpd.Try => typedTry(tree, pt) - case tree: untpd.Throw => typedThrow(tree) - case tree: untpd.SeqLiteral => typedSeqLiteral(tree, pt) - case tree: untpd.TypeTree => typedTypeTree(tree, pt) - case tree: untpd.SingletonTypeTree => typedSingletonTypeTree(tree) - case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt) - case tree: untpd.AndTypeTree => typedAndTypeTree(tree) - case tree: untpd.OrTypeTree => typedOrTypeTree(tree) - case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree) - case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree) - case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree) - case tree: untpd.Bind => typedBind(tree, pt) - case tree: untpd.Alternative => typedAlternative(tree, pt) - case tree: untpd.ValDef => - if (tree.isEmpty) tpd.EmptyValDef - else typedValDef(tree, sym)(localContext) - case tree: untpd.DefDef => - val typer1 = nestedTyper.remove(sym).get - typer1.typedDefDef(tree, sym)(localContext.withTyper(typer1)) - case tree: untpd.TypeDef => - if (tree.isClassDef) typedClassDef(tree, sym.asClass)(localContext) - else typedTypeDef(tree, sym)(localContext.withNewScope) - case tree: untpd.Import => typedImport(tree, sym) - case tree: untpd.PackageDef => typedPackageDef(tree) - case tree: untpd.Annotated => typedAnnotated(tree, pt) - case tree: untpd.TypedSplice => tree.tree - case untpd.PostfixOp(tree, nme.WILDCARD) => typed(tree, AnyFunctionProto) - case untpd.EmptyTree => tpd.EmptyTree - case _ => typed(desugar(tree), pt) - } - } - } + def typedUnadapted(initTree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = { + + val xtree = expanded(initTree) + typedTree remove xtree match { + case Some(ttree) => ttree + case none => + val sym = symOfTree.remove(xtree).getOrElse(NoSymbol) + sym.ensureCompleted() + def localContext = ctx.fresh.withOwner(sym) + + def typedNamed(tree: untpd.NameTree): Tree = tree match { + case tree: untpd.Ident => typedIdent(tree, pt) + case tree: untpd.Select => typedSelect(tree, pt) + case tree: untpd.SelectFromTypeTree => typedSelectFromTypeTree(tree, pt) + case tree: untpd.Bind => typedBind(tree, pt) + case tree: untpd.ValDef => + if (tree.isEmpty) tpd.EmptyValDef + else typedValDef(tree, sym)(localContext) + case tree: untpd.DefDef => + val typer1 = nestedTyper.remove(sym).get + typer1.typedDefDef(tree, sym)(localContext.withTyper(typer1)) + case tree: untpd.TypeDef => + if (tree.isClassDef) typedClassDef(tree, sym.asClass)(localContext) + else typedTypeDef(tree, sym)(localContext.withNewScope) + case _ => typedUnadapted(desugar(tree), pt) + } - def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ctx.traceIndented (i"typing $tree", show = true) { + def typedUnnamed(tree: untpd.Tree): Tree = tree match { + case tree: untpd.Apply => typedApply(tree, pt) + case tree: untpd.This => typedThis(tree) + case tree: untpd.Literal => typedLiteral(tree) + case tree: untpd.New => typedNew(tree, pt) + case tree: untpd.Pair => typedPair(tree, pt) + case tree: untpd.Typed => typedTyped(tree, pt) + case tree: untpd.NamedArg => typedNamedArg(tree, pt) + case tree: untpd.Assign => typedAssign(tree, pt) + case tree: untpd.Block => typedBlock(tree, pt) + case tree: untpd.If => typedIf(tree, pt) + case tree: untpd.Function => typedFunction(tree, pt) + case tree: untpd.Closure => typedClosure(tree, pt) + case tree: untpd.Match => typedMatch(tree, pt) + case tree: untpd.Return => typedReturn(tree) + case tree: untpd.Try => typedTry(tree, pt) + case tree: untpd.Throw => typedThrow(tree) + case tree: untpd.TypeApply => typedTypeApply(tree, pt) + case tree: untpd.Super => typedSuper(tree) + case tree: untpd.SeqLiteral => typedSeqLiteral(tree, pt) + case tree: untpd.TypeTree => typedTypeTree(tree, pt) + case tree: untpd.SingletonTypeTree => typedSingletonTypeTree(tree) + case tree: untpd.AndTypeTree => typedAndTypeTree(tree) + case tree: untpd.OrTypeTree => typedOrTypeTree(tree) + case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree) + case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree) + case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree) + case tree: untpd.Alternative => typedAlternative(tree, pt) + case tree: untpd.Import => typedImport(tree, sym) + case tree: untpd.PackageDef => typedPackageDef(tree) + case tree: untpd.Annotated => typedAnnotated(tree, pt) + case tree: untpd.TypedSplice => tree.tree + case untpd.PostfixOp(tree, nme.WILDCARD) => typed(tree, AnyFunctionProto) + case untpd.EmptyTree => tpd.EmptyTree + case _ => typedUnadapted(desugar(tree), pt) + } - def encodeName(tree: untpd.Tree) = tree match { - case tree: NameTree => tree.withName(tree.name.encode) - case _ => tree + xtree match { + case xtree: untpd.NameTree => typedNamed(xtree withName xtree.name.encode) + case xtree => typedUnnamed(xtree) + } } + } - val tree1 = typedExpanded(encodeName(tree), pt) + def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ctx.traceIndented (i"typing $tree", show = true) { + val tree1 = typedUnadapted(tree, pt) ctx.interpolateUndetVars(tree1.tpe.widen, tree1.pos) adapt(tree1, pt) } @@ -932,6 +939,8 @@ class Typer extends Namer with Applications with Implicits { */ def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", show = false) { + assert(pt.exists) + def methodStr = err.refStr(methPart(tree).tpe) def adaptOverloaded(ref: TermRef) = { @@ -973,7 +982,7 @@ class Typer extends Namer with Applications with Implicits { case wtp: ExprType => adapt(tree.withType(wtp.resultType), pt) case wtp: ImplicitMethodType => - val args = (wtp.paramNames, wtp.paramTypes).zipped(identity, identity) map { (pname, formal) => + val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) => val arg = inferImplicit(formal, EmptyTree, tree.pos.endPos) if (arg.isEmpty) ctx.error(i"no implicit argument of type $formal found for parameter $pname of $methodStr", tree.pos.endPos) @@ -991,7 +1000,7 @@ class Typer extends Namer with Applications with Implicits { i"""missing arguments for $methodStr |follow this method with `_' if you want to treat it as a partially applied function""".stripMargin) case _ => - if (conforms(tree.tpe, pt)) tree + if (typeConforms(tree.tpe, pt)) tree else if (ctx.mode is Mode.Pattern) tree // no subtype check for patterns else if (ctx.mode is Mode.Type) err.typeMismatch(tree, pt) else adaptToSubType(wtp) diff --git a/tests/pos/inferred.scala b/tests/pos/inferred.scala new file mode 100644 index 000000000..76f578a30 --- /dev/null +++ b/tests/pos/inferred.scala @@ -0,0 +1,9 @@ +object Inferred { + + def foo[T](x: T): T = x + + val x = foo(1) + + val y = foo("abc") + +} |