aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-24 18:04:09 +0200
committerMartin Odersky <odersky@gmail.com>2015-04-24 18:04:09 +0200
commit6a3aab8241cc5379bcffb7644bdbaa04ba12ce5b (patch)
tree80d4fa10baf4b1530963b2366fa4c420e68adeb4 /src/dotty
parent1e9c012a0c61b2031ecaf11de3f2e99a5fdff7af (diff)
downloaddotty-6a3aab8241cc5379bcffb7644bdbaa04ba12ce5b.tar.gz
dotty-6a3aab8241cc5379bcffb7644bdbaa04ba12ce5b.tar.bz2
dotty-6a3aab8241cc5379bcffb7644bdbaa04ba12ce5b.zip
Allow byname repated parameters
Implements #499
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala7
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala9
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala17
-rw-r--r--src/dotty/tools/dotc/core/Types.scala6
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala22
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala7
6 files changed, 44 insertions, 24 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 0c13d1ecc..f7904abc0 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -289,8 +289,13 @@ object desugar {
val caseParams = constrVparamss.head.toArray
val productElemMeths = for (i <- 0 until arity) yield
syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
+ def isRepeated(tree: Tree): Boolean = tree match {
+ case PostfixOp(_, nme.raw.STAR) => true
+ case ByNameTypeTree(tree1) => isRepeated(tree1)
+ case _ => false
+ }
val hasRepeatedParam = constrVparamss.exists(_.exists {
- case ValDef(_, PostfixOp(_, nme.raw.STAR), _) => true
+ case ValDef(_, tpt, _) => isRepeated(tpt)
case _ => false
})
val copyMeths =
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index a7f89337c..1ba7acb48 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -160,11 +160,12 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
case _ => Nil
}
- /** Is tpt a vararg type of the form T* ? */
- def isRepeatedParamType(tpt: Tree)(implicit ctx: Context) = tpt match {
+ /** Is tpt a vararg type of the form T* or => T*? */
+ def isRepeatedParamType(tpt: Tree)(implicit ctx: Context): Boolean = tpt match {
+ case ByNameTypeTree(tpt1) => isRepeatedParamType(tpt1)
case tpt: TypeTree => tpt.typeOpt.isRepeatedParam
- case AppliedTypeTree(Select(_, tpnme.REPEATED_PARAM_CLASS), _) => true
- case _ => false
+ case AppliedTypeTree(Select(_, tpnme.REPEATED_PARAM_CLASS), _) => true
+ case _ => false
}
/** Is name a left-associative operator? */
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index de42b3e5f..a5e24c5ff 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -279,15 +279,20 @@ class TypeApplications(val self: Type) extends AnyVal {
default
}
}
-
+
/** Translate a type of the form From[T] to To[T], keep other types as they are.
* `from` and `to` must be static classes, both with one type parameter, and the same variance.
+ * Do the same for by name types => From[T] and => To[T]
*/
- def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type =
- if (self.derivesFrom(from))
- if (ctx.erasedTypes) to.typeRef
- else RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
- else self
+ def translateParameterized(from: ClassSymbol, to: ClassSymbol)(implicit ctx: Context): Type = self match {
+ case self @ ExprType(tp) =>
+ self.derivedExprType(tp.translateParameterized(from, to))
+ case _ =>
+ if (self.derivesFrom(from))
+ if (ctx.erasedTypes) to.typeRef
+ else RefinedType(to.typeRef, to.typeParams.head.name, self.member(from.typeParams.head.name).info)
+ else self
+ }
/** If this is repeated parameter type, its underlying Seq type,
* or, if isJava is true, Array type, else the type itself.
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index e290e8868..595732b37 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2066,14 +2066,16 @@ object Types {
def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType)
def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = {
- def paramInfo(param: Symbol): Type = param.info match {
+ def translateRepeated(tp: Type): Type = tp match {
+ case tp @ ExprType(tp1) => tp.derivedExprType(translateRepeated(tp1))
case AnnotatedType(annot, tp) if annot matches defn.RepeatedAnnot =>
- val typeSym = param.info.typeSymbol.asClass
+ val typeSym = tp.typeSymbol.asClass
assert(typeSym == defn.SeqClass || typeSym == defn.ArrayClass)
tp.translateParameterized(typeSym, defn.RepeatedParamClass)
case tp =>
tp
}
+ def paramInfo(param: Symbol): Type = translateRepeated(param.info)
def transformResult(mt: MethodType) =
resultType.subst(params, (0 until params.length).toList map (MethodParam(mt, _)))
apply(params map (_.name.asTermName), params map paramInfo)(transformResult _)
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index cbefb81fe..dd2c9bcaa 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -754,17 +754,21 @@ object Parsers {
if (in.token == ARROW) atPos(in.skipToken()) { ByNameTypeTree(argType()) }
else argType()
- /** ParamType ::= FunArgType | ArgType `*'
+ /** ParamType ::= [`=>'] ParamValueType
*/
def paramType(): Tree =
- if (in.token == ARROW) funArgType()
- else {
- val t = argType()
- if (isIdent(nme.raw.STAR)) {
- in.nextToken()
- atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) }
- } else t
- }
+ if (in.token == ARROW) atPos(in.skipToken()) { ByNameTypeTree(paramValueType()) }
+ else paramValueType()
+
+ /** ParamValueType ::= Type [`*']
+ */
+ def paramValueType(): Tree = {
+ val t = typ()
+ if (isIdent(nme.raw.STAR)) {
+ in.nextToken()
+ atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) }
+ } else t
+ }
/** TypeArgs ::= `[' ArgType {`,' ArgType} `]'
*/
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index c5bd70c1e..dd30c45c0 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -330,7 +330,7 @@ trait Applications extends Compatibility { self: Typer =>
case arg :: Nil if isVarArg(arg) =>
addTyped(arg, formal)
case _ =>
- val elemFormal = formal.argTypesLo.head
+ val elemFormal = formal.widenExpr.argTypesLo.head
args foreach (addTyped(_, elemFormal))
makeVarArg(args.length, elemFormal)
}
@@ -842,7 +842,10 @@ trait Applications extends Compatibility { self: Typer =>
val tparams = ctx.newTypeParams(alt1.symbol, tp1.paramNames, EmptyFlags, tp1.instantiateBounds)
isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
case tp1: MethodType =>
- def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.argTypesHi.head else tp
+ def repeatedToSingle(tp: Type): Type = tp match {
+ case tp @ ExprType(tp1) => tp.derivedExprType(repeatedToSingle(tp1))
+ case _ => if (tp.isRepeatedParam) tp.argTypesHi.head else tp
+ }
isApplicable(alt2, tp1.paramTypes map repeatedToSingle, WildcardType) ||
tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly]
case _ =>