aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-10 11:43:01 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-10 12:10:10 +0200
commitd318cafbb92518a39c84539c0387c2c93815bb7a (patch)
tree0d822de681719bc4d01c91bda4e3064ea4c33e85 /src/dotty
parent2fffa023502cbaffe0e282495e18aefe2bff0d22 (diff)
downloaddotty-d318cafbb92518a39c84539c0387c2c93815bb7a.tar.gz
dotty-d318cafbb92518a39c84539c0387c2c93815bb7a.tar.bz2
dotty-d318cafbb92518a39c84539c0387c2c93815bb7a.zip
Added typing of all forms of type trees.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala27
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala97
5 files changed, 115 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 5c87517d2..cc26033f8 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -19,16 +19,22 @@ object desugar {
def valDef(vdef: ValDef)(implicit ctx: Context): Tree = {
val ValDef(mods, name, tpt, rhs) = vdef
if (!ctx.owner.isClass || (mods is Private)) vdef
- else {
- val lname = name.toLocalName
- val field = cpy.ValDef(vdef, mods, lname, tpt, rhs)
- val getter = cpy.DefDef(vdef, mods, name, Nil, Nil, tpt, Ident(lname))
- if (!(mods is Mutable)) Thicket(field, getter)
+ else flatTree {
+ val (field, getterRhs) =
+ if (rhs.isEmpty)
+ (EmptyTree, EmptyTree)
+ else {
+ val lname = name.toLocalName
+ (cpy.ValDef(vdef, mods, lname, tpt, rhs), Ident(lname))
+ }
+ val getter = cpy.DefDef(vdef, mods | Accessor, name, Nil, Nil, tpt, getterRhs)
+ if (!(mods is Mutable)) field :: getter :: Nil
else {
- val setterParam = makeSyntheticParameter(tpt = TypeTree(field))
+ val setterParam = makeSyntheticParameter(tpt = TypeTree(getter))
val setter = cpy.DefDef(vdef,
- mods, name.getterToSetter, Nil, (setterParam :: Nil) :: Nil, EmptyTree, refOfDef(setterParam))
- Thicket(field, getter, setter)
+ mods | Accessor, name.getterToSetter, Nil, (setterParam :: Nil) :: Nil,
+ EmptyTree, refOfDef(setterParam))
+ field :: getter :: setter :: Nil
}
}
}
@@ -545,6 +551,11 @@ object desugar {
}
}.withPos(tree.pos)
+ def refinedTypeToClass(tree: RefinedTypeTree)(implicit ctx: Context): TypeDef = {
+ val impl = Template(emptyConstructor, tree.tpt :: Nil, EmptyValDef, tree.refinements)
+ TypeDef(Modifiers(), tpnme.REFINE_CLASS, impl)
+ }
+
/** If tree is a variable pattern, return its name and type, otherwise return None.
*/
private object VarPattern {
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index f31f7373c..a266eaf87 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -922,6 +922,10 @@ object Trees {
case tree: SeqLiteral if (elems eq tree.elems) => tree
case _ => finalize(tree, untpd.SeqLiteral(elems))
}
+ def TypeTree(tree: Tree, original: Tree): TypeTree = tree match {
+ case tree: TypeTree if original eq tree.original => tree
+ case _ => finalize(tree, untpd.TypeTree(original))
+ }
def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree = tree match {
case tree: SingletonTypeTree if (ref eq tree.ref) => tree
case _ => finalize(tree, untpd.SingletonTypeTree(ref))
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 7a6094078..242acc43b 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -511,7 +511,7 @@ trait Applications extends Compatibility { self: Typer =>
val result = app.result
ConstFold(result) orElse result
case _ =>
- fun1.exprType match {
+ fun1.qualifierType match {
case ErrorType =>
tree.withType(ErrorType)
}
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index fe2692a88..88bb3d4d8 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -30,7 +30,7 @@ object Mode {
val Type = newMode(1, "Type")
val ImplicitsDisabled = newMode(2, "ImplicitsDisabled")
- val InSuperInit = newMode(3, "inSuperInit")
+ val InSuperInit = newMode(3, "InSuperInit")
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 7995da312..0869aff43 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -43,8 +43,9 @@ object Typer {
}
implicit class TreeDecorator(tree: Tree) {
- def exprType(implicit ctx: Context): Type = tree.tpe match {
+ def qualifierType(implicit ctx: Context): Type = tree.tpe match {
case tpe: TermRef if !tpe.symbol.isStable => tpe.info
+ case tpe: TypeRef => tpe.info
case tpe => tpe
}
}
@@ -69,7 +70,7 @@ class Typer extends Namer with Applications with Implicits {
*/
private var importedFromRoot: Set[Symbol] = Set()
- def typedSelection(site: Type, name: Name, pos: Position)(implicit ctx: Context): Type = {
+ def selectionType(site: Type, name: Name, pos: Position)(implicit ctx: Context): Type = {
val ref =
if (name == nme.CONSTRUCTOR) site.decl(name)
else site.member(name)
@@ -83,6 +84,12 @@ class Typer extends Namer with Applications with Implicits {
}
}
+ def checkedSelectionType(qual1: Tree, tree: untpd.RefTree)(implicit ctx: Context): Type = {
+ val ownType = selectionType(qual1.qualifierType, tree.name, tree.pos)
+ if (!ownType.isError) checkAccessible(ownType, qual1.isInstanceOf[Super], tree.pos)
+ ownType
+ }
+
def checkAccessible(tpe: Type, superAccess: Boolean, pos: Position)(implicit ctx: Context): Type = tpe match {
case tpe: NamedType =>
val pre = tpe.prefix
@@ -215,9 +222,9 @@ class Typer extends Namer with Applications with Implicits {
}
selectors match {
case Pair(Ident(from), Ident(`name`)) :: rest =>
- checkUnambiguous(typedSelection(site, name, tree.pos))
+ checkUnambiguous(selectionType(site, name, tree.pos))
case Ident(`name`) :: rest =>
- checkUnambiguous(typedSelection(site, name, tree.pos))
+ checkUnambiguous(selectionType(site, name, tree.pos))
case _ :: rest =>
namedImportRef(site, rest)
case nil =>
@@ -301,9 +308,7 @@ class Typer extends Namer with Applications with Implicits {
def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
val qual1 = typedExpr(tree.qualifier, RefinedType(WildcardType, tree.name, pt))
- val ownType = typedSelection(qual1.exprType, tree.name, tree.pos)
- if (!ownType.isError) checkAccessible(ownType, qual1.isInstanceOf[Super], tree.pos)
- cpy.Select(tree, qual1, tree.name).withType(ownType)
+ cpy.Select(tree, qual1, tree.name).withType(checkedSelectionType(qual1, tree))
}
def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = {
@@ -539,6 +544,84 @@ class Typer extends Namer with Applications with Implicits {
cpy.SeqLiteral(tree, elems1) withType ctx.lub(elems1.tpes)
}
+ def typedTypeTree(tree: untpd.TypeTree)(implicit ctx: Context): TypeTree = {
+ val (original1, ownType) = tree.original match {
+ case untpd.EmptyTree =>
+ (EmptyTree, errorType("internal error: missing type in TypeTree", tree.pos))
+ case original: DefDef =>
+ val meth = ctx.lookup(original.name).first
+ assert(meth.exists, meth)
+ (EmptyTree, meth.info.resultType)
+ case original =>
+ val original1 = typed(original)
+ (original1, original1.tpe)
+ }
+ cpy.TypeTree(tree, original1) withType ownType
+ }
+
+ def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = {
+ val ref1 = typedExpr(tree.ref)
+ checkStable(ref1.qualifierType, tree.pos)
+ cpy.SingletonTypeTree(tree, ref1) withType ref1.tpe
+ }
+
+ def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): SelectFromTypeTree = {
+ val qual1 = typedType(tree.qualifier, RefinedType(WildcardType, tree.name, pt))
+ cpy.SelectFromTypeTree(tree, qual1, tree.name).withType(checkedSelectionType(qual1, tree))
+ }
+
+ def typedAndTypeTree(tree: untpd.AndTypeTree, pt: Type)(implicit ctx: Context): AndTypeTree = {
+ val left1 = typed(tree.left)
+ val right1 = typed(tree.right)
+ cpy.AndTypeTree(tree, left1, right1) withType left1.tpe & right1.tpe
+ }
+
+ def typedOrTypeTree(tree: untpd.OrTypeTree, pt: Type)(implicit ctx: Context): OrTypeTree = {
+ val left1 = typed(tree.left, pt)
+ val right1 = typed(tree.right, pt)
+ cpy.OrTypeTree(tree, left1, right1) withType left1.tpe | right1.tpe
+ }
+
+ def typedRefinedTypeTree(tree: untpd.RefinedTypeTree)(implicit ctx: Context): RefinedTypeTree = {
+ val tpt1 = typedAheadType(tree.tpt)
+ val refineClsDef = desugar.refinedTypeToClass(tree)
+ val throwAwayScopeCtx = ctx.fresh.withNewScope
+ val refineCls = createSymbol(refineClsDef)(throwAwayScopeCtx).asClass
+ val TypeDef(_, _, Template(_, _, _, refinements1)) = typed(refineClsDef)
+ assert(tree.refinements.length == refinements1.length, s"${tree.refinements} != $refinements1")
+ def addRefinement(parent: Type, refinement: Tree): Type = {
+ foreachSubTreeOf(refinement) {
+ case tree: RefTree =>
+ if (tree.symbol.owner == refineCls && tree.pos.start <= tree.symbol.pos.end)
+ ctx.error(s"illegal forward reference in refinement", tree.pos)
+ case _ =>
+ }
+ val rsym = refinement.symbol
+ val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
+ RefinedType(parent, rsym.name, rt => rinfo.substThis(refineCls, RefinedThis(rt)))
+ }
+ cpy.RefinedTypeTree(tree, tpt1, refinements1) withType
+ (tpt1.tpe /: refinements1)(addRefinement)
+ }
+
+ def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(implicit ctx: Context): AppliedTypeTree = {
+ val tpt1 = typed(tree.tpt)
+ val args1 = tree.args map (typed(_))
+ val tparams = tpt1.tpe.typeParams
+ if (args1.length != tparams.length)
+ ctx.error(s"wrong number of type arguments for ${tpt1.tpe.show}, should be ${tparams.length}")
+ // todo in later phase: check arguments conform to parameter bounds
+ cpy.AppliedTypeTree(tree, tpt1, args1) withType tpt1.tpe.appliedTo(args1.tpes)
+ }
+
+ def typedTypeBounds(tree: untpd.TypeBoundsTree)(implicit ctx: Context): TypeBoundsTree = {
+ val lo1 = typed(tree.lo)
+ val hi1 = typed(tree.hi)
+ if (!(lo1.tpe <:< hi1.tpe))
+ ctx.error(s"lower bound ${lo1.tpe.show} does not conform to upper bound ${hi1.tpe.show}", tree.pos)
+ cpy.TypeBoundsTree(tree, lo1, hi1) withType TypeBounds(lo1.tpe, hi1.tpe)
+ }
+
def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = {
val body1 = typed(tree.body, pt)
val sym = ctx.newSymbol(ctx.owner, tree.name.asTermName, EmptyFlags, pt, coord = tree.pos)