aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2017-03-14 17:05:30 +0100
committerGitHub <noreply@github.com>2017-03-14 17:05:30 +0100
commit934da77590dad2003fe850b48b2ae01b427508f0 (patch)
tree42ded3e03ed2c16e1680ebaf72a49ad2964b2026 /compiler/src/dotty/tools/dotc/typer
parent1aad0a1433e1261af252d2240d63f6f01da65cef (diff)
parent3c22580feccca384e83465afd38d3df689c61f88 (diff)
downloaddotty-934da77590dad2003fe850b48b2ae01b427508f0.tar.gz
dotty-934da77590dad2003fe850b48b2ae01b427508f0.tar.bz2
dotty-934da77590dad2003fe850b48b2ae01b427508f0.zip
Merge pull request #2079 from dotty-staging/depmeth2
Allow inter-parameter dependencies
Diffstat (limited to 'compiler/src/dotty/tools/dotc/typer')
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala29
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ReTyper.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala9
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Variances.scala4
8 files changed, 62 insertions, 20 deletions
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index a65ef00cc..5dcf16b62 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -178,6 +178,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
*/
protected def normalizedFun: Tree
+ protected def typeOfArg(arg: Arg): Type
+
/** If constructing trees, pull out all parts of the function
* which are not idempotent into separate prefix definitions
*/
@@ -380,8 +382,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
if (success) formals match {
case formal :: formals1 =>
- def addTyped(arg: Arg, formal: Type) =
+ /** Add result of typing argument `arg` against parameter type `formal`.
+ * @return A type transformation to apply to all arguments following this one.
+ */
+ def addTyped(arg: Arg, formal: Type): Type => Type = {
addArg(typedArg(arg, formal), formal)
+ if (methodType.isParamDependent)
+ _.substParam(MethodParam(methodType, n), typeOfArg(arg))
+ else
+ identity
+ }
def missingArg(n: Int): Unit = {
val pname = methodType.paramNames(n)
@@ -395,8 +405,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
val getter = findDefaultGetter(n + numArgs(normalizedFun))
if (getter.isEmpty) missingArg(n)
else {
- addTyped(treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(
+ treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)),
+ formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
}
}
@@ -420,8 +432,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case EmptyTree :: args1 =>
tryDefault(n, args1)
case arg :: args1 =>
- addTyped(arg, formal)
- matchArgs(args1, formals1, n + 1)
+ val substParam = addTyped(arg, formal)
+ matchArgs(args1, formals1.mapconserve(substParam), n + 1)
case nil =>
tryDefault(n, args)
}
@@ -477,6 +489,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal)
def treeToArg(arg: Tree): Tree = arg
def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg)
+ def typeOfArg(arg: Tree): Type = arg.tpe
def harmonizeArgs(args: List[Tree]) = harmonize(args)
}
@@ -494,6 +507,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def argType(arg: Type, formal: Type): Type = arg
def treeToArg(arg: Tree): Type = arg.tpe
def isVarArg(arg: Type): Boolean = arg.isRepeatedParam
+ def typeOfArg(arg: Type): Type = arg
def harmonizeArgs(args: List[Type]) = harmonizeTypes(args)
}
@@ -592,6 +606,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
extends TypedApply(app, fun, methRef, proto.args, resultType) {
def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenExpr)
def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg)
+ def typeOfArg(arg: untpd.Tree) = proto.typeOfArg(arg)
}
/** Subclass of Application for type checking an Apply node with typed arguments. */
@@ -603,6 +618,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// not match the abstract method in Application and an abstract class error results.
def typedArg(arg: tpd.Tree, formal: Type): TypedArg = arg
def treeToArg(arg: Tree): Tree = arg
+ def typeOfArg(arg: Tree) = arg.tpe
}
/** If `app` is a `this(...)` constructor call, the this-call argument context,
@@ -1263,7 +1279,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def sizeFits(alt: TermRef, tp: Type): Boolean = tp match {
case tp: PolyType => sizeFits(alt, tp.resultType)
- case MethodType(_, ptypes) =>
+ case tp: MethodType =>
+ val ptypes = tp.paramTypes
val numParams = ptypes.length
def isVarArgs = ptypes.nonEmpty && ptypes.last.isRepeatedParam
def hasDefault = alt.symbol.hasDefaultParams
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index f822f8893..b43391592 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -441,7 +441,6 @@ object Checking {
case List(param) =>
if (param.is(Mutable))
ctx.error("value class parameter must not be a var", param.pos)
-
case _ =>
ctx.error("value class needs to have exactly one val parameter", clazz.pos)
}
@@ -625,6 +624,24 @@ trait Checking {
case _ =>
}
}
+
+ /** Check that method parameter types do not reference their own parameter
+ * or later parameters in the same parameter section.
+ */
+ def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = vparams match {
+ case vparam :: vparams1 =>
+ val check = new TreeTraverser {
+ def traverse(tree: Tree)(implicit ctx: Context) = tree match {
+ case id: Ident if vparams.exists(_.symbol == id.symbol) =>
+ ctx.error("illegal forward reference to method parameter", id.pos)
+ case _ =>
+ traverseChildren(tree)
+ }
+ }
+ check.traverse(vparam.tpt)
+ checkNoForwardDependencies(vparams1)
+ case Nil =>
+ }
}
trait NoChecking extends Checking {
@@ -642,4 +659,5 @@ trait NoChecking extends Checking {
override def checkNotSingleton(tpt: Tree, where: String)(implicit ctx: Context): Tree = tpt
override def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = ()
override def checkTraitInheritance(parentSym: Symbol, cls: ClassSymbol, pos: Position)(implicit ctx: Context) = ()
+ override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = ()
}
diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index e7e7ece78..57c1808c9 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -59,8 +59,8 @@ object EtaExpansion {
*/
def liftArgs(defs: mutable.ListBuffer[Tree], methRef: Type, args: List[Tree])(implicit ctx: Context) =
methRef.widen match {
- case MethodType(paramNames, paramTypes) =>
- (args, paramNames, paramTypes).zipped map { (arg, name, tp) =>
+ case mt: MethodType =>
+ (args, mt.paramNames, mt.paramTypes).zipped map { (arg, name, tp) =>
if (tp.isInstanceOf[ExprType]) arg
else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$")
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index b588e3ae5..f7dd725c8 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -237,6 +237,12 @@ object ProtoTypes {
typer.adapt(targ, formal, arg)
}
+ /** The type of the argument `arg`.
+ * @pre `arg` has been typed before
+ */
+ def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type =
+ myTypedArg(arg).tpe
+
private var myTupled: Type = NoType
/** The same proto-type but with all arguments combined in a single tuple */
diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
index 3252ead47..6080c6644 100644
--- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -85,8 +85,8 @@ class ReTyper extends Typer {
override def encodeName(tree: untpd.NameTree)(implicit ctx: Context) = tree
override def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree = fun.tpe match {
- case mt @ MethodType(_, formals) =>
- val args: List[Tree] = tree.args.zipWithConserve(formals)(typedExpr(_, _)).asInstanceOf[List[Tree]]
+ case mt: MethodType =>
+ val args: List[Tree] = tree.args.zipWithConserve(mt.paramTypes)(typedExpr(_, _)).asInstanceOf[List[Tree]]
assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
case _ =>
super.handleUnexpectedFunType(tree, fun)
diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 6bf8dcbbc..6e774e38e 100644
--- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -315,10 +315,10 @@ trait TypeAssigner {
def assignType(tree: untpd.Apply, fn: Tree, args: List[Tree])(implicit ctx: Context) = {
val ownType = fn.tpe.widen match {
- case fntpe @ MethodType(_, ptypes) =>
- if (sameLength(ptypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
+ case fntpe: MethodType =>
+ if (sameLength(fntpe.paramTypes, args) || ctx.phase.prev.relaxedTyping) fntpe.instantiate(args.tpes)
else
- errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${ptypes.length}, found: ${args.length}", tree.pos)
+ errorType(i"wrong number of arguments for $fntpe: ${fn.tpe}, expected: ${fntpe.paramTypes.length}, found: ${args.length}", tree.pos)
case t =>
errorType(i"${err.exprStr(fn)} does not take parameters", tree.pos)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index fd0c7c73d..d4a9744e4 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -672,8 +672,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// this can type the greatest set of admissible closures.
(pt.dealias.argTypesLo.init, pt.dealias.argTypesHi.last)
case SAMType(meth) =>
- val mt @ MethodType(_, paramTypes) = meth.info
- (paramTypes, mt.resultType)
+ val MethodTpe(_, formals, restpe) = meth.info
+ (formals, restpe)
case _ =>
(List.range(0, defaultArity) map alwaysWildcardType, WildcardType)
}
@@ -1229,6 +1229,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
completeAnnotations(ddef, sym)
val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef])
val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef])
+ vparamss1.foreach(checkNoForwardDependencies)
if (sym is Implicit) checkImplicitParamsNotSingletons(vparamss1)
var tpt1 = checkSimpleKinded(typedType(tpt))
@@ -1287,10 +1288,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def maybeCall(ref: Tree, psym: Symbol, cinfo: Type): Tree = cinfo match {
case cinfo: PolyType =>
maybeCall(ref, psym, cinfo.resultType)
- case cinfo @ MethodType(Nil, _) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
+ case cinfo @ MethodType(Nil) if cinfo.resultType.isInstanceOf[ImplicitMethodType] =>
val icall = New(ref).select(nme.CONSTRUCTOR).appliedToNone
typedExpr(untpd.TypedSplice(icall))(superCtx)
- case cinfo @ MethodType(Nil, _) if !cinfo.resultType.isInstanceOf[MethodType] =>
+ case cinfo @ MethodType(Nil) if !cinfo.resultType.isInstanceOf[MethodType] =>
ref
case cinfo: MethodType =>
if (!ctx.erasedTypes) { // after constructors arguments are passed in super call.
diff --git a/compiler/src/dotty/tools/dotc/typer/Variances.scala b/compiler/src/dotty/tools/dotc/typer/Variances.scala
index 92bd9fd74..5a1745930 100644
--- a/compiler/src/dotty/tools/dotc/typer/Variances.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Variances.scala
@@ -79,8 +79,8 @@ object Variances {
varianceInType(parent)(tparam) & varianceInType(rinfo)(tparam)
case tp: RecType =>
varianceInType(tp.parent)(tparam)
- case tp @ MethodType(_, paramTypes) =>
- flip(varianceInTypes(paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
+ case tp: MethodType =>
+ flip(varianceInTypes(tp.paramTypes)(tparam)) & varianceInType(tp.resultType)(tparam)
case ExprType(restpe) =>
varianceInType(restpe)(tparam)
case tp @ HKApply(tycon, args) =>