aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala172
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala44
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala34
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala19
6 files changed, 195 insertions, 77 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 4a635d259..ea9e7566a 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -6,9 +6,9 @@ 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 config.Printers._
import typer.ErrorReporting.InfoString
import typer.Mode
@@ -22,34 +22,64 @@ 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 -------------------
+// ----- DerivedTypeTrees -----------------------------------
- /** 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]]
+ class SetterParamTree extends DerivedTypeTree {
+ def derivedType(sym: Symbol)(implicit ctx: Context) = sym.info.resultType
+ }
- /** 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]
+ class TypeRefTree extends DerivedTypeTree {
+ def derivedType(sym: Symbol)(implicit ctx: Context) = sym.typeRef
+ }
- /** A type tree that gets its type from some other tree's symbol. Enters the
- * type tree in the References attachment of the `from` tree as a side effect.
- */
- abstract class DerivedTypeTree(from: Tree) extends TypeTree(EmptyTree) {
- val existing = from.attachmentOrElse(References, Nil)
- from.putAttachment(References, this :: existing)
+ class DerivedFromParamTree extends DerivedTypeTree {
- /** The method that computes the type of this tree */
- def derivedType(originalSym: Symbol)(implicit ctx: Context): Type
+ /** Make sure that for all enclosing module classes their companion lasses
+ * are completed. Reason: We need the constructor of such companion classes to
+ * be completed so that OriginalSymbol attachments are pushed to DerivedTypeTrees
+ * in appy/unapply methods.
+ */
+ override def ensureCompletions(implicit ctx: Context) =
+ if (!(ctx.owner is Package))
+ if (ctx.owner is ModuleClass) ctx.owner.linkedClass.ensureCompleted()
+ else ensureCompletions(ctx.outer)
+
+ /** Return info of original symbol, where all references to siblings of the
+ * original symbol (i.e. sibling and original symbol have the same owner)
+ * are rewired to same-named parameters or accessors in the scope enclosing
+ * the current scope. The current scope is the scope owned by the defined symbol
+ * itself, that's why we have to look one scope further out. If the resulting
+ * type is an alias type, dealias it. This is necessary because the
+ * accessor of a type parameter is a private type alias that cannot be accessed
+ * from subclasses.
+ */
+ def derivedType(sym: Symbol)(implicit ctx: Context) = {
+ val relocate = new TypeMap {
+ val originalOwner = sym.owner
+ def apply(tp: Type) = tp match {
+ case tp: NamedType if tp.symbol.owner eq originalOwner =>
+ val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next
+ var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol
+ typr.println(s"rewiring ${tp.symbol} from ${originalOwner.showLocated} to ${local.showLocated}, current owner = ${ctx.owner.showLocated}")
+ if (local.exists) (defctx.owner.thisType select local).dealias
+ else throw new Error(s"no matching symbol for ${sym.showLocated} in ${defctx.owner} / ${defctx.effectiveScope}")
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ relocate(sym.info)
+ }
}
- class SetterParam(vdef: ValDef) extends DerivedTypeTree(vdef) {
- def derivedType(vsym: Symbol)(implicit ctx: Context) = vsym.info.resultType
- }
+ /** A type definition copied from `tdef` with a rhs typetree derived from it */
+ def derivedTypeParam(tdef: TypeDef) =
+ cpy.TypeDef(tdef, tdef.mods, tdef.name,
+ new DerivedFromParamTree() withPos tdef.rhs.pos watching tdef, tdef.tparams) // todo: copy type params
+
+ /** A value definition copied from `vdef` with a tpt typetree derived from it */
+ def derivedTermParam(vdef: ValDef) =
+ cpy.ValDef(vdef, vdef.mods, vdef.name,
+ new DerivedFromParamTree() withPos vdef.tpt.pos watching vdef, vdef.rhs)
// ----- Desugar methods -------------------------------------------------
@@ -67,7 +97,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 = new SetterParam(vdef))
+ val setterParam = makeSyntheticParameter(tpt = (new SetterParamTree).watching(vdef))
val setterRhs = if (vdef.rhs.isEmpty) EmptyTree else unitLiteral
val setter = cpy.DefDef(vdef,
mods | Accessor, name.setterName, Nil, (setterParam :: Nil) :: Nil,
@@ -183,6 +213,9 @@ object desugar {
private def toDefParam(tparam: TypeDef) =
cpy.TypeDef(tparam, Modifiers(Param), tparam.name, tparam.rhs, tparam.tparams)
+ private def toDefParam(vparam: ValDef) =
+ cpy.ValDef(vparam, Modifiers(Param | vparam.mods.flags & Implicit), vparam.name, vparam.tpt, vparam.rhs)
+
/** The expansion of a class definition. See inline comments for what is involved */
def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = {
val TypeDef(
@@ -198,31 +231,35 @@ object desugar {
// prefixed by type or val). `tparams` and `vparamss` are the type parameters that
// go in `constr`, the constructor after desugaring.
- val tparams = constr1.tparams map toDefParam
- val vparamss =
+ val constrTparams = constr1.tparams map toDefParam
+ val constrVparamss =
if (constr1.vparamss.isEmpty) { // ensure parameter list is non-empty
if (mods is Case)
ctx.error("case class needs to have at least one parameter list", cdef.pos)
ListOfNil
- } else
- constr1.vparamss.nestedMap(vparam => cpy.ValDef(vparam,
- Modifiers(Param | vparam.mods.flags & Implicit), vparam.name, vparam.tpt, vparam.rhs))
-
+ }
+ else constr1.vparamss.nestedMap(toDefParam)
val constr = cpy.DefDef(constr1,
- constr1.mods, constr1.name, tparams, vparamss, constr1.tpt, constr1.rhs)
+ constr1.mods, constr1.name, constrTparams, constrVparamss, constr1.tpt, constr1.rhs)
+
+ val derivedTparams = constrTparams map derivedTypeParam
+ val derivedVparamss = constrVparamss nestedMap derivedTermParam
+ val arity = constrVparamss.head.length
+
+ var classTycon: Tree = EmptyTree
// a reference to the class type, with all parameters given.
val classTypeRef/*: Tree*/ = {
// -language:keepUnions difference: classTypeRef needs type annotation, otherwise
// infers Ident | AppliedTypeTree, which
// renders the :\ in companions below untypable.
- val tycon = Ident(cdef.name) withPos cdef.pos.startPos
+ classTycon = (new TypeRefTree) withPos cdef.pos.startPos // watching is set at end of method
val tparams = impl.constr.tparams
- if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map refOfDef)
+ if (tparams.isEmpty) classTycon else AppliedTypeTree(classTycon, tparams map refOfDef)
}
// new C[Ts](paramss)
- lazy val creatorExpr = New(classTypeRef, vparamss nestedMap refOfDef)
+ lazy val creatorExpr = New(classTypeRef, constrVparamss nestedMap refOfDef)
// Methods to add to a case class C[..](p1: T1, ..., pN: Tn)(moreParams)
// def isDefined = true
@@ -233,23 +270,23 @@ object desugar {
// def copy(p1: T1 = p1, ..., pN: TN = pN)(moreParams) = new C[...](p1, ..., pN)(moreParams)
val caseClassMeths =
if (mods is Case) {
- val caseParams = vparamss.head.toArray
def syntheticProperty(name: TermName, rhs: Tree) =
DefDef(synthetic, name, Nil, Nil, TypeTree(), rhs)
val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
- val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(caseParams.length)))
+ val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(arity)))
def selectorName(n: Int) =
- if (caseParams.length == 1) nme.get else nme.selectorName(n)
- val productElemMeths = for (i <- 0 until caseParams.length) yield
+ if (arity == 1) nme.get else nme.selectorName(n)
+ val caseParams = constrVparamss.head.toArray
+ val productElemMeths = for (i <- 0 until arity) yield
syntheticProperty(selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
val copyMeths =
if (mods is Abstract) Nil
else {
- val copyFirstParams = vparamss.head.map(vparam =>
+ val copyFirstParams = derivedVparamss.head.map(vparam =>
cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, refOfDef(vparam)))
- val copyRestParamss = vparamss.tail.nestedMap(vparam =>
+ val copyRestParamss = derivedVparamss.tail.nestedMap(vparam =>
cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, EmptyTree))
- DefDef(synthetic, nme.copy, tparams, copyFirstParams :: copyRestParamss, TypeTree(), creatorExpr) :: Nil
+ DefDef(synthetic, nme.copy, derivedTparams, copyFirstParams :: copyRestParamss, TypeTree(), creatorExpr) :: Nil
}
copyMeths ::: isDefinedMeth :: productArityMeth :: productElemMeths.toList
}
@@ -258,15 +295,14 @@ object desugar {
def anyRef = ref(defn.AnyRefAlias.typeRef)
def productConstr(n: Int) = {
val tycon = ref(defn.ProductNClass(n).typeRef)
- val targs = vparamss.head map (_.tpt)
+ val targs = constrVparamss.head map (_.tpt)
AppliedTypeTree(tycon, targs)
}
// Case classes get a ProductN parent
var parents1 = parents
- val n = vparamss.head.length
- if ((mods is Case) && 2 <= n && n <= Definitions.MaxTupleArity)
- parents1 = parents1 :+ productConstr(n)
+ if ((mods is Case) && 2 <= arity && arity <= Definitions.MaxTupleArity)
+ parents1 = parents1 :+ productConstr(arity)
// The thicket which is the desugared version of the companion object
// synthetic object C extends parentTpt { defs }
@@ -288,17 +324,18 @@ object desugar {
val companions =
if (mods is Case) {
val parent =
- if (tparams.nonEmpty) anyRef
- else (vparamss :\ classTypeRef) ((vparams, restpe) => Function(vparams map (_.tpt), restpe))
+ if (constrTparams.nonEmpty) anyRef // todo: also use anyRef if constructor has a dependent method type (or rule that out)!
+ else (constrVparamss :\ classTypeRef) ((vparams, restpe) => Function(vparams map (_.tpt), restpe))
val applyMeths =
if (mods is Abstract) Nil
- else DefDef(
+ else
+ DefDef(
synthetic | (constr1.mods.flags & DefaultParameterized), nme.apply,
- tparams, vparamss, TypeTree(), creatorExpr) :: Nil
+ derivedTparams, derivedVparamss, TypeTree(), creatorExpr) :: Nil
val unapplyMeth = {
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
- val unapplyRHS = if (n == 0) Literal(Constant(true)) else Ident(unapplyParam.name)
- DefDef(synthetic, nme.unapply, tparams, (unapplyParam :: Nil) :: Nil, TypeTree(), unapplyRHS)
+ val unapplyRHS = if (arity == 0) Literal(Constant(true)) else Ident(unapplyParam.name)
+ DefDef(synthetic, nme.unapply, derivedTparams, (unapplyParam :: Nil) :: Nil, TypeTree(), unapplyRHS)
}
companionDefs(parent, applyMeths ::: unapplyMeth :: defaultGetters)
}
@@ -315,19 +352,40 @@ object desugar {
ctx.error("implicit classes may not be toplevel", cdef.pos)
if (mods is Case)
ctx.error("implicit classes may not case classes", cdef.pos)
+
+ // implicit wrapper is typechecked in same scope as constructor, so
+ // we can reuse the constructor parameters; no derived params are needed.
DefDef(Modifiers(Synthetic | Implicit), name.toTermName,
- tparams, vparamss, classTypeRef, creatorExpr) :: Nil
+ constrTparams, constrVparamss, classTypeRef, creatorExpr) :: Nil
}
else Nil
- val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt
- val self1 =
+ val self1 = {
+ val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt
if (self.isEmpty) self
else cpy.ValDef(self, self.mods | SelfName, self.name, selfType, self.rhs)
+ }
+
+ val cdef1 = {
+ val originalTparams = constr1.tparams.toIterator
+ val originalVparams = constr1.vparamss.toIterator.flatten
+ val tparamAccessors = derivedTparams map { tdef =>
+ cpy.TypeDef(tdef, originalTparams.next.mods, tdef.name, tdef.rhs, tdef.tparams)
+ }
+ val vparamAccessors = derivedVparamss.flatten map { vdef =>
+ cpy.ValDef(vdef, originalVparams.next.mods, vdef.name, vdef.tpt, vdef.rhs)
+ }
+ cpy.TypeDef(cdef, mods, name,
+ cpy.Template(impl, constr, parents1, self1,
+ tparamAccessors ::: vparamAccessors ::: body ::: caseClassMeths))
+ }
+
+ // install the watch on classTycon
+ classTycon match {
+ case tycon: DerivedTypeTree => tycon.watching(cdef1)
+ case _ =>
+ }
- val cdef1 = cpy.TypeDef(cdef, mods, name,
- cpy.Template(impl, constr, parents1, self1,
- constr1.tparams ::: constr1.vparamss.flatten ::: body ::: caseClassMeths))
flatTree(cdef1 :: companions ::: implicitWrappers)
}
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index 4e55fe868..44f340932 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -6,12 +6,13 @@ import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
import Denotations._, SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import Decorators._
+import util.Attachment
import language.higherKinds
import collection.mutable.ListBuffer
object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
-// ----- Tree cases that exist in untyped form only ------------------
+ // ----- Tree cases that exist in untyped form only ------------------
trait OpTree extends Tree {
def op: Name
@@ -61,6 +62,47 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
override def withName(name: Name)(implicit ctx: Context) = cpy.PolyTypeDef(this, mods, name.toTypeName, tparams, rhs)
}
+ // ----- TypeTrees that refer to other tree's symbols -------------------
+
+ /** A type tree that gets its type from some other tree's symbol. Enters the
+ * type tree in the References attachment of the `from` tree as a side effect.
+ */
+ abstract class DerivedTypeTree extends TypeTree(EmptyTree) {
+
+ private var myWatched: Tree = EmptyTree
+
+ /** The watched tree; used only for printing */
+ def watched: Tree = myWatched
+
+ /** Install the derived type tree as a dependency on `original` */
+ def watching(original: DefTree): this.type = {
+ myWatched = original
+ val existing = original.attachmentOrElse(References, Nil)
+ original.putAttachment(References, this :: existing)
+ this
+ }
+
+ /** A hook to ensure that all necessary symbols are completed so that
+ * OriginalSymbol attachments are propagated to this tree
+ */
+ def ensureCompletions(implicit ctx: Context): Unit = ()
+
+ /** The method that computes the type of this tree */
+ def derivedType(originalSym: Symbol)(implicit ctx: Context): Type
+ }
+
+ /** 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]
+
// ------ Creation methods for untyped only -----------------
def Ident(name: Name): Ident = new Ident(name)
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 0d84a9e61..1a65b2978 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -241,6 +241,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
case SeqLiteral(elems) =>
"[" ~ toTextGlobal(elems, ",") ~ "]"
+ case tpt: untpd.DerivedTypeTree =>
+ "<derived typetree watching " ~ toText(tpt.watched) ~ ">"
case TypeTree(orig) =>
if (tree.hasType) toText(tree.typeOpt) else toText(orig)
case SingletonTypeTree(ref) =>
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index ea396519a..36822cb85 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -84,6 +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 tpt: untpd.DerivedTypeTree =>
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)
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 162e13bbc..7885e85ac 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -72,6 +72,13 @@ trait NamerContextOps { this: Context =>
}
go(this)
}
+
+ /** Context where `sym` is defined, assuming we are in a nested context. */
+ def defContext(sym: Symbol) =
+ outersIterator
+ .dropWhile(_.owner != sym)
+ .dropWhile(_.owner == sym)
+ .next
}
/** This class creates symbols from definitions and imports and gives them
@@ -173,10 +180,10 @@ class Namer { typer: Typer =>
enclosingClassNamed(mods.privateWithin, mods.pos)
def record(sym: Symbol): Symbol = {
- val refs = tree.attachmentOrElse(desugar.References, Nil)
+ val refs = tree.attachmentOrElse(References, Nil)
if (refs.nonEmpty) {
- tree.removeAttachment(desugar.References)
- refs foreach (_.pushAttachment(desugar.OriginalSymbol, sym))
+ tree.removeAttachment(References)
+ refs foreach (_.pushAttachment(OriginalSymbol, sym))
}
tree.pushAttachment(SymOfTree, sym)
sym
@@ -449,17 +456,25 @@ class Namer { typer: Typer =>
if (self.isEmpty) NoType
else if (cls is Module) cls.owner.thisType select sourceModule
else createSymbol(self)
+
// pre-set info, so that parent types can refer to type params
denot.info = ClassInfo(cls.owner.thisType, cls, Nil, decls, selfInfo)
+
+ // Ensure constructor is completed so that any parameter accessors
+ // which have type trees deriving from its parameters can be
+ // completed in turn. Note that parent types access such parameter
+ // accessors, that's why the constructor needs to be completed before
+ // the parent types are elaborated.
+ index(constr)
+ symbolOfTree(constr).ensureCompleted()
+
val parentTypes = ensureFirstIsClass(parents map checkedParentType)
val parentRefs = ctx.normalizeToClassRefs(parentTypes, cls, decls)
typr.println(s"completing $denot, parents = $parents, parentTypes = $parentTypes, parentRefs = $parentRefs")
- index(constr)
index(rest)(inClassContext(selfInfo))
denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo)
// make sure constr parameters are all entered because we refer to them in desugarings:
- symbolOfTree(constr).ensureCompleted()
}
}
@@ -509,13 +524,6 @@ class Namer { typer: Typer =>
if (!mdef.tpt.isEmpty) WildcardType
else {
- /** Context where `sym` is defined */
- def defContext(sym: Symbol) =
- ctx.outersIterator
- .dropWhile(_.owner != sym)
- .dropWhile(_.owner == sym)
- .next
-
/** An type for this definition that might be inherited from elsewhere:
* If this is a setter parameter, the corresponding getter type.
* If this is a class member, the conjunction of all result types
@@ -561,7 +569,7 @@ class Namer { typer: Typer =>
if (original.isConstructorName && (sym.owner is ModuleClass))
sym.owner.companionClass.info.decl(nme.CONSTRUCTOR)
else
- defContext(sym).denotNamed(original)
+ ctx.defContext(sym).denotNamed(original)
def paramProto(paramss: List[List[Type]], idx: Int): Type = paramss match {
case params :: paramss1 =>
if (idx < params.length) wildApprox(params(idx))
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index e9a79eeb1..67e5c5902 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -637,12 +637,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = track("typedTypeTree") {
if (tree.original.isEmpty)
tree match {
- case tree: desugar.DerivedTypeTree =>
- TypeTree(tree.derivedType(tree.attachment(desugar.OriginalSymbol))) withPos tree.pos
- // 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.
+ case tree: untpd.DerivedTypeTree =>
+ tree.ensureCompletions
+ try
+ TypeTree(tree.derivedType(tree.attachment(untpd.OriginalSymbol))) withPos tree.pos
+ // 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.
+ catch {
+ case ex: NoSuchElementException =>
+ println(s"missing OriginalSymbol for ${ctx.owner.ownersIterator.toList}")
+ throw ex
+ }
case _ =>
assert(isFullyDefined(pt, ForceDegree.none))
tree.withType(pt)