aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-22 18:34:00 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-22 18:58:18 +0100
commit6ed666c4be5bc4904c926a265d711b85f729d4b3 (patch)
treebfd51f640ecd89eb3a6d111213747af77c68dde2
parent108be8880688653de490975f29f6ae469e9f3e6a (diff)
downloaddotty-6ed666c4be5bc4904c926a265d711b85f729d4b3.tar.gz
dotty-6ed666c4be5bc4904c926a265d711b85f729d4b3.tar.bz2
dotty-6ed666c4be5bc4904c926a265d711b85f729d4b3.zip
Typing by-name parameters with ExprTypes.
To avoid duplication between by-name parameters and expr types, we treat by-name parameters as as having ExprType. A part of this is introducing ByNameTypeTree, a specific tree class for => T types.
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala5
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala7
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala15
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala3
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala1
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala4
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala6
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala4
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala5
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala4
-rw-r--r--src/dotty/tools/dotc/typer/EtaExpansion.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
15 files changed, 40 insertions, 30 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index bf32ffcd9..e6c43acbb 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -651,10 +651,7 @@ object desugar {
Select(t, op)
}
case PrefixOp(op, t) =>
- if ((ctx.mode is Mode.Type) && op == nme.ARROWkw)
- AppliedTypeTree(ref(defn.ByNameParamClass.typeRef), t)
- else
- Select(t, nme.UNARY_PREFIX ++ op)
+ Select(t, nme.UNARY_PREFIX ++ op)
case Parens(t) =>
t
case Tuple(ts) =>
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 0d3f1970f..29ff492d4 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -176,13 +176,6 @@ trait TreeInfo[T >: Untyped] { self: Trees.Instance[T] =>
case _ => false
}
- /** Is tpt a by-name parameter type of the form => T? */
- def isByNameParamType(tpt: Tree)(implicit ctx: Context) = tpt match {
- case tpt: TypeTree => tpt.typeOpt isRef defn.ByNameParamClass
- case AppliedTypeTree(Select(_, tpnme.BYNAME_PARAM_CLASS), _) => true
- case _ => false
- }
-
/** Is name a left-associative operator? */
def isLeftAssoc(operator: Name) = operator.nonEmpty && (operator.last != ':')
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 183e5a2e4..12d71e32f 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -620,6 +620,12 @@ object Trees {
def forwardTo = tpt
}
+ /** => T */
+ case class ByNameTypeTree[-T >: Untyped] private[ast] (result: Tree[T])
+ extends Tree[T] {
+ type ThisTree[-T >: Untyped] = ByNameTypeTree[T]
+ }
+
/** >: lo <: hi */
case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T])
extends Tree[T] {
@@ -841,6 +847,7 @@ object Trees {
type OrTypeTree = Trees.OrTypeTree[T]
type RefinedTypeTree = Trees.RefinedTypeTree[T]
type AppliedTypeTree = Trees.AppliedTypeTree[T]
+ type ByNameTypeTree = Trees.ByNameTypeTree[T]
type TypeBoundsTree = Trees.TypeBoundsTree[T]
type Bind = Trees.Bind[T]
type Alternative = Trees.Alternative[T]
@@ -1014,6 +1021,10 @@ object Trees {
case tree: AppliedTypeTree if (tpt eq tree.tpt) && (args eq tree.args) => tree
case _ => finalize(tree, untpd.AppliedTypeTree(tpt, args))
}
+ def ByNameTypeTree(tree: Tree, result: Tree): ByNameTypeTree = tree match {
+ case tree: ByNameTypeTree if (result eq tree.result) => tree
+ case _ => finalize(tree, untpd.ByNameTypeTree(result))
+ }
def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree = tree match {
case tree: TypeBoundsTree if (lo eq tree.lo) && (hi eq tree.hi) => tree
case _ => finalize(tree, untpd.TypeBoundsTree(lo, hi))
@@ -1128,6 +1139,8 @@ object Trees {
cpy.RefinedTypeTree(tree, transform(tpt), transformSub(refinements))
case AppliedTypeTree(tpt, args) =>
cpy.AppliedTypeTree(tree, transform(tpt), transform(args))
+ case ByNameTypeTree(result) =>
+ cpy.ByNameTypeTree(tree, transform(result))
case TypeBoundsTree(lo, hi) =>
cpy.TypeBoundsTree(tree, transform(lo), transform(hi))
case Bind(name, body) =>
@@ -1233,6 +1246,8 @@ object Trees {
this(this(x, tpt), refinements)
case AppliedTypeTree(tpt, args) =>
this(this(x, tpt), args)
+ case ByNameTypeTree(result) =>
+ this(x, result)
case TypeBoundsTree(lo, hi) =>
this(this(x, lo), hi)
case Bind(name, body) =>
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 8d079fa72..3e2b0d7f9 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -196,6 +196,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree =
untpd.AppliedTypeTree(tpt, args).withType(tpt.tpe.appliedTo(args map (_.tpe))).checked
+ def ByNameTypeTree(result: Tree)(implicit ctx: Context): ByNameTypeTree =
+ untpd.ByNameTypeTree(result).withType(ExprType(result.tpe)).checked
+
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
untpd.TypeBoundsTree(lo, hi).withType(TypeBounds(lo.tpe, hi.tpe)).checked
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index afb3ba63a..3fb21feb7 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -79,6 +79,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] {
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)
def RefinedTypeTree(tpt: Tree, refinements: List[Tree]): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
def AppliedTypeTree(tpt: Tree, args: List[Tree]): AppliedTypeTree = new AppliedTypeTree(tpt, args)
+ def ByNameTypeTree(result: Tree): ByNameTypeTree = new ByNameTypeTree(result)
def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
def Alternative(trees: List[Tree]): Alternative = new Alternative(trees)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index a2527c9f2..a24bdd7d8 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -182,7 +182,7 @@ class Definitions(implicit ctx: Context) {
lazy val BoxedFloatClass = requiredClass("java.lang.Float")
lazy val BoxedDoubleClass = requiredClass("java.lang.Double")
- lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, AnyType)
+ lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, AnyType)
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, SeqType)
@@ -451,7 +451,7 @@ class Definitions(implicit ctx: Context) {
AnyRefAlias,
RepeatedParamClass,
JavaRepeatedParamClass,
- ByNameParamClass,
+ ByNameParamClass2x,
AnyClass,
AnyValClass,
NullClass,
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index f7308c1f1..93db5d624 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -550,10 +550,6 @@ object Types {
case _ => this
}
- /** Widen from => T to T */
- final def widenByName(implicit ctx: Context): Type =
- if (this isRef defn.ByNameParamClass) this.typeArgs.head else this
-
/** Widen type if it is unstable (i.e. an EpxprType, or Termref to unstable symbol */
final def widenIfUnstable(implicit ctx: Context): Type = this match {
case tp: ExprType => tp.resultType.widenIfUnstable
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 2f063fd4c..e7a87b220 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -638,10 +638,8 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
}
else TypeRef(pre, sym.name.asTypeName)
val args = until(end, readTypeRef)
-// if (args.nonEmpty) { // DEBUG
-// println(s"reading app type $tycon $args")
-// }
- tycon.appliedTo(args)
+ if (sym == defn.ByNameParamClass2x) ExprType(args.head)
+ else tycon.appliedTo(args)
case TYPEBOUNDStpe =>
TypeBounds(readTypeRef(), readTypeRef())
case REFINEDtpe =>
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 85289ee0f..f3f87daff 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -647,7 +647,7 @@ object Parsers {
atPos(start, in.skipToken()) { Function(ts, typ()) }
else {
for (t <- ts)
- if (isByNameParamType(t))
+ if (t.isInstanceOf[ByNameTypeTree])
syntaxError("no by-name parameter type allowed here", t.pos)
val tuple = atPos(start) { makeTupleOrParens(ts) }
infixTypeRest(refinedTypeRest(withTypeRest(simpleTypeRest(tuple))))
@@ -748,7 +748,7 @@ object Parsers {
/** FunArgType ::= ArgType | `=>' ArgType
*/
val funArgType = () =>
- if (in.token == ARROW) atPos(in.skipToken()) { PrefixOp(nme.ARROWkw, argType()) }
+ if (in.token == ARROW) atPos(in.skipToken()) { ByNameTypeTree(argType()) }
else argType()
/** ParamType ::= FunArgType | ArgType `*'
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 3636731aa..df9986d5f 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -99,7 +99,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
val cls = tycon.typeSymbol
if (cls.typeParams.length == args.length) {
if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*"
- if (cls == defn.ByNameParamClass) return "=> " ~ toText(args.head)
if (defn.FunctionClasses contains cls) return toTextFunction(args)
if (defn.TupleClasses contains cls) return toTextTuple(args)
}
@@ -112,8 +111,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case _ => nameString(tp.symbol)
}
}
+ case ExprType(result) =>
+ return "=> " ~ toText(result)
case typer.Inferencing.FunProto(args, resultType, _) =>
- "funproto(" ~ toTextGlobal(args, ", ") ~ "):" ~ toText(resultType)
+ return "funproto(" ~ toTextGlobal(args, ", ") ~ "):" ~ toText(resultType)
case _ =>
}
super.toText(tp)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 860a7be80..9efa7d49e 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -360,7 +360,7 @@ trait Applications extends Compatibility { self: Typer =>
init()
def addArg(arg: Tree, formal: Type): Unit =
- typedArgBuf += adaptInterpolated(arg, formal.widenByName)
+ typedArgBuf += adaptInterpolated(arg, formal.widenExpr)
def makeVarArg(n: Int, elemFormal: Type): Unit = {
val args = typedArgBuf.takeRight(n).toList
@@ -433,7 +433,7 @@ trait Applications extends Compatibility { self: Typer =>
/** Subclass of Application for type checking an Apply node with untyped arguments. */
class ApplyToUntyped(app: untpd.Apply, fun: Tree, methRef: TermRef, proto: FunProto, resultType: Type)(implicit ctx: Context)
extends TypedApply(app, fun, methRef, proto.args, resultType) {
- def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenByName)
+ def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenExpr)
def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg)
}
diff --git a/src/dotty/tools/dotc/typer/EtaExpansion.scala b/src/dotty/tools/dotc/typer/EtaExpansion.scala
index 782e5382f..16a02ba5c 100644
--- a/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -58,7 +58,7 @@ object EtaExpansion {
methType match {
case MethodType(paramNames, paramTypes) =>
(args, paramNames, paramTypes).zipped map { (arg, name, tp) =>
- if (tp isRef defn.ByNameParamClass) arg
+ if (tp.isInstanceOf[ExprType]) arg
else liftArg(defs, arg, if (name contains '$') "" else name.toString + "$")
}
case _ =>
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index b32535167..3878e5235 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -263,7 +263,7 @@ trait Implicits { self: Typer =>
*/
def inferImplicit(pt: Type, argument: Tree, pos: Position)(implicit ctx: Context): SearchResult = track("inferImplicit") {
ctx.traceIndented(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", show = true) {
- assert(!(pt isRef defn.ByNameParamClass))
+ assert(!pt.isInstanceOf[ExprType])
val isearch =
if (ctx.settings.explaintypes.value) new ExplainedImplicitSearch(pt, argument, pos)
else new ImplicitSearch(pt, argument, pos)
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 81e03f696..c306b07f3 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -30,7 +30,7 @@ object Inferencing {
* 3. there is an implicit conversion from `tp` to `pt`.
*/
def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean =
- tp.widenByName <:< pt.widenByName || viewExists(tp, pt)
+ tp.widenExpr <:< pt.widenExpr || viewExists(tp, pt)
/** Test compatibility after normalization in a fresh typerstate. */
def normalizedCompatible(tp: Type, pt: Type)(implicit ctx: Context) = {
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 54a299291..99d5f6b98 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -707,6 +707,11 @@ class Typer extends Namer with Applications with Implicits {
cpy.AppliedTypeTree(tree, tpt1, args1) withType tpt1.tpe.appliedTo(args1.tpes)
}
+ def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(implicit ctx: Context): ByNameTypeTree = track("typedByNameTypeTree") {
+ val result1 = typed(tree.result)
+ cpy.ByNameTypeTree(tree, result1) withType ExprType(result1.tpe)
+ }
+
def typedTypeBoundsTree(tree: untpd.TypeBoundsTree)(implicit ctx: Context): TypeBoundsTree = track("typedTypeBoundsTree") {
val TypeBoundsTree(lo, hi) = desugar.typeBoundsTree(tree)
val lo1 = typed(lo)
@@ -875,6 +880,7 @@ class Typer extends Namer with Applications with Implicits {
case tree: untpd.OrTypeTree => typedOrTypeTree(tree)
case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree)
case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree)
+ case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree)
case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree)
case tree: untpd.Alternative => typedAlternative(tree, pt)
case tree: untpd.Import => typedImport(tree, sym)