aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-11-07 21:43:59 +0100
committerMartin Odersky <odersky@gmail.com>2013-11-07 21:43:59 +0100
commit067ef2076cfcf7864b840ddf38c514ff67f52c64 (patch)
tree3b974ba717ecc08ab37d8dfb49c02f4f74d5eb5a
parent514801453e240610a0ba68fff7305355a7d204e1 (diff)
downloaddotty-067ef2076cfcf7864b840ddf38c514ff67f52c64.tar.gz
dotty-067ef2076cfcf7864b840ddf38c514ff67f52c64.tar.bz2
dotty-067ef2076cfcf7864b840ddf38c514ff67f52c64.zip
Fixing inference problem and block scope problem
1. Typing blocks: forgot to create new scope. Now fixed. 2. The decitsion whether to interpolate a type variable was made based on the type variable's position and the current tree's position. This is too imprecise, because we might have auto-generated trees where all important parts have the same position. We now check for actual tree containment: A type variable can be interpolated for the type of a tree T if T contains the tree which introduced the type variable.
-rw-r--r--src/dotty/tools/dotc/core/Types.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala20
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala6
-rw-r--r--tests/pos/Coder.scala44
6 files changed, 51 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index d07bdc6fc..afb1501f5 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -17,6 +17,7 @@ import Periods._
import util.Positions.Position
import util.Stats.track
import ast.tpd._, printing.Texts._
+import ast.untpd
import transform.Erasure
import printing.Printer
import scala.util.hashing.{ MurmurHash3 => hashing }
@@ -1939,12 +1940,10 @@ object Types {
*
* @param origin The parameter that's tracked by the type variable.
* @param creatorState The typer state in which the variable was created.
- * @param pos The position of the TypeApply tree that introduces
+ * @param owningTree The function part of the TypeApply tree tree that introduces
* the type variable.
*/
- final class TypeVar(val origin: PolyParam, creatorState: TyperState, val pos: Position) extends UncachedProxyType with ValueType {
-
- assert(pos.exists)
+ final class TypeVar(val origin: PolyParam, creatorState: TyperState, val owningTree: untpd.Tree) extends UncachedProxyType with ValueType {
/** The permanent instance type of the the variable, or NoType is none is given yet */
private[core] var inst: Type = NoType
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index e522727a0..78d3f15c1 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -298,7 +298,7 @@ trait Implicits { self: Typer =>
if (!argument.isEmpty)
generated = typedUnadapted(
untpd.Apply(untpd.TypedSplice(generated), untpd.TypedSplice(argument) :: Nil),
- pt)(ctx.fresh.addMode(Mode.RestrictedInterpolation))
+ pt)
val generated1 = interpolateAndAdapt(generated, pt)
lazy val shadowing =
typed(untpd.Ident(ref.name) withPos pos.toSynthetic, ref)(nestedContext).tpe
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 805d64898..42b3564ce 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -211,20 +211,20 @@ object Inferencing {
tracked
}
- /** Interpolate those undetermined type variables whose position
- * is included in the position `pos` of the current tree.
+ /** Interpolate those undetermined type variables in the widened type of this tree
+ * which are introduced by type application contained in the tree.
* If such a variable appears covariantly in type `tp` or does not appear at all,
* approximate it by its lower bound. Otherwise, if it appears contravariantly
* in type `tp` approximate it by its upper bound.
*/
- def interpolateUndetVars(tp: Type, pos: Position): Unit = Stats.track("interpolateUndetVars") {
- println(s"interpolate undet vars in ${tp.show}, pos = $pos, mode = ${ctx.mode}, undets = ${ctx.typerState.undetVars map (tvar => s"${tvar.show}@${tvar.pos}")}")
+ def interpolateUndetVars(tree: Tree): Unit = Stats.track("interpolateUndetVars") {
+ val tp = tree.tpe.widen
+
+ println(s"interpolate undet vars in ${tp.show}, pos = ${tree.pos}, mode = ${ctx.mode}, undets = ${ctx.typerState.undetVars map (tvar => s"${tvar.show}@${tvar.owningTree.pos}")}")
println(s"qualifying undet vars: ${ctx.typerState.undetVars filter qualifies map (_.show)}")
println(s"fulltype: $tp") // !!! DEBUG
- def qualifies(tvar: TypeVar) =
- (pos contains tvar.pos) &&
- !((ctx.mode is Mode.RestrictedInterpolation) && (tvar.pos contains pos))
+ def qualifies(tvar: TypeVar) = tree contains tvar.owningTree
val vs = tp.variances(tvar =>
(ctx.typerState.undetVars contains tvar) && qualifies(tvar))
println(s"variances = $vs")
@@ -236,7 +236,7 @@ object Inferencing {
changed = true
}
if (changed)
- interpolateUndetVars(tp, pos)
+ interpolateUndetVars(tree)
else
for (tvar <- ctx.typerState.undetVars)
if (!(vs contains tvar) && qualifies(tvar)) {
@@ -267,11 +267,11 @@ object Inferencing {
* @param pos The position of the new type variables (relevant for
* interpolateUndetVars
*/
- def newTypeVars(pt: PolyType, pos: Position): List[TypeVar] = {
+ def newTypeVars(pt: PolyType, owningTree: untpd.Tree): List[TypeVar] = {
val state = ctx.typerState
val tvars =
for (n <- (0 until pt.paramNames.length).toList)
- yield new TypeVar(PolyParam(pt, n), state, pos)
+ yield new TypeVar(PolyParam(pt, n), state, owningTree)
state.constraint = state.constraint.updated(pt,
state.constraint(pt) map (_.substParams(pt, tvars)))
tvars
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index e126a794d..1890822b6 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -31,7 +31,6 @@ object Mode {
val ImplicitsEnabled = newMode(2, "ImplicitsEnabled")
val InSuperInit = newMode(3, "InSuperInit")
- val RestrictedInterpolation = newMode(4, "RestrictedInterpolation")
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index e9c6b0d08..08bf6badf 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -833,7 +833,7 @@ class Typer extends Namer with Applications with Implicits {
case tree: untpd.Typed => typedTyped(tree, pt)
case tree: untpd.NamedArg => typedNamedArg(tree, pt)
case tree: untpd.Assign => typedAssign(tree, pt)
- case tree: untpd.Block => typedBlock(desugar.block(tree), pt)
+ case tree: untpd.Block => typedBlock(desugar.block(tree), pt)(ctx.fresh.withNewScope)
case tree: untpd.If => typedIf(tree, pt)
case tree: untpd.Function => typedFunction(tree, pt)
case tree: untpd.Closure => typedClosure(tree, pt)
@@ -933,7 +933,7 @@ class Typer extends Namer with Applications with Implicits {
}
def interpolateAndAdapt(tree: Tree, pt: Type)(implicit ctx: Context) = {
- ctx.interpolateUndetVars(tree.tpe.widen, tree.pos)
+ ctx.interpolateUndetVars(tree)
tree overwriteType tree.tpe.simplified
adapt(tree, pt)
}
@@ -1107,7 +1107,7 @@ class Typer extends Namer with Applications with Implicits {
else {
val tvars = ctx.typerState.withCheckingDisabled {
val tracked = ctx.track(poly)
- ctx.newTypeVars(tracked, tree.pos)
+ ctx.newTypeVars(tracked, tree)
}
adapt(tree appliedToTypes tvars, pt)
}
diff --git a/tests/pos/Coder.scala b/tests/pos/Coder.scala
index 62ceebe80..a168dee4c 100644
--- a/tests/pos/Coder.scala
+++ b/tests/pos/Coder.scala
@@ -8,26 +8,50 @@ class Coder(words: List[String]) {
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
+
+ ('1', "1") match {
+ case (digit, str) => true
+ case _ => false
+ }
+
/** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
- private val charCode: Map[Char, Char] = mnemonics flatMap { ds =>
- val digit = ds._1
- val str = ds._2
- str map (ltr => ltr -> digit)
+ private val charCode0: Map[Char, Char] = mnemonics withFilter {
+ case (digit, str) => true
+ case _ => false
+ } flatMap { x$1 =>
+ x$1 match {
+ case (digit, str) => str map (ltr => ltr -> digit)
+ }
}
-// for ((digit, str) <- mnemonics; ltr <- str) yield ltr -> digit
+ private val charCode: Map[Char, Char] =
+ for ((digit, str) <- mnemonics; ltr <- str) yield ltr -> digit
+/*
/** Maps a word to the digit string it can represent */
- private def wordCode(word: String): String = ???
+ private def wordCode(word: String): String = word map charCode
/** A map from digit strings to the words that represent them */
- private val wordsForNum: Map[String, List[String]] = ???
+ private val wordsForNum: Map[String, List[String]] =
+ words groupBy wordCode withDefaultValue Nil
/** All ways to encode a number as a list of words */
- def encode(number: String): Set[List[String]] = ???
-
+ def encode(number: String): Set[List[String]] =
+ if (number.isEmpty) Set(Nil)
+ else {
+ val x: List[List[String]] = ???
+ x.toSet
+ }
+*/
+/* for {
+ splitPoint <- 1 to number.length
+ word <- number take splitPoint
+ rest <- encode(number drop splitPoint)
+ } yield word :: rest
+*/
+
/** Maps a number to a list of all word phrases that can represent it */
- def translate(number: String): Set[String] = encode(number) map (_ mkString " ")
+// def translate(number: String): Set[String] = encode(number) map (_ mkString " ")
}
/*