diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Trees.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypedTrees.scala | 154 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 6 |
7 files changed, 105 insertions, 76 deletions
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 50694f223..60f6025fd 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -208,9 +208,6 @@ object Flags { final val PackageObjectVal = PackageObject.toTermFlags final val PackageObjectClass = PackageObject.toTypeFlags - /** A by-name parameter !!! needed? */ - final val ByNameParam = termFlag(17, "<by-name>") - /** A covariant type variable */ final val Covariant = typeFlag(17, "<covariant>") @@ -351,7 +348,7 @@ object Flags { final val PackageCreationFlags = Module | Package | Final | JavaDefined | Static /** A value that's unstable unless complemented with a Stable flag */ - final val UnstableValue = Mutable | Method | ByNameParam + final val UnstableValue = Mutable | Method /** Flags that are passed from a type parameter of a class to a refinement symbol * that sets the type parameter */ diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 2bafb7732..9299e7e63 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -169,6 +169,12 @@ object SymDenotations { /** Is this symbol an abstract type? */ def isAbstractType = isType && info.isRealTypeBounds + /** Is this symbol an alias type? */ + def isAliasType = isType && info.isAliasTypeBounds + + /** Is this symbol an abstract or alias type? */ + def isAbstractOrAliasType = isType & info.isInstanceOf[TypeBounds] + /** Is this definition contained in `boundary`? * Same as `ownersIterator contains boundary` but more efficient. */ diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 68579f15f..88a4b21f4 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -112,7 +112,7 @@ trait Symbols { this: Context => def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) = newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType) - def newImportSymbol(expr: TypedTree, coord: Coord = NoCoord) = + def newImportSymbol(expr: Shared[Type], coord: Coord = NoCoord) = newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord) def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) = diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala index 6215cfc69..4f739ced1 100644 --- a/src/dotty/tools/dotc/core/Trees.scala +++ b/src/dotty/tools/dotc/core/Trees.scala @@ -345,8 +345,8 @@ object Trees { } /** qualifier # name */ - case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit cpos: Position) - extends RefTree[T] with TypTree[T] { + case class SelectFromTypeTree[T](qualifier: Tree[T], name: Name)(implicit cpos: Position) + extends RefTree[T] { type ThisTree[T] = SelectFromTypeTree[T] val pos = cpos union qualifier.pos } @@ -632,7 +632,7 @@ object Trees { case tree: SingletonTypeTree[_] if (ref eq tree.ref) => tree case _ => SingletonTypeTree(ref).copyAttr(tree) } - def derivedSelectFromTypeTree(qualifier: Tree[T], name: TypeName): SelectFromTypeTree[T] = tree match { + def derivedSelectFromTypeTree(qualifier: Tree[T], name: Name): SelectFromTypeTree[T] = tree match { case tree: SelectFromTypeTree[_] if (qualifier eq tree.qualifier) && (name == tree.name) => tree case _ => SelectFromTypeTree(qualifier, name).copyAttr(tree) } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 77038816e..71bc9f801 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -61,7 +61,7 @@ trait TypeOps { this: Context => final def isVolatile(tp: Type): Boolean = { def isAbstractIntersection(tp: Type): Boolean = tp match { - case tp: TypeRef => tp.isAbstractType + case tp: TypeRef => tp.symbol.isAbstractType case AndType(l, r) => isAbstractIntersection(l) | isAbstractIntersection(l) case OrType(l, r) => isAbstractIntersection(l) & isAbstractIntersection(r) case _ => false diff --git a/src/dotty/tools/dotc/core/TypedTrees.scala b/src/dotty/tools/dotc/core/TypedTrees.scala index 65ab95693..f9223b04b 100644 --- a/src/dotty/tools/dotc/core/TypedTrees.scala +++ b/src/dotty/tools/dotc/core/TypedTrees.scala @@ -92,15 +92,27 @@ object TypedTrees { } def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply = { - val fntpe @ MethodType(pnames, ptypes) = fn.tpe - assert(sameLength(ptypes, args)) - Trees.Apply(fn, args).withType(fntpe.instantiate(args map (_.tpe))).checked + val owntype = fn.tpe.widen match { + case fntpe @ MethodType(pnames, ptypes) => + check(sameLength(ptypes, args)) + fntpe.instantiate(args map (_.tpe)) + case _ => + check(false) + ErrorType + } + Trees.Apply(fn, args).withType(owntype).checked } def TypeApply(fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = { - val fntpe @ PolyType(pnames) = fn.tpe - assert(sameLength(pnames, args)) - Trees.TypeApply(fn, args).withType(fntpe.instantiate(args map (_.tpe))).checked + val owntype = fn.tpe.widen match { + case fntpe @ PolyType(pnames) => + check(sameLength(pnames, args)) + fntpe.instantiate(args map (_.tpe)) + case _ => + check(false) + ErrorType + } + Trees.TypeApply(fn, args).withType(owntype).checked } def Literal(const: Constant)(implicit ctx: Context): Literal = @@ -122,7 +134,7 @@ object TypedTrees { Trees.Assign(lhs, rhs).withType(defn.UnitType).checked def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = { - lazy val locals = localSyms(stats) + lazy val locals = localSyms(stats).toSet val blk = Trees.Block(stats, expr) def widen(tp: Type): Type = tp match { case tp: TermRef if locals contains tp.symbol => @@ -156,7 +168,7 @@ object TypedTrees { def SingletonTypeTree(ref: Tree)(implicit ctx: Context): SingletonTypeTree = Trees.SingletonTypeTree(ref).withType(ref.tpe).checked - def SelectFromTypeTree(qualifier: Tree, tp: TypeRef)(implicit ctx: Context): SelectFromTypeTree = + def SelectFromTypeTree(qualifier: Tree, tp: NamedType)(implicit ctx: Context): SelectFromTypeTree = Trees.SelectFromTypeTree(qualifier, tp.name).withType(tp).checked def AndTypeTree(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree = @@ -187,12 +199,13 @@ object TypedTrees { def Alternative(trees: List[Tree])(implicit ctx: Context): Alternative = Trees.Alternative(trees).withType(ctx.lub(trees map (_.tpe))).checked - def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = - Trees.UnApply(fun, args).withType(fun.tpe.widen match { + def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = { + val owntype = fun.tpe.widen match { case MethodType(_, paramType :: Nil) => paramType - }).checked - - def refType(sym: Symbol)(implicit ctx: Context) = NamedType(sym.owner.thisType, sym) + case _ => check(false); ErrorType + } + Trees.UnApply(fun, args).withType(owntype).checked + } def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef = Trees.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs)(defPos(sym)) @@ -234,7 +247,7 @@ object TypedTrees { if (cls.selfType eq cls.typeConstructor) EmptyValDef else ValDef(ctx.newSelfSym(cls)) def isOwnTypeParamAccessor(stat: Tree) = - stat.symbol.owner == cls && (stat.symbol is TypeParam) + (stat.symbol is TypeParam) && stat.symbol.owner == cls val (tparamAccessors, rest) = body partition isOwnTypeParamAccessor val tparams = (typeParams map TypeDef) ++ @@ -266,8 +279,19 @@ object TypedTrees { def Shared(tree: Tree): Shared = Trees.Shared(tree).withType(tree.tpe) + def refType(sym: Symbol)(implicit ctx: Context) = NamedType(sym.owner.thisType, sym) + // ------ Creating typed equivalents of trees that exist only in untyped form ------- + /** A tree representing the same reference as the given type */ + def ref(tp: NamedType)(implicit ctx: Context): tpd.NameTree = + if (tp.symbol.isStatic) Ident(tp) + else tp.prefix match { + case pre: TermRef => Select(ref(pre), tp) + case pre => SelectFromTypeTree(TypeTree(pre), tp) + } // no checks necessary + + /** new C(args) */ def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = Apply( Select( @@ -343,24 +367,24 @@ object TypedTrees { else sym } else foldOver(sym, tree) } - - implicit class addChecked[T <: Tree](val tree: T) extends AnyVal { - def checked(implicit ctx: Context): T = { - if (ctx.settings.YcheckTypedTrees.value) checkType(tree) - tree - } - } } import Trees._ def check(p: Boolean)(implicit ctx: Context): Unit = assert(p) + def checkTypeArg(arg: tpd.Tree, bounds: TypeBounds)(implicit ctx: Context): Unit = { + check(arg.isValueType) + check(bounds contains arg.tpe) + } + def checkType(tree: tpd.Tree)(implicit ctx: Context): Unit = tree match { case Ident(name) => case Select(qualifier, name) => check(qualifier.isValue) + check(qualifier.tpe =:= tree.tpe.normalizedPrefix) val denot = qualifier.tpe.member(name) + check(denot.exists) check(denot.hasAltWith(_.symbol == tree.symbol)) case This(cls) => case Super(qual, mixin) => @@ -380,26 +404,14 @@ object TypedTrees { } check(arg.tpe <:< formal) } - fn.tpe.widen match { - case MethodType(paramNames, paramTypes) => - (args, paramNames, paramTypes).zipped foreach checkArg - case _ => - check(false) - } + val MethodType(paramNames, paramTypes) = fn.tpe.widen // checked already at construction + (args, paramNames, paramTypes).zipped foreach checkArg case TypeApply(fn, args) => - def checkArg(arg: tpd.Tree, bounds: TypeBounds): Unit = { - check(arg.isType) - check(bounds contains arg.tpe) - } - fn.tpe.widen match { - case pt: PolyType => - (args, pt.instantiateBounds(args map (_.tpe))).zipped foreach checkArg - case _ => - check(false) - } + val pt @ PolyType(_) = fn.tpe.widen // checked already at construction + (args, pt.instantiateBounds(args map (_.tpe))).zipped foreach checkTypeArg case Literal(const: Constant) => case New(tpt) => - check(tpt.isType) + check(tpt.isValueType) val cls = tpt.tpe.typeSymbol check(cls.isClass) check(!(cls is AbstractOrTrait)) @@ -407,7 +419,7 @@ object TypedTrees { check(left.isValue) check(right.isValue) case Typed(expr, tpt) => - check(tpt.isType) + check(tpt.isValueType) expr.tpe.widen match { case tp: MethodType => val cls = tpt.tpe.typeSymbol @@ -419,6 +431,7 @@ object TypedTrees { check(tp <:< absMembers.head.info) case _ => check(expr.isValueOrPattern) + check(expr.tpe <:< tpt.tpe) } case NamedArg(name, arg) => case Assign(lhs, rhs) => @@ -432,7 +445,7 @@ object TypedTrees { check(rhs.tpe <:< lhs.tpe.widen) case Block(stats, expr) => var hoisted: Set[Symbol] = Set() - lazy val locals = localSyms(stats) + lazy val locals = localSyms(stats).toSet check(expr.isValue) def isNonLocal(sym: Symbol): Boolean = !(locals contains sym) || isHoistableClass(sym) @@ -467,31 +480,35 @@ object TypedTrees { check(expr.isValue) check(expr.tpe <:< defn.ThrowableType) case SeqLiteral(elemtpt, elems) => - check(elemtpt.isType); + check(elemtpt.isValueType); for (elem <- elems) { check(elem.isValue) check(elem.tpe <:< elemtpt.tpe) } case TypeTree(original) => - if (!original.isEmpty) check(original.tpe == tree.tpe) + if (!original.isEmpty) { + check(original.isValueType) + check(original.tpe == tree.tpe) + } case SingletonTypeTree(ref) => check(ref.isValue) check(ref.symbol.isStable) case SelectFromTypeTree(qualifier, name) => - check(qualifier.isType) + check(qualifier.isValueType) + check(qualifier.tpe =:= tree.tpe.normalizedPrefix) val denot = qualifier.tpe.member(name) check(denot.exists) check(denot.symbol == tree.symbol) case AndTypeTree(left, right) => - check(left.isType); check(right.isType) + check(left.isValueType); check(right.isValueType) case OrTypeTree(left, right) => - check(left.isType); check(right.isType) + check(left.isValueType); check(right.isValueType) case RefineTypeTree(tpt, refinements) => - check(tpt.isType) + check(tpt.isValueType) def checkRefinements(forbidden: Set[Symbol], rs: List[tpd.DefTree]): Unit = rs match { case r :: rs1 => val rsym = r.symbol - check(rsym.isTerm || rsym.isAbstractType) + check(rsym.isTerm || rsym.isAbstractOrAliasType) if (rsym.isAbstractType) check(tpt.tpe.member(rsym.name).exists) check(rsym.info forall { case nt: NamedType => !(forbidden contains nt.symbol) @@ -502,30 +519,26 @@ object TypedTrees { } checkRefinements(localSyms(refinements).toSet, refinements) case AppliedTypeTree(tpt, args) => - check(tpt.isType) - for (arg <- args) check(arg.isType) - check(sameLength(tpt.tpe.typeParams, args)) + check(tpt.isValueType) + val tparams = tpt.tpe.typeParams + check(sameLength(tparams, args)) + (args, tparams map (_.info.bounds)).zipped foreach checkTypeArg case TypeBoundsTree(lo, hi) => - check(lo.isType); check(hi.isType) + check(lo.isValueType); check(hi.isValueType) check(lo.tpe <:< hi.tpe) case Bind(sym, body) => - // missing because it cannot be done easily bottom-up: - // check that Bind (and Alternative, and UnApply) only occur in patterns check(body.isValueOrPattern) check(!(tree.symbol is Method)) body match { case Ident(nme.WILDCARD) => - case _ => check(body.tpe <:< tree.symbol.info) + case _ => check(body.tpe.widen =:= tree.symbol.info) } case Alternative(alts) => for (alt <- alts) check(alt.isValueOrPattern) case UnApply(fun, args) => check(fun.isTerm) - val funtpe = fun.tpe.widen match { - case mt: MethodType => mt - case _ => check(false); ErrorType - } for (arg <- args) check(arg.isValueOrPattern) + val funtpe @ MethodType(_, _) = fun.tpe.widen fun.symbol.name match { // check arg arity case nme.unapplySeq => // args need to be wrapped in (...: _*) @@ -567,28 +580,43 @@ object TypedTrees { check(expr.isValue) check(expr.tpe.termSymbol.isStable) case PackageDef(pid, stats) => - check(pid.isValue) + check(pid.isTerm) check(pid.symbol.isPackage) case Annotated(annot, arg) => - check(annot.symbol.isClassConstructor) + check(annot.isInstantiation) check(annot.symbol.owner.isSubClass(defn.AnnotationClass)) - check(arg.isType || arg.isValue) + check(arg.isValueType || arg.isValue) case tpd.EmptyTree => case Shared(shared) => check(shared.isType || shared.isTerm) } - implicit class TreeInfo(val tree: tpd.Tree) extends AnyVal { + implicit class TreeOps[T <: tpd.Tree](val tree: T) extends AnyVal { + def isValue(implicit ctx: Context): Boolean = tree.isTerm && tree.tpe.widen.isValueType + def isValueOrPattern(implicit ctx: Context) = tree.isValue || tree.isPattern + + def isValueType: Boolean = + tree.isType && tree.tpe.isValueType + + def isInstantiation = tree match { + case Apply(Select(New(_), nme.CONSTRUCTOR), _) => true + case _ => false + } + + def checked(implicit ctx: Context): T = { + if (ctx.settings.YcheckTypedTrees.value) checkType(tree) + tree + } } // ensure that constructors are fully applied? // ensure that normal methods are fully applied? - def localSyms(stats: List[tpd.Tree])(implicit ctx: Context) = + def localSyms(stats: List[tpd.Tree])(implicit ctx: Context): List[Symbol] = for (stat <- stats if (stat.isDef)) yield stat.symbol } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 60facee3c..4b3271ed2 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -299,7 +299,7 @@ object Types { */ final def normalizedPrefix(implicit ctx: Context): Type = this match { case tp: NamedType => - if (tp.isAbstractType) tp.info.normalizedPrefix else tp.prefix + if (tp.symbol.isAliasType) tp.info.normalizedPrefix else tp.prefix case tp: ClassInfo => tp.prefix case tp: TypeProxy => @@ -735,8 +735,6 @@ object Types { override def underlying(implicit ctx: Context): Type = info - def isAbstractType(implicit ctx: Context) = info.isRealTypeBounds - def derivedNamedType(prefix: Type, name: Name)(implicit ctx: Context): Type = if (prefix eq this.prefix) this else NamedType(prefix, name) @@ -1152,7 +1150,7 @@ object Types { else AnnotatedType(annots, underlying) } - case class ImportType(expr: TypedTree) extends UncachedGroundType + case class ImportType(expr: Shared[Type]) extends UncachedGroundType // Special type objects ------------------------------------------------------------ |