aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-07-25 22:16:07 +0200
committerMartin Odersky <odersky@gmail.com>2013-07-25 22:22:42 +0200
commitcf65e84a6da2a151286a36297c057b72545960c8 (patch)
tree55f3d8a30f5751602836d62d0b1a4ae6269b64bd
parent0a86c0ae8668070f62df25c7a4ba12369f23b216 (diff)
downloaddotty-cf65e84a6da2a151286a36297c057b72545960c8.tar.gz
dotty-cf65e84a6da2a151286a36297c057b72545960c8.tar.bz2
dotty-cf65e84a6da2a151286a36297c057b72545960c8.zip
More typer logic, in particular dealing with variants of applications
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala3
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala5
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala115
-rw-r--r--src/dotty/tools/dotc/ast/UntypedTrees.scala36
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala5
-rw-r--r--src/dotty/tools/dotc/core/Types.scala29
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala273
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala32
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala137
13 files changed, 460 insertions, 197 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 2535e32ad..0a0638fa1 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -189,7 +189,8 @@ object desugar {
else DefDef(synthetic, nme.apply, tparams, vparamss, EmptyTree, creatorExpr) :: Nil
val unapplyMeth = {
val unapplyParam = makeSyntheticParameter(tpt = classTypeRef)
- DefDef(synthetic, nme.unapply, tparams, (unapplyParam :: Nil) :: Nil, EmptyTree, This(EmptyTypeName))
+ DefDef(synthetic, nme.unapply, tparams, (unapplyParam :: Nil) :: Nil,
+ EmptyTree, Ident(unapplyParam.name))
}
companionDefs(parent, applyMeths ::: unapplyMeth :: defaultGetters)
}
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index e43fd66cb..cde8c10b0 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -47,6 +47,11 @@ abstract class TreeInfo {
false
}
+ def isOpAssign(tree: untpd.Tree) = tree match {
+ case Apply(Select(_, name), _ :: Nil) if name.isOpAssignmentName => true
+ case _ => false
+ }
+
/** Is tree an expression which can be inlined without affecting program semantics?
*
* Note that this is not called "isExprPure" since purity (lack of side-effects)
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index dc37d5655..2ae474d15 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -52,6 +52,9 @@ object Trees {
newpd.asInstanceOf[this.type]
}
+ def withPos(posd: Positioned): this.type =
+ if (posd == null) this else withPos(posd.pos)
+
/** This item with a position that's the union of the given `pos` and the
* current position.
*/
@@ -150,33 +153,36 @@ object Trees {
/** The type constructor at the root of the tree */
type ThisTree[T >: Untyped] <: Tree[T]
- private var _tpe: T = _
+ private var myTpe: T = _
/** The type of the tree. In case of an untyped tree,
* an UnAssignedTypeException is thrown. (Overridden by empty trees)
*/
def tpe: T = {
- if (_tpe == null) throw new UnAssignedTypeException(this)
- _tpe
+ if (myTpe == null) throw new UnAssignedTypeException(this)
+ myTpe
}
/** Copy `tpe` attribute from tree `from` into this tree, independently
* whether it is null or not.
- */
- final def copyAttr(from: Tree[T]): ThisTree[T] = {
- _tpe = from._tpe
- this.withPos(from.pos).asInstanceOf[ThisTree[T]]
+ final def copyAttr[U >: Untyped](from: Tree[U]): ThisTree[T] = {
+ val t1 = this.withPos(from.pos)
+ val t2 =
+ if (from.myTpe != null) t1.withType(from.myTpe.asInstanceOf[Type])
+ else t1
+ t2.asInstanceOf[ThisTree[T]]
}
+ */
/** Return a typed tree that's isomorphic to this tree, but has given
* type. (Overridden by empty trees)
*/
def withType(tpe: Type): ThisTree[Type] = {
val tree =
- (if (_tpe == null ||
- (_tpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this
+ (if (myTpe == null ||
+ (myTpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this
else clone).asInstanceOf[Tree[Type]]
- tree._tpe = tpe
+ tree.myTpe = tpe
tree.asInstanceOf[ThisTree[Type]]
}
@@ -185,9 +191,9 @@ object Trees {
* modifications. Should be used only in special circumstances (we
* need it for printing trees with optional type info).
*/
- final def hasType: Boolean = _tpe != null
+ final def hasType: Boolean = myTpe != null
- final def typeOpt: Type = _tpe match {
+ final def typeOpt: Type = myTpe match {
case tp: Type => tp
case _ => NoType
}
@@ -695,6 +701,7 @@ object Trees {
type ValOrDefDef = Trees.ValOrDefDef[T]
type Ident = Trees.Ident[T]
+ type BackquotedIdent = Trees.BackquotedIdent[T]
type Select = Trees.Select[T]
type This = Trees.This[T]
type Super = Trees.Super[T]
@@ -747,169 +754,169 @@ object Trees {
def derivedIdent(name: Name): Ident[T] = tree match {
case tree: BackquotedIdent[_] =>
if (name == tree.name) tree
- else new BackquotedIdent[T](name).copyAttr(tree)
+ else new BackquotedIdent[T](name).withPos(tree.pos)
case tree: Ident[_] if (name == tree.name) => tree
- case _ => Ident[T](name).copyAttr(tree)
+ case _ => Ident[T](name).withPos(tree.pos)
}
def derivedSelect(qualifier: Tree[T], name: Name): Select[T] = tree match {
case tree: Select[_] if (qualifier eq tree.qualifier) && (name == tree.name) => tree
- case _ => Select(qualifier, name).copyAttr(tree)
+ case _ => Select(qualifier, name).withPos(tree.pos)
}
def derivedThis(qual: TypeName): This[T] = tree match {
case tree: This[_] if (qual == tree.qual) => tree
- case _ => This[T](qual).copyAttr(tree)
+ case _ => This[T](qual).withPos(tree.pos)
}
def derivedSuper(qual: Tree[T], mix: TypeName): Super[T] = tree match {
case tree: Super[_] if (qual eq tree.qual) && (mix == tree.mix) => tree
- case _ => Super(qual, mix).copyAttr(tree)
+ case _ => Super(qual, mix).withPos(tree.pos)
}
def derivedApply(fun: Tree[T], args: List[Tree[T]]): Apply[T] = tree match {
case tree: Apply[_] if (fun eq tree.fun) && (args eq tree.args) => tree
- case _ => Apply(fun, args).copyAttr(tree)
+ case _ => Apply(fun, args).withPos(tree.pos)
}
def derivedTypeApply(fun: Tree[T], args: List[Tree[T]]): TypeApply[T] = tree match {
case tree: TypeApply[_] if (fun eq tree.fun) && (args eq tree.args) => tree
- case _ => TypeApply(fun, args).copyAttr(tree)
+ case _ => TypeApply(fun, args).withPos(tree)
}
def derivedLiteral(const: Constant): Literal[T] = tree match {
case tree: Literal[_] if (const == tree.const) => tree
- case _ => Literal[T](const).copyAttr(tree)
+ case _ => Literal[T](const).withPos(tree.pos)
}
def derivedNew(tpt: Tree[T]): New[T] = tree match {
case tree: New[_] if (tpt eq tree.tpt) => tree
- case _ => New(tpt).copyAttr(tree)
+ case _ => New(tpt).withPos(tree.pos)
}
def derivedPair(left: Tree[T], right: Tree[T]): Pair[T] = tree match {
case tree: Pair[_] if (left eq tree.left) && (right eq tree.right) => tree
- case _ => Pair(left, right).copyAttr(tree)
+ case _ => Pair(left, right).withPos(tree.pos)
}
def derivedTyped(expr: Tree[T], tpt: Tree[T]): Typed[T] = tree match {
case tree: Typed[_] if (expr eq tree.expr) && (tpt eq tree.tpt) => tree
- case _ => Typed(expr, tpt).copyAttr(tree)
+ case _ => Typed(expr, tpt).withPos(tree.pos)
}
def derivedNamedArg(name: Name, arg: Tree[T]): NamedArg[T] = tree match {
case tree: NamedArg[_] if (name == tree.name) && (arg eq tree.arg) => tree
- case _ => NamedArg(name, arg).copyAttr(tree)
+ case _ => NamedArg(name, arg).withPos(tree.pos)
}
def derivedAssign(lhs: Tree[T], rhs: Tree[T]): Assign[T] = tree match {
case tree: Assign[_] if (lhs eq tree.lhs) && (rhs eq tree.rhs) => tree
- case _ => Assign(lhs, rhs).copyAttr(tree)
+ case _ => Assign(lhs, rhs).withPos(tree.pos)
}
def derivedBlock(stats: List[Tree[T]], expr: Tree[T]): Block[T] = tree match {
case tree: Block[_] if (stats eq tree.stats) && (expr eq tree.expr) => tree
- case _ => Block(stats, expr).copyAttr(tree)
+ case _ => Block(stats, expr).withPos(tree.pos)
}
def derivedIf(cond: Tree[T], thenp: Tree[T], elsep: Tree[T]): If[T] = tree match {
case tree: If[_] if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree
- case _ => If(cond, thenp, elsep).copyAttr(tree)
+ case _ => If(cond, thenp, elsep).withPos(tree.pos)
}
def derivedClosure(env: List[Tree[T]], meth: RefTree[T]): Closure[T] = tree match {
case tree: Closure[_] if (env eq tree.env) && (meth eq tree.meth) => tree
- case _ => Closure(env, meth).copyAttr(tree)
+ case _ => Closure(env, meth).withPos(tree.pos)
}
def derivedMatch(selector: Tree[T], cases: List[CaseDef[T]]): Match[T] = tree match {
case tree: Match[_] if (selector eq tree.selector) && (cases eq tree.cases) => tree
- case _ => Match(selector, cases).copyAttr(tree)
+ case _ => Match(selector, cases).withPos(tree.pos)
}
def derivedCaseDef(pat: Tree[T], guard: Tree[T], body: Tree[T]): CaseDef[T] = tree match {
case tree: CaseDef[_] if (pat eq tree.pat) && (guard eq tree.guard) && (body eq tree.body) => tree
- case _ => CaseDef(pat, guard, body).copyAttr(tree)
+ case _ => CaseDef(pat, guard, body).withPos(tree.pos)
}
def derivedReturn(expr: Tree[T], from: Tree[T]): Return[T] = tree match {
case tree: Return[_] if (expr eq tree.expr) && (from eq tree.from) => tree
- case _ => Return(expr, from).copyAttr(tree)
+ case _ => Return(expr, from).withPos(tree.pos)
}
def derivedTry(expr: Tree[T], handler: Tree[T], finalizer: Tree[T]): Try[T] = tree match {
case tree: Try[_] if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree
- case _ => Try(expr, handler, finalizer).copyAttr(tree)
+ case _ => Try(expr, handler, finalizer).withPos(tree.pos)
}
def derivedThrow(expr: Tree[T]): Throw[T] = tree match {
case tree: Throw[_] if (expr eq tree.expr) => tree
- case _ => Throw(expr).copyAttr(tree)
+ case _ => Throw(expr).withPos(tree.pos)
}
def derivedSeqLiteral(elems: List[Tree[T]]): SeqLiteral[T] = tree match {
case tree: SeqLiteral[_] if (elems eq tree.elems) => tree
- case _ => SeqLiteral(elems).copyAttr(tree)
+ case _ => SeqLiteral(elems).withPos(tree.pos)
}
def derivedSingletonTypeTree(ref: Tree[T]): SingletonTypeTree[T] = tree match {
case tree: SingletonTypeTree[_] if (ref eq tree.ref) => tree
- case _ => SingletonTypeTree(ref).copyAttr(tree)
+ case _ => SingletonTypeTree(ref).withPos(tree.pos)
}
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)
+ case _ => SelectFromTypeTree(qualifier, name).withPos(tree.pos)
}
def derivedAndTypeTree(left: Tree[T], right: Tree[T]): AndTypeTree[T] = tree match {
case tree: AndTypeTree[_] if (left eq tree.left) && (right eq tree.right) => tree
- case _ => AndTypeTree(left, right).copyAttr(tree)
+ case _ => AndTypeTree(left, right).withPos(tree.pos)
}
def derivedOrTypeTree(left: Tree[T], right: Tree[T]): OrTypeTree[T] = tree match {
case tree: OrTypeTree[_] if (left eq tree.left) && (right eq tree.right) => tree
- case _ => OrTypeTree(left, right).copyAttr(tree)
+ case _ => OrTypeTree(left, right).withPos(tree.pos)
}
def derivedRefinedTypeTree(tpt: Tree[T], refinements: List[Tree[T]]): RefinedTypeTree[T] = tree match {
case tree: RefinedTypeTree[_] if (tpt eq tree.tpt) && (refinements eq tree.refinements) => tree
- case _ => RefinedTypeTree(tpt, refinements).copyAttr(tree)
+ case _ => RefinedTypeTree(tpt, refinements).withPos(tree.pos)
}
def derivedAppliedTypeTree(tpt: Tree[T], args: List[Tree[T]]): AppliedTypeTree[T] = tree match {
case tree: AppliedTypeTree[_] if (tpt eq tree.tpt) && (args eq tree.args) => tree
- case _ => AppliedTypeTree(tpt, args).copyAttr(tree)
+ case _ => AppliedTypeTree(tpt, args).withPos(tree.pos)
}
def derivedTypeBoundsTree(lo: Tree[T], hi: Tree[T]): TypeBoundsTree[T] = tree match {
case tree: TypeBoundsTree[_] if (lo eq tree.lo) && (hi eq tree.hi) => tree
- case _ => TypeBoundsTree(lo, hi).copyAttr(tree)
+ case _ => TypeBoundsTree(lo, hi).withPos(tree.pos)
}
def derivedBind(name: Name, body: Tree[T]): Bind[T] = tree match {
case tree: Bind[_] if (name eq tree.name) && (body eq tree.body) => tree
- case _ => Bind(name, body).copyAttr(tree)
+ case _ => Bind(name, body).withPos(tree.pos)
}
def derivedAlternative(trees: List[Tree[T]]): Alternative[T] = tree match {
case tree: Alternative[_] if (trees eq tree.trees) => tree
- case _ => Alternative(trees).copyAttr(tree)
+ case _ => Alternative(trees).withPos(tree.pos)
}
def derivedUnApply(fun: Tree[T], args: List[Tree[T]]): UnApply[T] = tree match {
case tree: UnApply[_] if (fun eq tree.fun) && (args eq tree.args) => tree
- case _ => UnApply(fun, args).copyAttr(tree)
+ case _ => UnApply(fun, args).withPos(tree.pos)
}
def derivedValDef(mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T]): ValDef[T] = tree match {
case tree: ValDef[_] if (mods == tree.mods) && (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
- case _ => ValDef(mods, name, tpt, rhs).copyAttr(tree)
+ case _ => ValDef(mods, name, tpt, rhs).withPos(tree.pos)
}
def derivedDefDef(mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]): DefDef[T] = tree match {
case tree: DefDef[_] if (mods == tree.mods) && (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
- case _ => DefDef(mods, name, tparams, vparamss, tpt, rhs).copyAttr(tree)
+ case _ => DefDef(mods, name, tparams, vparamss, tpt, rhs).withPos(tree.pos)
}
def derivedTypeDef(mods: Modifiers[T], name: TypeName, rhs: Tree[T], tparams: List[untpd.TypeDef] = Nil): TypeDef[T] = tree match {
case tree: TypeDef[_] if (mods == tree.mods) && (name == tree.name) && (rhs eq tree.rhs) && (tparams eq tree.tparams) => tree
case _ =>
if (tparams.nonEmpty)
(untpd.typeDef _).asInstanceOf[(Modifiers[T], TypeName, List[untpd.TypeDef], Tree[T]) => TypeDef[T]](
- mods, name, tparams, rhs).copyAttr(tree)
- else TypeDef(mods, name, rhs).copyAttr(tree)
+ mods, name, tparams, rhs).withPos(tree.pos)
+ else TypeDef(mods, name, rhs).withPos(tree.pos)
}
def derivedTemplate(constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]): Template[T] = tree match {
case tree: Template[_] if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.body) => tree
- case _ => Template(constr, parents, self, body).copyAttr(tree)
+ case _ => Template(constr, parents, self, body).withPos(tree.pos)
}
def derivedImport(expr: Tree[T], selectors: List[Tree[Untyped]]): Import[T] = tree match {
case tree: Import[_] if (expr eq tree.expr) && (selectors eq tree.selectors) => tree
- case _ => Import(expr, selectors).copyAttr(tree)
+ case _ => Import(expr, selectors).withPos(tree.pos)
}
def derivedPackageDef(pid: RefTree[T], stats: List[Tree[T]]): PackageDef[T] = tree match {
case tree: PackageDef[_] if (pid eq tree.pid) && (stats eq tree.stats) => tree
- case _ => PackageDef(pid, stats).copyAttr(tree)
+ case _ => PackageDef(pid, stats).withPos(tree.pos)
}
def derivedAnnotated(annot: Tree[T], arg: Tree[T]): Annotated[T] = tree match {
case tree: Annotated[_] if (annot eq tree.annot) && (arg eq tree.arg) => tree
- case _ => Annotated(annot, arg).copyAttr(tree)
+ case _ => Annotated(annot, arg).withPos(tree.pos)
}
def derivedSharedTree(shared: Tree[T]): SharedTree[T] = tree match {
case tree: SharedTree[_] if (shared eq tree.shared) => tree
- case _ => SharedTree(shared).copyAttr(tree)
+ case _ => SharedTree(shared).withPos(tree.pos)
}
def derivedThicket(trees: List[Tree[T]]): Thicket[T] = tree match {
case tree: Thicket[_] if (trees eq tree.trees) => tree
- case _ => Thicket(trees).copyAttr(tree)
+ case _ => Thicket(trees).withPos(tree.pos)
}
}
diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala
index dacf13510..9449392dd 100644
--- a/src/dotty/tools/dotc/ast/UntypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala
@@ -105,75 +105,75 @@ object untpd extends Trees.Instance[Untyped] {
implicit class UntypedTreeCopier(val tree: Tree) extends AnyVal {
def derivedModuleDef(mods: Modifiers, name: TermName, impl: Template) = tree match {
case tree: ModuleDef if (mods eq tree.mods) && (name eq tree.name) && (impl eq tree.impl) => tree
- case _ => ModuleDef(mods, name, impl).copyAttr(tree)
+ case _ => ModuleDef(mods, name, impl).withPos(tree.pos)
}
def derivedPolyTypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) = tree match {
case tree: PolyTypeDef if (mods eq tree.mods) && (name eq tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree
- case _ => new PolyTypeDef(mods, name, tparams, rhs).copyAttr(tree)
+ case _ => new PolyTypeDef(mods, name, tparams, rhs).withPos(tree.pos)
}
def derivedSymbolLit(str: String) = tree match {
case tree: SymbolLit if (str == tree.str) => tree
- case _ => SymbolLit(str).copyAttr(tree)
+ case _ => SymbolLit(str).withPos(tree.pos)
}
def derivedInterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match {
case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree
- case _ => InterpolatedString(id, strings, elems).copyAttr(tree)
+ case _ => InterpolatedString(id, strings, elems).withPos(tree.pos)
}
def derivedFunction(args: List[Tree], body: Tree) = tree match {
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
- case _ => Function(args, body).copyAttr(tree)
+ case _ => Function(args, body).withPos(tree.pos)
}
def derivedInfixOp(left: Tree, op: Name, right: Tree) = tree match {
case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
- case _ => InfixOp(left, op, right).copyAttr(tree)
+ case _ => InfixOp(left, op, right).withPos(tree.pos)
}
def derivedPostfixOp(od: Tree, op: Name) = tree match {
case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
- case _ => PostfixOp(od, op).copyAttr(tree)
+ case _ => PostfixOp(od, op).withPos(tree.pos)
}
def derivedPrefixOp(op: Name, od: Tree) = tree match {
case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
- case _ => PrefixOp(op, od).copyAttr(tree)
+ case _ => PrefixOp(op, od).withPos(tree.pos)
}
def derivedParens(t: Tree) = tree match {
case tree: Parens if (t eq tree.t) => tree
- case _ => Parens(t).copyAttr(tree)
+ case _ => Parens(t).withPos(tree.pos)
}
def derivedTuple(trees: List[Tree]) = tree match {
case tree: Tuple if (trees eq tree.trees) => tree
- case _ => Tuple(trees).copyAttr(tree)
+ case _ => Tuple(trees).withPos(tree.pos)
}
def derivedWhileDo(cond: Tree, body: Tree) = tree match {
case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree
- case _ => WhileDo(cond, body).copyAttr(tree)
+ case _ => WhileDo(cond, body).withPos(tree.pos)
}
def derivedDoWhile(body: Tree, cond: Tree) = tree match {
case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree
- case _ => DoWhile(body, cond).copyAttr(tree)
+ case _ => DoWhile(body, cond).withPos(tree.pos)
}
def derivedForYield(enums: List[Tree], expr: Tree) = tree match {
case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree
- case _ => ForYield(enums, expr).copyAttr(tree)
+ case _ => ForYield(enums, expr).withPos(tree.pos)
}
def derivedForDo(enums: List[Tree], body: Tree) = tree match {
case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree
- case _ => ForDo(enums, body).copyAttr(tree)
+ case _ => ForDo(enums, body).withPos(tree.pos)
}
def derivedGenFrom(pat: Tree, expr: Tree) = tree match {
case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree
- case _ => GenFrom(pat, expr).copyAttr(tree)
+ case _ => GenFrom(pat, expr).withPos(tree.pos)
}
def derivedGenAlias(pat: Tree, expr: Tree) = tree match {
case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree
- case _ => GenAlias(pat, expr).copyAttr(tree)
+ case _ => GenAlias(pat, expr).withPos(tree.pos)
}
def derivedContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) = tree match {
case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree
- case _ => ContextBounds(bounds, cxBounds).copyAttr(tree)
+ case _ => ContextBounds(bounds, cxBounds).withPos(tree.pos)
}
def derivedPatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) = tree match {
case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
- case _ => PatDef(mods, pats, tpt, rhs).copyAttr(tree)
+ case _ => PatDef(mods, pats, tpt, rhs).withPos(tree.pos)
}
}
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 41d032f7a..bde325897 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -181,7 +181,7 @@ class Definitions(implicit ctx: Context) {
lazy val RepeatedParamAlias = newAliasType(tpnme.REPEATED_PARAM_CLASS, SeqType)
lazy val JavaRepeatedParamAlias = newAliasType(tpnme.JAVA_REPEATED_PARAM_CLASS, ArrayType)
- // fundamental reference classes
+ // fundamental classes
lazy val StringClass = requiredClass("java.lang.String")
lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
@@ -202,6 +202,7 @@ class Definitions(implicit ctx: Context) {
lazy val ThrowableClass = requiredClass("java.lang.Throwable")
lazy val JavaSerializableClass = requiredClass("java.lang.Serializable")
lazy val ComparableClass = requiredClass("java.lang.Comparable")
+ lazy val ProductClass = requiredClass("scala.Product")
// Annotation base classes
lazy val AnnotationClass = requiredClass("scala.annotation.Annotation")
@@ -286,9 +287,11 @@ class Definitions(implicit ctx: Context) {
lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity, 2)
+ lazy val ProductNClass = mkArityArray("Product", MaxTupleArity, 2)
lazy val FunctionClasses: Set[Symbol] = FunctionClass.toSet
lazy val TupleClasses: Set[Symbol] = TupleClass.toSet
+ lazy val ProductClasses: Set[Symbol] = ProductNClass.toSet
lazy val RepeatedParamAliases: Set[Symbol] = Set(RepeatedParamAlias, JavaRepeatedParamAlias)
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 468c5f58a..c3e15d94c 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -579,6 +579,15 @@ object Types {
case _ => List()
}
+ def firstParent(implicit ctx: Context): TypeRef = this match {
+ case tp: TypeProxy => tp.underlying.firstParent
+ case _ =>
+ parents match {
+ case p :: _ => p
+ case _ => defn.AnyClass.symTypeRef
+ }
+ }
+
/** The parameter types of a PolyType or MethodType, Empty list for others */
final def paramTypess: List[List[Type]] = this match {
case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
@@ -1428,7 +1437,7 @@ object Types {
}
def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
- if (isDependent) new InstMethodMap(this, argTypes) apply resultType
+ if (isDependent) resultType.substParams(this, argTypes)
else resultType
/* probably won't be needed
@@ -1530,10 +1539,10 @@ object Types {
override def signature(implicit ctx: Context) = resultType.signature
def instantiate(argTypes: List[Type])(implicit ctx: Context): Type =
- new InstPolyMap(this, argTypes) apply resultType
+ resultType.substParams(this, argTypes)
def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] =
- paramBounds.mapConserve(new InstPolyMap(this, argTypes).apply(_).bounds)
+ paramBounds.mapConserve(_.substParams(this, argTypes).bounds)
def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
@@ -1953,20 +1962,6 @@ object Types {
def apply(tp: Type) = tp
}
- class InstMethodMap(mt: MethodType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap {
- def apply(tp: Type) = tp match {
- case MethodParam(`mt`, n) => argtypes(n)
- case _ => mapOver(tp)
- }
- }
-
- class InstPolyMap(pt: PolyType, argtypes: List[Type])(implicit ctx: Context) extends TypeMap {
- def apply(tp: Type) = tp match {
- case PolyParam(`pt`, n) => argtypes(n)
- case _ => mapOver(tp)
- }
- }
-
/** Approximate occurrences of paremter types and uninstantiated typevars
* by wildcard types
*/
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index bd16f97aa..d0b9dc6bd 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -5,8 +5,8 @@ import core._
import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._
import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
import StdNames.nme
-import ast.Trees._
-import ast.untpd
+import ast.{Trees, untpd}
+import Trees._
import scala.annotation.switch
class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
@@ -135,7 +135,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
import untpd._
val txt: Text = tree match {
- case id: BackquotedIdent[_] =>
+ case id: Trees.BackquotedIdent[_] =>
"`" ~ toText(id.name) ~ "`"
case Ident(name) =>
toText(name)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index f4b8d8b12..3ce735c12 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -13,7 +13,10 @@ import Denotations._
import NameOps._
import Symbols._
import Types._
+import Typer.TreeDecorator
import Decorators._
+import ErrorReporting._
+import Trees._
import Names._
import StdNames._
import Constants._
@@ -24,6 +27,8 @@ import language.implicitConversions
object Applications {
+ import tpd._
+
private val isNamedArg = (arg: Any) => arg.isInstanceOf[Trees.NamedArg[_]]
def hasNamedArg(args: List[Any]) = args exists isNamedArg
@@ -61,16 +66,18 @@ object Applications {
}
case class FunProtoType(args: List[untpd.Tree], override val resultType: Type, typer: Typer)(implicit ctx: Context) extends UncachedGroundType {
- private var myTypedArgs: List[tpd.Tree] = null
+ private var myTypedArgs: List[Tree] = null
def argsAreTyped: Boolean = myTypedArgs != null
- def typedArgs: List[tpd.Tree] = {
+ def typedArgs: List[Tree] = {
if (myTypedArgs == null)
myTypedArgs = args mapconserve (typer.typed(_))
myTypedArgs
}
}
+
+ case class PolyProtoType(nargs: Int, override val resultType: Type) extends UncachedGroundType
}
import Applications._
@@ -78,7 +85,7 @@ import Applications._
trait Applications extends Compatibility{ self: Typer =>
import Applications._
- import Trees._
+ import tpd._
private def state(implicit ctx: Context) = ctx.typerState
@@ -100,7 +107,7 @@ trait Applications extends Compatibility{ self: Typer =>
protected def typedArg(arg: Arg, formal: Type): TypedArg
/** Turn a typed tree into an argument */
- protected def treeToArg(arg: tpd.Tree): Arg
+ protected def treeToArg(arg: Tree): Arg
/** Check that argument corresponds to type `formal` and
* possibly add it to the list of adapted arguments
@@ -126,7 +133,7 @@ trait Applications extends Compatibility{ self: Typer =>
/** If constructing trees, the current function part, which might be
* affected by lifting. EmptyTree otherwise.
*/
- protected def normalizedFun: tpd.Tree
+ protected def normalizedFun: Tree
/** If constructing trees, pull out all parts of the function
* which are not idempotent into separate prefix definitions
@@ -175,11 +182,11 @@ trait Applications extends Compatibility{ self: Typer =>
private def methString: String = s"method ${methRef.name}: ${methType.show}"
/** Re-order arguments to correctly align named arguments */
- def reorder[T >: Untyped](args: List[Tree[T]]): List[Tree[T]] = {
- var namedToArg: Map[Name, Tree[T]] =
+ def reorder[T >: Untyped](args: List[Trees.Tree[T]]): List[Trees.Tree[T]] = {
+ var namedToArg: Map[Name, Trees.Tree[T]] =
(for (NamedArg(name, arg1) <- args) yield (name, arg1)).toMap
- def badNamedArg(arg: Tree[_ >: Untyped]): Unit = {
+ def badNamedArg(arg: Trees.Tree[_ >: Untyped]): Unit = {
val NamedArg(name, _) = arg
def msg =
if (methodType.paramNames contains name)
@@ -189,7 +196,7 @@ trait Applications extends Compatibility{ self: Typer =>
fail(msg, arg.asInstanceOf[Arg])
}
- def recur(pnames: List[Name], args: List[Tree[T]]): List[Tree[T]] = pnames match {
+ def recur(pnames: List[Name], args: List[Trees.Tree[T]]): List[Trees.Tree[T]] = pnames match {
case pname :: pnames1 =>
namedToArg get pname match {
case Some(arg) =>
@@ -223,9 +230,9 @@ trait Applications extends Compatibility{ self: Typer =>
}
/** Splice new method reference into existing application */
- def spliceMeth(meth: tpd.Tree, app: tpd.Tree): tpd.Tree = app match {
- case Apply(fn, args) => tpd.Apply(spliceMeth(meth, fn), args)
- case TypeApply(fn, targs) => tpd.TypeApply(spliceMeth(meth, fn), targs)
+ def spliceMeth(meth: Tree, app: Tree): Tree = app match {
+ case Apply(fn, args) => Apply(spliceMeth(meth, fn), args)
+ case TypeApply(fn, targs) => TypeApply(spliceMeth(meth, fn), targs)
case _ => meth
}
@@ -285,7 +292,7 @@ trait Applications extends Compatibility{ self: Typer =>
findDefaultGetter(n + TreeInfo.numArgs(normalizedFun)) match {
case dref: NamedType =>
liftFun()
- addTyped(treeToArg(spliceMeth(tpd.Ident(dref), normalizedFun)), formal)
+ addTyped(treeToArg(spliceMeth(Ident(dref), normalizedFun)), formal)
matchArgs(args1, formals1, n + 1)
case _ =>
missingArg(n)
@@ -362,29 +369,29 @@ trait Applications extends Compatibility{ self: Typer =>
ok = false
def fail(msg: => String) =
ok = false
- def normalizedFun = tpd.EmptyTree
+ def normalizedFun = EmptyTree
}
/** Subtrait of Application for the cases where arguments are (typed or
* untyped) trees.
*/
- trait TreeApplication[T >: Untyped] extends Application[Tree[T]] {
- type TypeArg = tpd.Tree
- def isVarArg(arg: Tree[T]): Boolean = TreeInfo.isWildcardStarArg(arg)
+ trait TreeApplication[T >: Untyped] extends Application[Trees.Tree[T]] {
+ type TypeArg = Tree
+ def isVarArg(arg: Trees.Tree[T]): Boolean = TreeInfo.isWildcardStarArg(arg)
}
/** Subclass of Application for applicability tests with trees as arguments. */
- class ApplicableToTrees(methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context)
+ class ApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context)
extends TestApplication(methRef, methRef, args, resultType) with TreeApplication[Type] {
- def argType(arg: tpd.Tree): Type = normalize(arg.tpe)
- def treeToArg(arg: tpd.Tree): tpd.Tree = arg
+ def argType(arg: Tree): Type = normalize(arg.tpe)
+ def treeToArg(arg: Tree): Tree = arg
}
/** Subclass of Application for applicability tests with types as arguments. */
class ApplicableToTypes(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context)
extends TestApplication(methRef, methRef, args, resultType) {
def argType(arg: Type): Type = arg
- def treeToArg(arg: tpd.Tree): Type = arg.tpe
+ def treeToArg(arg: Tree): Type = arg.tpe
def isVarArg(arg: Type): Boolean = arg.isRepeatedParam
}
@@ -392,24 +399,24 @@ trait Applications extends Compatibility{ self: Typer =>
* types of arguments are either known or unknown.
*/
abstract class TypedApply[T >: Untyped](
- app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, args: List[Tree[T]], resultType: Type)(implicit ctx: Context)
+ app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Trees.Tree[T]], resultType: Type)(implicit ctx: Context)
extends Application(methRef, fun.tpe, args, resultType) with TreeApplication[T] {
- type TypedArg = tpd.Tree
- private var typedArgBuf = new mutable.ListBuffer[tpd.Tree]
- private var liftedDefs: mutable.ListBuffer[tpd.Tree] = null
- private var myNormalizedFun: tpd.Tree = fun
+ type TypedArg = Tree
+ private var typedArgBuf = new mutable.ListBuffer[Tree]
+ private var liftedDefs: mutable.ListBuffer[Tree] = null
+ private var myNormalizedFun: Tree = fun
- def addArg(arg: tpd.Tree, formal: Type): Unit =
+ def addArg(arg: Tree, formal: Type): Unit =
typedArgBuf += adapt(arg, formal)
def makeVarArg(n: Int, elemFormal: Type): Unit = {
val args = typedArgBuf.takeRight(n).toList
typedArgBuf.trimEnd(n)
val seqType = if (methodType.isJava) defn.ArrayType else defn.SeqType
- typedArgBuf += tpd.SeqLiteral(seqType.appliedTo(elemFormal :: Nil), args)
+ typedArgBuf += SeqLiteral(seqType.appliedTo(elemFormal :: Nil), args)
}
- def fail(msg: => String, arg: Tree[T]) = {
+ def fail(msg: => String, arg: Trees.Tree[T]) = {
ctx.error(msg, arg.pos)
ok = false
}
@@ -423,7 +430,7 @@ trait Applications extends Compatibility{ self: Typer =>
override def liftFun(): Unit =
if (liftedDefs == null) {
- liftedDefs = new mutable.ListBuffer[tpd.Tree]
+ liftedDefs = new mutable.ListBuffer[Tree]
myNormalizedFun = liftApp(liftedDefs, myNormalizedFun)
}
@@ -431,7 +438,7 @@ trait Applications extends Compatibility{ self: Typer =>
* where `EmptyTree`s in the second list are skipped.
* -1 if there are no differences.
*/
- private def firstDiff[T <: Tree[_]](xs: List[T], ys: List[T], n: Int = 0): Int = xs match {
+ private def firstDiff[T <: Trees.Tree[_]](xs: List[T], ys: List[T], n: Int = 0): Int = xs match {
case x :: xs1 =>
ys match {
case EmptyTree :: ys1 => firstDiff(xs1, ys1, n)
@@ -445,53 +452,183 @@ trait Applications extends Compatibility{ self: Typer =>
case nil => -1
}
}
- def sameSeq[T <: Tree[_]](xs: List[T], ys: List[T]): Boolean = firstDiff(xs, ys) < 0
-
- val result: tpd.Tree =
- if (!success) app withType ErrorType
- else {
- var typedArgs = typedArgBuf.toList
- if (!sameSeq(app.args, orderedArgs)) {
- // need to lift arguments to maintain evaluation order in the
- // presence of argument reorderings.
- liftFun()
- val eqSuffixLength = firstDiff(app.args.reverse, orderedArgs.reverse)
- val (liftable, rest) = typedArgs splitAt (typedArgs.length - eqSuffixLength)
- typedArgs = liftArgs(liftedDefs, methType, liftable) ++ rest
+ def sameSeq[T <: Trees.Tree[_]](xs: List[T], ys: List[T]): Boolean = firstDiff(xs, ys) < 0
+
+ val result = {
+ var typedArgs = typedArgBuf.toList
+ val ownType =
+ if (!success) ErrorType
+ else {
+ if (!sameSeq(app.args, orderedArgs)) {
+ // need to lift arguments to maintain evaluation order in the
+ // presence of argument reorderings.
+ liftFun()
+ val eqSuffixLength = firstDiff(app.args.reverse, orderedArgs.reverse)
+ val (liftable, rest) = typedArgs splitAt (typedArgs.length - eqSuffixLength)
+ typedArgs = liftArgs(liftedDefs, methType, liftable) ++ rest
+ }
+ if (sameSeq(typedArgs, args)) // trick to cut down on tree copying
+ typedArgs = args.asInstanceOf[List[Tree]]
+ methodType.instantiate(typedArgs map (_.tpe))
}
- if (sameSeq(typedArgs, args)) // trick to cut down on tree copying
- typedArgs = args.asInstanceOf[List[tpd.Tree]]
- val app1 = app.withType(methodType.instantiate(typedArgs map (_.tpe)))
- .derivedApply(normalizedFun, typedArgs)
- if (liftedDefs != null && liftedDefs.nonEmpty) tpd.Block(liftedDefs.toList, app1)
- else app1
- }
+ val app1 = app.withType(ownType).derivedApply(normalizedFun, typedArgs)
+ if (liftedDefs != null && liftedDefs.nonEmpty) Block(liftedDefs.toList, app1)
+ else app1
+ }
}
/** Subclass of Application for type checking an Apply node with untyped arguments. */
- class ApplyToUntyped(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, args: List[untpd.Tree], resultType: Type)(implicit ctx: Context)
+ class ApplyToUntyped(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[untpd.Tree], resultType: Type)(implicit ctx: Context)
extends TypedApply(app, fun, methRef, args, resultType) {
def typedArg(arg: untpd.Tree, formal: Type): TypedArg = typed(arg, formal)
- def treeToArg(arg: tpd.Tree): untpd.Tree = untpd.TypedSplice(arg)
+ def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg)
}
/** Subclass of Application for type checking an Apply node with typed arguments. */
- class ApplyToTyped(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context)
+ class ApplyToTyped(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context)
extends TypedApply(app, fun, methRef, args, resultType) {
- def typedArg(arg: tpd.Tree, formal: Type): TypedArg = arg
- def treeToArg(arg: tpd.Tree): tpd.Tree = arg
+ def typedArg(arg: Tree, formal: Type): TypedArg = arg
+ def treeToArg(arg: Tree): Tree = arg
}
- def typedApply(app: untpd.Apply, fun: tpd.Tree, methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context): tpd.Tree =
+ def typedApply(app: untpd.Apply, fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree =
new ApplyToTyped(app, fun, methRef, args, resultType).result
- def typedApply(fun: tpd.Tree, methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context): tpd.Tree =
- typedApply(Apply(untpd.TypedSplice(fun), Nil), fun, methRef, args, resultType)
+ def typedApply(fun: Tree, methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context): Tree =
+ typedApply(Trees.Apply(untpd.TypedSplice(fun), Nil), fun, methRef, args, resultType)
+
+ def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
+ if (ctx.mode is Mode.Pattern)
+ typedUnApply(tree.fun, tree.args, tree, pt)
+ else {
+
+ def realApply(implicit ctx: Context) = {
+ val proto = new FunProtoType(tree.args, pt, this)
+ val fun1 = typedExpr(tree.fun, proto)
+ TreeInfo.methPart(fun1).tpe match {
+ case funRef: TermRef =>
+ val app =
+ if (proto.argsAreTyped) new ApplyToTyped(tree, fun1, funRef, proto.typedArgs, pt)
+ else new ApplyToUntyped(tree, fun1, funRef, tree.args, pt)
+ val result = app.result
+ ConstFold(result) orElse result
+ case _ =>
+ fun1.exprType match {
+ case ErrorType =>
+ tree.withType(ErrorType)
+ }
+ }
+ }
+
+ def typedOpAssign: Tree = {
+ val Apply(Select(lhs, name), rhss) = tree
+ val lhs1 = typedExpr(lhs)
+ val lifted = new mutable.ListBuffer[Tree]
+ val lhs2 = untpd.TypedSplice(liftApp(lifted, lhs1))
+ val assign = Trees.Assign(lhs2, Trees.Apply(Trees.Select(lhs2, name.init), rhss))
+ typed(assign)
+ }
+
+ realApply
+ if (TreeInfo.isOpAssign(tree))
+ tryEither {
+ implicit ctx => realApply
+ } { failed =>
+ tryEither {
+ implicit ctx => typedOpAssign
+ } { _ =>
+ failed.commit()
+ }
+ }
+ else realApply
+ }
+ }
+
+ def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = {
+ val typedFn = typedExpr(tree.fun, PolyProtoType(tree.args.length, pt))
+ val typedArgs = tree.args map (typedType(_))
+ val ownType = typedFn.tpe.widen match {
+ case pt: PolyType =>
+ checkBounds(typedArgs, pt, tree.pos)
+ pt.resultType.substParams(pt, typedArgs map (_.tpe))
+ case _ =>
+ ctx.error(s"${err.exprStr(typedFn)} does not take type parameters", tree.pos)
+ ErrorType
+ }
+ tree.withType(ownType).derivedTypeApply(typedFn, typedArgs)
+ }
+
+ def typedUnApply(qual: untpd.Tree, args: List[untpd.Tree], tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
+
+ def unapplyArgs(unapplyResult: Type)(implicit ctx: Context): List[Type] = {
+ def recur(tp: Type): List[Type] = {
+ def nonOverloadedMember(name: Name) = {
+ val ref = tp member name
+ if (ref.isOverloaded) {
+ errorType(s"Overloaded reference to $ref is not allowed in extractor", tree.pos)
+ }
+ else
+ ref.info
+ }
+
+ def productSelectors: List[Type] = {
+ val sels = for (n <- Iterator.from(0)) yield nonOverloadedMember(("_" + n).toTermName)
+ sels.takeWhile(_.exists).toList
+ }
+ def seqSelector = defn.RepeatedParamType.appliedTo(tp.elemType :: Nil)
+
+ if (tp derivesFrom defn.ProductClass) productSelectors
+ else if (tp derivesFrom defn.SeqClass) seqSelector :: Nil
+ else if (tp.typeSymbol == defn.BooleanClass) Nil
+ else if (nonOverloadedMember(nme.isDefined).exists &&
+ nonOverloadedMember(nme.get).exists) recur(nonOverloadedMember(nme.get))
+ else {
+ ctx.error(s"${unapplyResult.show} is not a valid result type of an unapply method of an extractor", tree.pos)
+ Nil
+ }
+ }
+
+ recur(unapplyResult)
+ }
+
+ val fn = {
+ val dummyArg = untpd.TypedSplice(dummyTreeOfType(WildcardType))
+ val unappProto = FunProtoType(dummyArg :: Nil, pt, this)
+ tryEither {
+ implicit ctx => typedExpr(Trees.Select(qual, nme.unapply), unappProto)
+ } {
+ s => tryEither {
+ implicit ctx => typedExpr(Trees.Select(qual, nme.unapplySeq), unappProto) // for backwards compatibility; will be dropped
+ } {
+ _ => errorTree(s.value, s"${qual.show} cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method")
+ }
+ }
+ }
+ fn.tpe.widen match {
+ case mt: MethodType =>
+ val ownType = mt.resultType
+ ownType <:< pt // done for registering the constraints; error message would come later
+ var argTypes = unapplyArgs(ownType)
+ val bunchedArgs = argTypes match {
+ case argType :: Nil if argType.isRepeatedParam => Trees.SeqLiteral(args) :: Nil
+ case _ => args
+ }
+ if (argTypes.length != bunchedArgs.length) {
+ ctx.error(s"wrong number of argument patterns for ${err.patternConstrStr(fn)}", tree.pos)
+ argTypes = argTypes.take(args.length) ++
+ List.fill(argTypes.length - args.length)(WildcardType)
+ }
+ val typedArgs = (bunchedArgs, argTypes).zipped map (typed(_, _))
+ Trees.UnApply(fn, typedArgs).withPos(tree.pos).withType(ownType)
+ case et: ErrorType =>
+ tree.withType(ErrorType)
+ }
+ }
/** Is given method reference applicable to argument types `args`?
* @param resultType The expected result type of the application
*/
- def isApplicableToTrees(methRef: TermRef, args: List[tpd.Tree], resultType: Type)(implicit ctx: Context) =
+ def isApplicableToTrees(methRef: TermRef, args: List[Tree], resultType: Type)(implicit ctx: Context) =
new ApplicableToTrees(methRef, args, resultType)(ctx.fresh.withNewTyperState).success
/** Is given method reference applicable to arguments `args`?
@@ -576,8 +713,8 @@ trait Applications extends Compatibility{ self: Typer =>
best :: asGood(alts1)
}
- private val dummyTree = Literal(Constant(null))
- def dummyTreeOfType(tp: Type): tpd.Tree = dummyTree withType tp
+ private val dummyTree = Trees.Literal(Constant(null))
+ def dummyTreeOfType(tp: Type): Tree = dummyTree withType tp
/** Resolve overloaded alternative `alts`, given expected type `pt`. */
def resolveOverloaded(alts: List[TermRef], pt: Type)(implicit ctx: Context): List[TermRef] = {
@@ -595,7 +732,7 @@ trait Applications extends Compatibility{ self: Typer =>
/** The shape of given tree as a type; is more expensive than
* typeShape but can can handle named arguments.
*/
- def treeShape(tree: untpd.Tree): tpd.Tree = tree match {
+ def treeShape(tree: untpd.Tree): Tree = tree match {
case NamedArg(name, arg) =>
val argShape = treeShape(arg)
tree.withType(argShape.tpe).derivedNamedArg(name, argShape)
@@ -627,14 +764,14 @@ trait Applications extends Compatibility{ self: Typer =>
def narrowByShapes(alts: List[TermRef]): List[TermRef] =
if (args exists (_.isInstanceOf[untpd.Function]))
- if (args exists (_.isInstanceOf[NamedArg[_]]))
+ if (args exists (_.isInstanceOf[Trees.NamedArg[_]]))
narrowByTrees(alts, args map treeShape, resultType)
else
narrowByTypes(alts, args map typeShape, resultType)
else
alts
- def narrowByTrees(alts: List[TermRef], args: List[tpd.Tree], resultType: Type): List[TermRef] =
+ def narrowByTrees(alts: List[TermRef], args: List[Tree], resultType: Type): List[TermRef] =
alts filter (isApplicableToTrees(_, args, resultType))
val alts1 = narrowBySize(alts)
@@ -645,6 +782,12 @@ trait Applications extends Compatibility{ self: Typer =>
else narrowByTrees(alts2, pt.typedArgs, resultType)
}
+ case pt @ PolyProtoType(nargs, _) =>
+ alts filter ( alt => alt.widen match {
+ case PolyType(pnames) if pnames.length == nargs => true
+ case _ => false
+ })
+
case defn.FunctionType(args, resultType) =>
narrowByTypes(alts, args, resultType)
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index ef6184394..e0ff8e351 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -13,9 +13,12 @@ object ErrorReporting {
import tpd._
- def errorTree(tree: Trees.Tree[_], msg: => String)(implicit ctx: Context): tpd.Tree = {
- ctx.error(msg, tree.pos)
- tree withType ErrorType
+ def errorTree(tree: Tree, msg: => String)(implicit ctx: Context): tpd.Tree =
+ tree withType errorType(msg, tree.pos)
+
+ def errorType(msg: => String, pos: Position)(implicit ctx: Context): ErrorType = {
+ ctx.error(msg, pos)
+ ErrorType
}
class Errors(implicit ctx: Context) {
@@ -54,6 +57,10 @@ object ErrorReporting {
case _ => anonymousTypeMemberStr(tp)
}
+ def exprStr(tree: Tree): String = refStr(tree.tpe)
+
+ def patternConstrStr(tree: Tree): String = ???
+
def typeMismatch(tree: Tree, pt: Type): Tree =
errorTree(tree,
s"""type mismatch:
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 9d244ea3e..1ae33d87a 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -3,11 +3,42 @@ package dotc
package typer
import core._
+import ast._
import Contexts._, Types._, Flags._, Denotations._, NameOps._, Symbols._
+import Trees._
import annotation.unchecked
+import util.Positions._
+import Decorators._
object Inferencing {
+ import tpd._
+
+ def checkBounds(args: List[Tree], poly: PolyType, pos: Position)(implicit ctx: Context): Unit = {
+
+ }
+
+ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = {
+ if (!tp.isStable)
+ ctx.error(s"Prefix ${tp.show} is not stable", pos)
+ tp
+ }
+
+ def checkClassTypeWithStablePrefix(tp: Type, pos: Position)(implicit ctx: Context): ClassSymbol = tp.dealias match {
+ case tp: TypeRef if tp.symbol.isClass =>
+ checkStable(tp.prefix, pos)
+ tp.symbol.asClass
+ case _: RefinedType | _: TypeVar | _: AnnotatedType =>
+ checkClassTypeWithStablePrefix(tp.asInstanceOf[TypeProxy].underlying, pos)
+ case _ =>
+ ctx.error(s"${tp.show} is not a class type", pos)
+ defn.ObjectClass
+ }
+
+ def checkInstantiatable(cls: ClassSymbol, pos: Position): Unit = {
+ ???
+ }
+
implicit class Infer(val ictx: Context) extends AnyVal {
implicit private def ctx = ictx
@@ -68,6 +99,7 @@ object Inferencing {
case nil =>
actuals.isEmpty
}
+
/* not needed right now
def formalParameters[T](mtp: MethodType, actuals: List[T])(isRepeated: T => Boolean)(implicit ctx: Context) =
if (mtp.isVarArgs && !(actuals.nonEmpty && isRepeated(actuals.last))) {
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index d71c0c020..fe2692a88 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -30,6 +30,7 @@ object Mode {
val Type = newMode(1, "Type")
val ImplicitsDisabled = newMode(2, "ImplicitsDisabled")
+ val InSuperInit = newMode(3, "inSuperInit")
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 0b6aa3c9e..1279fcf03 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -211,7 +211,7 @@ class Namer { typer: Typer =>
else typeDefSig(tree, sym)(localContext.withNewScope)
case imp: Import =>
val expr1 = typedAheadExpr(imp.expr)
- ImportType(SharedTree(expr1))
+ ImportType(tpd.SharedTree(expr1))
}
sym.info = typeSig(original)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index f99c08ecb..6d6211daf 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -9,7 +9,7 @@ import Constants._
import StdNames._
import Scopes._
import Denotations._
-import Inferencing.Infer
+import Inferencing._
import Contexts._
import Symbols._
import Types._
@@ -19,7 +19,7 @@ import NameOps._
import Flags._
import Decorators._
import ErrorReporting._
-import Applications.FunProtoType
+import Applications.{FunProtoType, PolyProtoType}
import EtaExpansion.etaExpand
import util.Positions._
import util.SourcePosition
@@ -31,6 +31,8 @@ trait TyperContextOps { ctx: Context => }
object Typer {
+ import tpd._
+
object BindingPrec {
val definition = 4
val namedImport = 3
@@ -40,12 +42,19 @@ object Typer {
def isImportPrec(prec: Int) = prec == namedImport || prec == wildImport
}
- implicit class TreeDecorator(tree: tpd.Tree) {
+ implicit class TreeDecorator(tree: Tree) {
def exprType(implicit ctx: Context): Type = tree.tpe match {
case tpe: TermRef if !tpe.symbol.isStable => tpe.info
case tpe => tpe
}
}
+
+ case class StateFul[T](value: T, state: TyperState) {
+ def commit()(implicit ctx: Context): T = {
+ state.commit()
+ value
+ }
+ }
}
class Typer extends Namer with Applications with Implicits {
@@ -60,11 +69,15 @@ 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 = {
- val ref = site.member(name)
+ val ref =
+ if (name == nme.CONSTRUCTOR) site.decl(name)
+ else site.member(name)
if (ref.exists) NamedType(site, name).withDenot(ref)
else {
if (!site.isErroneous)
- ctx.error(s"$name is not a member of ${site.show}", pos)
+ ctx.error(
+ if (name == nme.CONSTRUCTOR) s"${site.show} does not have a constructor"
+ else s"$name is not a member of ${site.show}", pos)
ErrorType
}
}
@@ -95,6 +108,21 @@ class Typer extends Namer with Applications with Implicits {
tpe
}
+ /** The qualifying class
+ * of a this or super with prefix `qual`.
+ * packageOk is equal false when qualifying class symbol
+ */
+ def qualifyingClass(tree: untpd.Tree, qual: Name, packageOK: Boolean)(implicit ctx: Context): Symbol =
+ ctx.owner.enclosingClass.ownersIterator.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
+ case Some(c) if packageOK || !(c is Package) =>
+ c
+ case _ =>
+ ctx.error(
+ if (qual.isEmpty) tree.show + " can be used only in a class, object, or template"
+ else qual.show + " is not an enclosing class", tree.pos)
+ NoSymbol
+ }
+
/** Attribute an identifier consisting of a simple name or an outer reference.
*
* @param tree The tree representing the identifier.
@@ -258,7 +286,7 @@ class Typer extends Namer with Applications with Implicits {
val rawType =
try findRef(NoType, BindingPrec.nothingBound, NoContext)
finally importedFromRoot = saved
-
+
val ownType =
if (rawType.exists) checkAccessible(rawType, superAccess = false, tree.pos)
else {
@@ -275,21 +303,61 @@ class Typer extends Namer with Applications with Implicits {
tree.withType(ownType).derivedSelect(qual1, tree.name)
}
- def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
- val proto = new FunProtoType(tree.args, pt, this)
- val fun1 = typedExpr(tree.fun, proto)
- TreeInfo.methPart(fun1).tpe match {
- case funRef: TermRef =>
- val app =
- if (proto.argsAreTyped) new ApplyToTyped(tree, fun1, funRef, proto.typedArgs, pt)
- else new ApplyToUntyped(tree, fun1, funRef, tree.args, pt)
- app.result
- case _ =>
- fun1.exprType match {
- case ErrorType =>
- tree.withType(ErrorType)
- }
+ def typedThis(tree: untpd.This)(implicit ctx: Context): Tree = {
+ val cls = qualifyingClass(tree, tree.qual, packageOK = false)
+ tree.withType(cls.thisType)
+ }
+
+ def typedSuper(tree: untpd.Super)(implicit ctx: Context): Tree = {
+ val mix = tree.mix
+ val qual1 = typed(tree.qual)
+ val cls = qual1.tpe.typeSymbol
+
+ def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix) match {
+ case p :: Nil =>
+ p
+ case Nil =>
+ errorType(s"$mix does not name a parent class of $cls", tree.pos)
+ case p :: q :: _ =>
+ errorType(s"ambiguous parent class qualifier", tree.pos)
}
+ val owntype =
+ if (!mix.isEmpty) findMixinSuper(cls.info)
+ else if (ctx.mode is Mode.InSuperInit) cls.info.firstParent
+ else cls.info.parents.reduceLeft((x: Type, y: Type) => AndType(x, y))
+
+ tree.withType(SuperType(cls.thisType, owntype)).derivedSuper(qual1, mix)
+ }
+
+ def typedLiteral(tree: untpd.Literal)(implicit ctx: Context) =
+ tree.withType(if (tree.const.tag == UnitTag) defn.UnitType else ConstantType(tree.const))
+
+ def typedNew(tree: untpd.New)(implicit ctx: Context) = {
+ val tpt1 = typedType(tree.tpt)
+ val cls = checkClassTypeWithStablePrefix(tpt1.tpe, tpt1.pos)
+ checkInstantiatable(cls, tpt1.pos)
+ tree.withType(tpt1.tpe).derivedNew(tpt1)
+ }
+
+ def typedPair(tree: untpd.Pair)(implicit ctx: Context) = {
+ val left1 = typed(tree.left)
+ val right1 = typed(tree.right)
+ tree.withType(defn.PairType.appliedTo(left1.tpe :: right1.tpe :: Nil)).derivedPair(left1, right1)
+ }
+
+ def TypedTyped(tree: untpd.Typed)(implicit ctx: Context) = {
+ val tpt1 = typedType(tree.tpt)
+ val expr1 = typedExpr(tree.expr, tpt1.tpe)
+ tree.withType(tpt1.tpe).derivedTyped(tpt1, expr1)
+ }
+
+ def NamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context) = {
+ val arg1 = typed(tree.arg, pt)
+ tree.withType(arg1.tpe).derivedNamedArg(tree.name, arg1)
+ }
+
+ def Assign(tree: untpd.Assign)(implicit ctx: Context) = {
+ ???
}
def typedModifiers(mods: untpd.Modifiers)(implicit ctx: Context): Modifiers = {
@@ -428,29 +496,24 @@ class Typer extends Namer with Applications with Implicits {
def typedPattern(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree =
typed(tree, pt)(ctx addMode Mode.Pattern)
- def tryEither[T](op: Context => T)(fallBack: => T)(implicit ctx: Context) = {
+ def tryEither[T](op: Context => T)(fallBack: StateFul[T] => T)(implicit ctx: Context) = {
val nestedCtx = ctx.fresh.withNewTyperState
val result = op(nestedCtx)
if (nestedCtx.reporter.hasErrors)
- fallBack
+ fallBack(StateFul(result, nestedCtx.typerState))
else {
nestedCtx.typerState.commit()
result
}
}
- def tryInsertApply(tree: Tree, pt: Type)(fallBack: => Tree)(implicit ctx: Context): Tree =
+ def tryInsertApply(tree: Tree, pt: Type)(fallBack: StateFul[Tree] => Tree)(implicit ctx: Context): Tree =
tryEither {
implicit ctx => typedSelect(Trees.Select(untpd.TypedSplice(tree), nme.apply), pt)
} {
fallBack
}
- def tryInsertApplyIfFunProto(tree: Tree, pt: Type)(fallBack: => Tree)(implicit ctx: Context): Tree = pt match {
- case pt: FunProtoType => tryInsertApply(tree, pt)(fallBack)
- case _ => fallBack
- }
-
/**
* (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
* (0) Convert expressions with constant types to literals (unless in interactive/scaladoc mode)
@@ -501,10 +564,13 @@ class Typer extends Namer with Applications with Implicits {
case alt :: Nil =>
adapt(tree.withType(alt), pt)
case Nil =>
- tryInsertApplyIfFunProto(tree, pt) {
+ def noMatches =
errorTree(tree,
s"""none of the ${err.overloadedAltsStr(altDenots)}
|match $expectedStr""".stripMargin)
+ pt match {
+ case pt: FunProtoType => tryInsertApply(tree, pt)(_ => noMatches)
+ case _ => noMatches
}
case alts =>
errorTree(tree,
@@ -521,7 +587,7 @@ class Typer extends Namer with Applications with Implicits {
case Apply(_, _) => " more"
case _ => ""
}
- errorTree(tree, s"$fn does not take$more parameters")
+ _ => errorTree(tree, s"$fn does not take$more parameters")
}
}
@@ -559,10 +625,13 @@ class Typer extends Namer with Applications with Implicits {
tree.tpe.widen match {
case ref: TermRef =>
adaptOverloaded(ref)
- case pt: PolyType =>
- val tracked = ctx.track(pt)
- val tvars = ctx.newTypeVars(tracked)
- adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt)
+ case poly: PolyType =>
+ if (pt.isInstanceOf[PolyProtoType]) tree
+ else {
+ val tracked = ctx.track(poly)
+ val tvars = ctx.newTypeVars(tracked)
+ adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt)
+ }
case tp =>
pt match {
case pt: FunProtoType => adaptToArgs(tp, pt)