aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-10-15 14:55:00 +0200
committerMartin Odersky <odersky@gmail.com>2013-10-15 14:55:09 +0200
commit4f05aa9bf0d3c29eae720115433ffe29b239d70f (patch)
treedbc9c8a430351c0a5b372adc9442c1b74ff92d54 /src/dotty/tools/dotc
parentcdafc3058566d5eede8995f0812fe57a3a1ad6ee (diff)
downloaddotty-4f05aa9bf0d3c29eae720115433ffe29b239d70f.tar.gz
dotty-4f05aa9bf0d3c29eae720115433ffe29b239d70f.tar.bz2
dotty-4f05aa9bf0d3c29eae720115433ffe29b239d70f.zip
Changes to adaptation and local type inference.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/Compiler.scala2
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala4
-rw-r--r--src/dotty/tools/dotc/core/TyperState.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala31
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala11
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala6
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala28
7 files changed, 52 insertions, 41 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index e6675237a..9c71bdc96 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -23,7 +23,7 @@ class Compiler {
.withOwner(defn.RootClass)
.withTyper(new Typer)
.withNewMode(Mode.ImplicitsEnabled)
- .withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx), committable = true))
+ .withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx), isCommittable = true))
def addImport(ctx: Context, sym: Symbol) =
ctx.fresh.withImportInfo(ImportInfo.rootImport(sym)(ctx))
(start.withRunInfo(new RunInfo(start)) /: rootImports)(addImport)
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 3de6337b1..d06670b94 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -288,8 +288,8 @@ object Contexts {
def withPeriod(period: Period): this.type = { this.period = period; this }
def withNewMode(mode: Mode): this.type = { this.mode = mode; this }
def withTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
- def withNewTyperState: this.type = withTyperState(typerState.fresh(committable = true))
- def withExploreTyperState: this.type = withTyperState(typerState.fresh(committable = false))
+ def withNewTyperState: this.type = withTyperState(typerState.fresh(isCommittable = true))
+ def withExploreTyperState: this.type = withTyperState(typerState.fresh(isCommittable = false))
def withPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
def withOwner(owner: Symbol): this.type = { this.owner = owner; this }
def withSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala
index a4663f824..8fbd3502c 100644
--- a/src/dotty/tools/dotc/core/TyperState.scala
+++ b/src/dotty/tools/dotc/core/TyperState.scala
@@ -29,9 +29,10 @@ class TyperState(val reporter: Reporter) extends DotClass with Showable {
def undetVars_=(vs: Set[TypeVar]): Unit = unsupported("undetVars_=")
def instType_=(m: SimpleMap[TypeVar, Type]): Unit = unsupported("instType_=")
- def fresh(committable: Boolean): TyperState = this
+ def fresh(isCommittable: Boolean): TyperState = this
def commit()(implicit ctx: Context): Unit = unsupported("commit")
+ def isCommittable: Boolean = false
@elidable(elidable.FINER)
def checkConsistent(implicit ctx: Context) = ()
@@ -44,7 +45,7 @@ class TyperState(val reporter: Reporter) extends DotClass with Showable {
override def toText(printer: Printer): Text = "ImmutableTyperState"
}
-class MutableTyperState(previous: TyperState, reporter: Reporter, committable: Boolean)
+class MutableTyperState(previous: TyperState, reporter: Reporter, override val isCommittable: Boolean)
extends TyperState(reporter) {
private var myConstraint: Constraint = previous.constraint
@@ -66,8 +67,8 @@ extends TyperState(reporter) {
}
override def instType_=(m: SimpleMap[TypeVar, Type]): Unit = myInstType = m
- override def fresh(committable: Boolean): TyperState =
- new MutableTyperState(this, new StoreReporter, committable)
+ override def fresh(isCommittable: Boolean): TyperState =
+ new MutableTyperState(this, new StoreReporter, isCommittable)
/** Commit typer state so that its information is copied into current typer state
* In addition (1) the owning state of undetermined or temporarily instantiated
@@ -104,7 +105,7 @@ extends TyperState(reporter) {
def err(msg: String, what: Showable) = s"$msg: ${show(what)}\n${show(this)}"
for (tvar <- undetVars)
assert(constraint(tvar.origin).exists, err("unconstrained type var", tvar.origin))
- if (committable) {
+ if (isCommittable) {
val undetParams = undetVars map (_.origin)
for (param <- constraint.domainParams)
assert(undetParams contains param, err("junk constraint on", param))
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 832693b98..05db467f0 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -27,6 +27,9 @@ import collection.mutable
/** Implicit resolution */
object Implicits {
+ private def disableImplicits(ctx: Context): Context =
+ if (ctx == NoContext) ctx else ctx retractMode Mode.ImplicitsEnabled
+
/** A common base class of contextual implicits and of-type implicits which
* represents as set of implicit references.
*/
@@ -61,7 +64,7 @@ object Implicits {
class OfTypeImplicits(tp: Type, val companionRefs: TermRefSet)(initctx: Context)
extends ImplicitRefs {
assert(initctx.typer != null)
- implicit val ctx: Context = initctx retractMode ImplicitsEnabled
+ implicit val ctx: Context = disableImplicits(initctx)
val refs: List[TermRef] = companionRefs.toList flatMap (_.implicitMembers)
/** The implicit references that are eligible for expected type `tp` */
@@ -76,8 +79,7 @@ object Implicits {
* @param outerCtx the next outer context that makes visible further implicits
*/
class ContextualImplicits(val refs: List[TermRef], val outerCtx: Context)(initctx: Context) extends ImplicitRefs {
- implicit val ctx: Context =
- if (initctx == NoContext) initctx else initctx retractMode Mode.ImplicitsEnabled
+ implicit val ctx: Context = disableImplicits(initctx)
private val eligibleCache = new mutable.HashMap[Type, List[TermRef]]
@@ -259,7 +261,7 @@ trait Implicits { self: Typer =>
* @param pos The position where errors should be reported.
*/
def inferImplicit(pt: Type, argument: Tree, pos: Position)(implicit ctx: Context): SearchResult = track("inferImplicit") {
- ctx.traceIndented(s"search implicit ${pt.show}, arg = ${argument.show}", show = true) {
+ ctx.traceIndented(s"search implicit ${pt.show}, arg = ${argument.show}: ${argument.tpe.show}", show = true) {
val isearch =
if (ctx.settings.explaintypes.value) new ExplainedImplicitSearch(pt, argument, pos)
else new ImplicitSearch(pt, argument, pos)
@@ -275,7 +277,7 @@ trait Implicits { self: Typer =>
/** An implicit search; parameters as in `inferImplicit` */
class ImplicitSearch(protected val pt: Type, protected val argument: Tree, pos: Position)(implicit ctx: Context) {
- val initctx: Context = ctx.fresh.withNewTyperState.retractMode(ImplicitsEnabled)
+ val initctx: Context = disableImplicits(ctx.fresh.withNewTyperState)
def nestedContext = initctx.fresh.withNewTyperState
protected def nonMatchingImplicit(ref: TermRef): SearchFailure = NoImplicitMatches
@@ -287,19 +289,18 @@ trait Implicits { self: Typer =>
def searchImplicits(eligible: List[TermRef], contextual: Boolean): SearchResult = {
/** Try to typecheck an implicit reference */
- def typedImplicit(ref: TermRef)(implicit ctx: Context): SearchResult = track("typedImplicit") {
- val id = Ident(ref).withPos(pos)
- val tree =
- if (argument.isEmpty)
- adapt(id, pt)
- else
- typed(untpd.Apply(untpd.TypedSplice(id), untpd.TypedSplice(argument) :: Nil), pt)
+ def typedImplicit(ref: TermRef)(implicit ctx: Context): SearchResult = track("typedImplicit") { ctx.traceIndented(s"typed implicit $ref, pt = $pt, implicitsEnabled == ${ctx.mode is ImplicitsEnabled}", show = true) {
+ var generated: Tree = Ident(ref).withPos(pos)
+ if (!argument.isEmpty)
+ generated = typedUnadapted(
+ untpd.Apply(untpd.TypedSplice(generated), untpd.TypedSplice(argument) :: Nil), pt)
+ val generated1 = interpolateAndAdapt(generated, pt)
lazy val shadowing =
typed(untpd.Ident(ref.name), ref)(nestedContext).tpe
if (ctx.typerState.reporter.hasErrors) nonMatchingImplicit(ref)
else if (contextual && !(shadowing =:= ref)) shadowedImplicit(ref, shadowing)
- else SearchSuccess(tree)(ref, ctx.typerState)
- }
+ else SearchSuccess(generated)(ref, ctx.typerState)
+ }}
/** Given a list of implicit references, produce a list of all implicit search successes,
* where the first is supposed to be the best one.
@@ -312,7 +313,7 @@ trait Implicits { self: Typer =>
case fail: SearchFailure =>
rankImplicits(pending1, acc)
case best: SearchSuccess =>
- val newPending = pending filterNot (isAsGood(_, best.ref))
+ val newPending = pending1 filterNot (isAsGood(_, best.ref)(nestedContext.withExploreTyperState))
rankImplicits(newPending, best :: acc)
}
case nil => acc
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 8d85c1911..cbce206ef 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -10,7 +10,7 @@ import annotation.unchecked
import util.Positions._
import util.Stats
import Decorators._
-import ErrorReporting.InfoString
+import ErrorReporting.{errorType, InfoString}
object Inferencing {
@@ -113,7 +113,7 @@ object Inferencing {
* any uninstantiated type variables, provided that
* - the instance type for the variable is not Nothing or Null
* - the overall result of `isFullYDefined` is `true`.
- * Variables that are succesfully minimized do not count as uninstantiated.
+ * Variables that are successfully minimized do not count as uninstantiated.
*/
def isFullyDefined(tp: Type, forceIt: Boolean = false)(implicit ctx: Context): Boolean = {
val nestedCtx = ctx.fresh.withNewTyperState
@@ -122,6 +122,13 @@ object Inferencing {
result
}
+ def forceFullyDefined(tp: Type)(implicit ctx: Context): Boolean =
+ isFullyDefined(tp, forceIt = true)
+
+ def fullyDefinedType(tp: Type, what: String, pos: Position)(implicit ctx: Context) =
+ if (forceFullyDefined(tp)) tp
+ else errorType(i"internal error: type of $what $tp is not fully defined", pos)
+
private class IsFullyDefinedAccumulator(forceIt: Boolean)(implicit ctx: Context) extends TypeAccumulator[Boolean] {
def traverse(tp: Type): Boolean = apply(true, tp)
def apply(x: Boolean, tp: Type) = !x || isOK(tp) && foldOver(x, tp)
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 72ed20454..7582b0d0d 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -7,7 +7,7 @@ import ast._
import Trees._, Constants._, StdNames._, Scopes._, Denotations._
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
import ast.desugar, ast.desugar._
-import Inferencing.AnySelectionProto
+import Inferencing.{fullyDefinedType, AnySelectionProto}
import util.Positions._
import util.SourcePosition
import collection.mutable
@@ -385,7 +385,9 @@ class Namer { typer: Typer =>
tp & itpe
}
}
- inherited orElse typedAheadExpr(mdef.rhs).tpe.widen
+ def rhsType = interpolateAndAdapt(typedAheadExpr(mdef.rhs), WildcardType).tpe.widen
+ def lhsType = fullyDefinedType(rhsType, "right-hand side", mdef.pos)
+ inherited orElse lhsType
}
paramFn(typedAheadType(mdef.tpt, pt).tpe)
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 1e3049f7e..11de19648 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -458,7 +458,7 @@ class Typer extends Namer with Applications with Implicits {
val result = cpy.Block(tree, stats1, expr1).withType(blockType(stats1, expr1.tpe))
val leaks = CheckTrees.escapingRefs(result)
if (leaks.isEmpty) result
- else if (isFullyDefined(pt)) {
+ else if (forceFullyDefined(pt)) {
val expr2 = typed(untpd.Typed(untpd.TypedSplice(expr1), untpd.TypeTree(pt)))
untpd.Block(stats1, expr2) withType expr2.tpe
} else errorTree(result,
@@ -493,7 +493,7 @@ class Typer extends Namer with Applications with Implicits {
if (!param.tpt.isEmpty) param
else {
val paramType =
- if (isFullyDefined(formal)) formal
+ if (forceFullyDefined(formal)) formal
else errorType("missing parameter type", param.pos)
cpy.ValDef(param, param.mods, param.name, untpd.TypeTree(paramType), param.rhs)
}
@@ -521,12 +521,10 @@ class Typer extends Namer with Applications with Implicits {
typed(desugar.makeCaseLambda(tree.cases) withPos tree.pos, pt)
case _ =>
val sel1 = typedExpr(tree.selector)
- val selType =
- if (isFullyDefined(sel1.tpe)) sel1.tpe
- else errorType("internal error: type of pattern selector is not fully defined", tree.pos)
+ val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos)
/** gadtSyms = "all type parameters of enclosing methods that appear
- * non-variantly in the selector type
+ * non-variantly in the selector type"
*/
val gadtSyms: Set[Symbol] = {
val accu = new TypeAccumulator[Set[Symbol]] {
@@ -863,11 +861,8 @@ class Typer extends Namer with Applications with Implicits {
}
def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = ctx.traceIndented (s"typing ${tree.show}", show = true) {
- try {
- val tree1 = typedUnadapted(tree, pt)
- ctx.interpolateUndetVars(tree1.tpe.widen, tree1.pos)
- adapt(tree1, pt)
- } catch {
+ try interpolateAndAdapt(typedUnadapted(tree, pt), pt)
+ catch {
case ex: FatalTypeError => errorTree(tree, ex.getMessage)
}
}
@@ -927,6 +922,11 @@ class Typer extends Namer with Applications with Implicits {
fallBack
}
+ def interpolateAndAdapt(tree: Tree, pt: Type)(implicit ctx: Context) = {
+ ctx.interpolateUndetVars(tree.tpe.widen, tree.pos)
+ adapt(tree, pt)
+ }
+
/** (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
* (0) Convert expressions with constant types to literals (unless in interactive/scaladoc mode)
*/
@@ -965,7 +965,7 @@ class Typer extends Namer with Applications with Implicits {
* (14) When in mode EXPRmode, apply a view
* If all this fails, error
*/
- def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = track("adapt") { ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", show = false) {
+ def adapt(tree: Tree, pt: Type)(implicit ctx: Context): Tree = track("adapt") { ctx.traceIndented(i"adapting $tree of type ${tree.tpe} to $pt", show = true) {
assert(pt.exists)
@@ -1034,7 +1034,7 @@ class Typer extends Namer with Applications with Implicits {
implicitArgError(i"no implicit argument of type $formal found for $where" + failure.postscript)
}
}
- adapt(tpd.Apply(tree, args), pt)
+ adapt(tpd.Apply(tree, args), wtp.resultType)
case wtp: MethodType if !pt.isInstanceOf[SingletonType] =>
if ((defn.isFunctionType(pt) || (pt eq AnyFunctionProto)) &&
!tree.symbol.isConstructor)
@@ -1064,7 +1064,7 @@ class Typer extends Namer with Applications with Implicits {
if defn.isFunctionType(wtp) && !defn.isFunctionType(pt) =>
pt match {
case SAMType(meth)
- if wtp <:< meth.info.toFunctionType && isFullyDefined(pt, forceIt = false) =>
+ if wtp <:< meth.info.toFunctionType && isFullyDefined(pt) =>
return cpy.Closure(tree, Nil, id, TypeTree(pt)).withType(pt)
case _ =>
}