aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-17 22:32:10 +0200
committerMartin Odersky <odersky@gmail.com>2016-09-17 22:33:14 +0200
commit528f6b0524c465a3e795aa5bb538c680956bf6d2 (patch)
tree2a0f48e7f1ea2c9a52c15d0c9038712173804d41 /src/dotty
parentc420b4cc0573e88bf301d4e020e2ad91b26806d0 (diff)
downloaddotty-528f6b0524c465a3e795aa5bb538c680956bf6d2.tar.gz
dotty-528f6b0524c465a3e795aa5bb538c680956bf6d2.tar.bz2
dotty-528f6b0524c465a3e795aa5bb538c680956bf6d2.zip
Fix #1503 - be careful where to insert an apply.
`apply` nodes should not be inserted in the result parts of a block, if-then-else, match, or try. Instead they should be added to the surrounding statement.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala2
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala10
-rw-r--r--src/dotty/tools/dotc/core/Types.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala2
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala16
6 files changed, 29 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index 70d8f2d5e..631b1bf8d 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -699,7 +699,7 @@ object desugar {
Apply(Select(left, op), args)
} else {
val x = ctx.freshName().toTermName
- Block(
+ new InfixOpBlock(
ValDef(x, TypeTree(), left).withMods(synthetic),
Apply(Select(right, op), Ident(x)))
}
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index cef78c6e6..6bbb76b89 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -63,6 +63,16 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
class PolyTypeDef(name: TypeName, override val tparams: List[TypeDef], rhs: Tree)
extends TypeDef(name, rhs)
+ /** A block arising from a right-associative infix operation, where, e.g.
+ *
+ * a +: b
+ *
+ * is expanded to
+ *
+ * { val x = a; b.+:(x) }
+ */
+ class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp)
+
// ----- TypeTrees that refer to other tree's symbols -------------------
/** A type tree that gets its type from some other tree's symbol. Enters the
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index cb423e186..d788b7e69 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -927,7 +927,7 @@ object Types {
def narrow(implicit ctx: Context): TermRef =
TermRef(NoPrefix, ctx.newSkolem(this))
- /** Useful for diagnsotics: The underlying type if this type is a type proxy,
+ /** Useful for diagnostics: The underlying type if this type is a type proxy,
* otherwise NoType
*/
def underlyingIfProxy(implicit ctx: Context) = this match {
@@ -935,7 +935,10 @@ object Types {
case _ => NoType
}
- // ----- Normalizing typerefs over refined types ----------------------------
+ /** If this is a FunProto or PolyProto, WildcardType, otherwise this */
+ def notApplied: Type = this
+
+ // ----- Normalizing typerefs over refined types ----------------------------
/** If this normalizes* to a refinement type that has a refinement for `name` (which might be followed
* by other refinements), and the refined info is a type alias, return the alias,
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index a9212e5d6..20850e21d 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -652,7 +652,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
/** Overridden in ReTyper to handle primitive operations that can be generated after erasure */
protected def handleUnexpectedFunType(tree: untpd.Apply, fun: Tree)(implicit ctx: Context): Tree =
- throw new Error(s"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}")
+ throw new Error(i"unexpected type.\n fun = $fun,\n methPart(fun) = ${methPart(fun)},\n methPart(fun).tpe = ${methPart(fun).tpe},\n tpe = ${fun.tpe}")
def typedNamedArgs(args: List[untpd.Tree])(implicit ctx: Context) =
for (arg @ NamedArg(id, argtpt) <- args) yield {
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index f209c99be..41628f0dc 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -182,6 +182,8 @@ object ProtoTypes {
if ((args eq this.args) && (resultType eq this.resultType) && (typer eq this.typer)) this
else new FunProto(args, resultType, typer)
+ override def notApplied = WildcardType
+
/** Forget the types of any arguments that have been typed producing a constraint in a
* typer state that is not yet committed into the one of the current context `ctx`.
* This is necessary to avoid "orphan" PolyParams that are referred to from
@@ -319,6 +321,8 @@ object ProtoTypes {
if ((targs eq this.targs) && (resType eq this.resType)) this
else PolyProto(targs, resType)
+ override def notApplied = WildcardType
+
def map(tm: TypeMap)(implicit ctx: Context): PolyProto =
derivedPolyProto(targs mapConserve tm, tm(resultType))
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 3f8c421d9..c59cd38c3 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -572,7 +572,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = track("typedBlock") {
val exprCtx = index(tree.stats)
val stats1 = typedStats(tree.stats, ctx.owner)
- val expr1 = typedExpr(tree.expr, pt)(exprCtx)
+ val ept = if (tree.isInstanceOf[untpd.InfixOpBlock]) pt else pt.notApplied
+ val expr1 = typedExpr(tree.expr, ept)(exprCtx)
ensureNoLocalRefs(
assignType(cpy.Block(tree)(stats1, expr1), stats1, expr1), pt, localSyms(stats1))
}
@@ -619,8 +620,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context) = track("typedIf") {
val cond1 = typed(tree.cond, defn.BooleanType)
- val thenp1 = typed(tree.thenp, pt)
- val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt)
+ val thenp1 = typed(tree.thenp, pt.notApplied)
+ val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied)
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
}
@@ -793,7 +794,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val selType = widenForMatchSelector(
fullyDefinedType(sel1.tpe, "pattern selector", tree.pos))
- val cases1 = typedCases(tree.cases, selType, pt)
+ val cases1 = typedCases(tree.cases, selType, pt.notApplied)
val cases2 = harmonize(cases1).asInstanceOf[List[CaseDef]]
assignType(cpy.Match(tree)(sel1, cases2), cases2)
}
@@ -920,8 +921,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = track("typedTry") {
- val expr1 = typed(tree.expr, pt)
- val cases1 = typedCases(tree.cases, defn.ThrowableType, pt)
+ val expr1 = typed(tree.expr, pt.notApplied)
+ val cases1 = typedCases(tree.cases, defn.ThrowableType, pt.notApplied)
val finalizer1 = typed(tree.finalizer, defn.UnitType)
val expr2 :: cases2x = harmonize(expr1 :: cases1)
val cases2 = cases2x.asInstanceOf[List[CaseDef]]
@@ -1535,8 +1536,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
/** If this tree is a select node `qual.name`, try to insert an implicit conversion
- * `c` around `qual` so that `c(qual).name` conforms to `pt`. If that fails
- * return `tree` itself.
+ * `c` around `qual` so that `c(qual).name` conforms to `pt`.
*/
def tryInsertImplicitOnQualifier(tree: Tree, pt: Type)(implicit ctx: Context): Option[Tree] = ctx.traceIndented(i"try insert impl on qualifier $tree $pt") {
tree match {