diff options
author | Martin Odersky <odersky@gmail.com> | 2014-03-10 22:06:13 +0100 |
---|---|---|
committer | Tobias Schlatter <tobias@meisch.ch> | 2014-03-20 20:25:05 +0100 |
commit | 3ba0931636a5d34ca2da9588f2952af709d41ace (patch) | |
tree | cc80be514102bca1203cc6a83a8fd62c7e0ae6c8 /src/dotty/tools/dotc | |
parent | ce466da9fd5b2601c91e351fd1d288099ec380b2 (diff) | |
download | dotty-3ba0931636a5d34ca2da9588f2952af709d41ace.tar.gz dotty-3ba0931636a5d34ca2da9588f2952af709d41ace.tar.bz2 dotty-3ba0931636a5d34ca2da9588f2952af709d41ace.zip |
New scheme for TypeTrees that refer to others
Adds a new scheme by which a TypeTree() can refer for its type to the symbol of some other type.
Applies the scheme to setter parameters, replacing the previous ad-hoc solution.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r-- | src/dotty/tools/dotc/ast/Desugar.scala | 40 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 26 |
4 files changed, 68 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 0c741a652..e8099f360 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -6,6 +6,7 @@ import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._ import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ +import util.Attachment import language.higherKinds import collection.mutable.ListBuffer import typer.ErrorReporting.InfoString @@ -21,6 +22,43 @@ object desugar { /** Info of a variable in a pattern: The named tree and its type */ private type VarInfo = (NameTree, Tree) +// ----- TypeTrees that refer to other tree's symbols ------------------- + + /** A marker tree used as the original for TypeTrees that get their type by taking + * the typeRef of some other tree's symbol. (currently unused) + */ + val TypeRefOfSym = new TypeTree(EmptyTree) + + /** A marker tree used as the original for TypeTrees that get their type by taking + * the result type of the info of some other tree's symbol. + */ + val InfoOfSym = new TypeTree(EmptyTree) + + /** Attachment key containing TypeTrees whose type is computed + * from the symbol in this type. These type trees have marker trees + * TypeRefOfSym or InfoOfSym as their originals. + */ + val References = new Attachment.Key[List[Tree]] + + /** Attachment key for TypeTrees marked with TypeRefOfSym or InfoOfSym + * which contains the symbol of the original tree from which this + * TypeTree is derived. + */ + val OriginalSymbol = new Attachment.Key[Symbol] + + /** A type tree that is marked to get its type by taking + * the typeRef of some other tree's symbol. Enters the type tree + * in the References attachment of the `original` tree as a side effect. + */ + def refTypeTree(original: Tree, marker: TypeTree): TypeTree = { + val result = TypeTree(marker) + val existing = original.attachmentOrElse(References, Nil) + original.putAttachment(References, result :: existing) + result + } + +// ----- Desugar methods ------------------------------------------------- + /** var x: Int = expr * ==> * def x: Int = expr @@ -35,7 +73,7 @@ object desugar { // val getter = ValDef(mods, name, tpt, rhs) withPos vdef.pos ? // right now vdef maps via expandedTree to a thicket which concerns itself. // I don't see a problem with that but if there is one we can avoid it by making a copy here. - val setterParam = makeSyntheticParameter(tpt = TypeTree()) + val setterParam = makeSyntheticParameter(tpt = refTypeTree(vdef, InfoOfSym)) val setterRhs = if (vdef.rhs.isEmpty) EmptyTree else unitLiteral val setter = cpy.DefDef(vdef, mods | Accessor, name.setterName, Nil, (setterParam :: Nil) :: Nil, diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 39da1dbae..ea396519a 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -84,7 +84,7 @@ trait Checking extends NoChecking { /** Check that (return) type of implicit definition is not empty */ override def checkImplicitTptNonEmpty(defTree: untpd.ValOrDefDef)(implicit ctx: Context): Unit = defTree.tpt match { - case TypeTree(original) if original.isEmpty => + case TypeTree(untpd.EmptyTree) => val resStr = if (defTree.isInstanceOf[untpd.DefDef]) "result " else "" ctx.error(i"${resStr}type of implicit definition needs to be given explicitly", defTree.pos) case _ => diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index c318ddf36..21b87aee4 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -173,6 +173,11 @@ class Namer { typer: Typer => enclosingClassNamed(mods.privateWithin, mods.pos) def record(sym: Symbol): Symbol = { + val refs = tree.attachmentOrElse(desugar.References, Nil) + if (refs.nonEmpty) { + tree.removeAttachment(desugar.References) + refs foreach (_.pushAttachment(desugar.OriginalSymbol, sym)) + } tree.pushAttachment(SymOfTree, sym) sym } @@ -516,10 +521,7 @@ class Namer { typer: Typer => * NoType if neither case holds. */ val inherited = - if ((sym is Param) && sym.owner.isSetter) // fill in type from getter result type - defContext(sym.owner) - .denotNamed(sym.owner.asTerm.name.setterToGetter).info.widenExpr - else if (sym.owner.isTerm) NoType + if (sym.owner.isTerm) NoType else { // TODO: Look only at member of supertype instead? lazy val schema = paramFn(WildcardType) @@ -578,7 +580,7 @@ class Namer { typer: Typer => val rhsCtx = ctx.fresh addMode Mode.InferringReturnType def rhsType = typedAheadExpr(mdef.rhs, rhsProto)(rhsCtx).tpe.widen.approximateUnion def lhsType = fullyDefinedType(rhsType, "right-hand side", mdef.pos) - inherited orElse lhsType + inherited orElse lhsType orElse WildcardType } paramFn(typedAheadType(mdef.tpt, pt).tpe) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index f961a4544..32e847757 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -635,11 +635,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = track("typedTypeTree") { - val original1 = typed(tree.original) - val ownType = - if (original1.isEmpty) { assert(isFullyDefined(pt, ForceDegree.none)); pt } - else original1.tpe - cpy.TypeTree(tree, original1) withType ownType + if (tree.original.isEmpty) { + def symbol = tree.attachment(desugar.OriginalSymbol) + // btw, no need to remove the attachment. The typed + // tree is different from the untyped one, so the + // untyped tree is no longer accessed after all + // accesses with typedTypeTree are done. + val ownType = tree.original match { + case untpd.EmptyTree => + assert(isFullyDefined(pt, ForceDegree.none)) + pt + case desugar.TypeRefOfSym => + symbol.typeRef + case desugar.InfoOfSym => + symbol.info.resultType + } + cpy.TypeTree(tree, untpd.EmptyTree).withType(ownType) + } + else { + val original1 = typed(tree.original) + cpy.TypeTree(tree, original1).withType(original1.tpe) + } } def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = track("typedSingletonTypeTree") { |