aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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/typer/Applications.scala12
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala49
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala2
-rw-r--r--tests/pos/implicits1.scala8
7 files changed, 55 insertions, 32 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index 582853fdf..50d703a28 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -23,7 +23,7 @@ class Compiler {
.withRunInfo(new RunInfo)
.withOwner(defn.RootClass)
.withTyper(new Typer)
- .withMode(Mode.None)
+ .withMode(Mode.ImplicitsEnabled)
.withTyperState(new MutableTyperState(ctx.typerState, new ConsoleReporter()(ctx)))
def addImport(ctx: Context, sym: Symbol) =
ctx.fresh.withImportInfo(ImportInfo.rootImport(sym)(ctx))
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 6bc932429..531df739e 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -163,7 +163,7 @@ object Contexts {
else if (isNonEmptyScopeContext) scope.implicitDecls
else Set()
if (implicitRefs.isEmpty) outer.implicits
- else new ContextualImplicits(implicitRefs, outer.implicits.ctx)
+ else new ContextualImplicits(implicitRefs, outer.implicits.ctx)(this)
}
implicitsCache
}
@@ -330,7 +330,7 @@ object Contexts {
object NoContext extends Context {
lazy val base = unsupported("base")
- override def implicits: ContextualImplicits = new ContextualImplicits(Set(), this)
+ override def implicits: ContextualImplicits = new ContextualImplicits(Set(), this)(this)
}
/** A context base defines state and associated methods that exist once per
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 8af9e0b57..e5e8be05b 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -6,7 +6,7 @@ import core._
import ast.{Trees, untpd, tpd, TreeInfo}
import util.Positions._
import Trees.Untyped
-import Mode.ImplicitsDisabled
+import Mode.ImplicitsEnabled
import Contexts._
import Flags._
import Denotations._
@@ -629,6 +629,14 @@ trait Applications extends Compatibility { self: Typer =>
def isApplicableToTypes(methRef: TermRef, args: List[Type], resultType: Type = WildcardType)(implicit ctx: Context) =
new ApplicableToTypes(methRef, args, resultType)(ctx.fresh.withNewTyperState).success
+ def isApplicableToTypes(tp: Type, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean = tp match {
+ case methRef: TermRef => isApplicableToTypes(methRef, args, resultType)
+ case _ =>
+ val app = tp.member(nme.apply)
+ app.exists && app.hasAltWith(d =>
+ isApplicableToTypes(TermRef(tp, nme.apply).withDenot(d), args, resultType))
+ }
+
/** Is `tp` a subtype of `pt`? */
def testCompatible(tp: Type, pt: Type)(implicit ctx: Context) =
isCompatible(tp, pt)(ctx.fresh.withNewTyperState)
@@ -788,6 +796,6 @@ trait Applications extends Compatibility { self: Typer =>
}
if (isDetermined(candidates)) candidates
- else narrowMostSpecific(candidates)(ctx.addMode(ImplicitsDisabled))
+ else narrowMostSpecific(candidates)(ctx.retractMode(ImplicitsEnabled))
}
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 3676cc214..2a92cf442 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -8,7 +8,7 @@ import util.Positions._
import Contexts._
import Types._
import Flags._
-import Mode.ImplicitsDisabled
+import Mode.ImplicitsEnabled
import Denotations._
import NameOps._
import SymDenotations._
@@ -45,8 +45,9 @@ object Implicits {
* @param tp the type determining the implicit scope
* @param companionRefs the companion objects in the implicit scope.
*/
- class OfTypeImplicits(tp: Type, val companionRefs: Set[TermRef])(implicit ctx: Context)
- extends ImplicitRefs{
+ class OfTypeImplicits(tp: Type, val companionRefs: Set[TermRef])(initctx: Context)
+ extends ImplicitRefs {
+ implicit val ctx: Context = initctx retractMode ImplicitsEnabled
val refs: Set[TermRef] = companionRefs flatMap (_.implicitMembers)
/** The implicit references that are eligible for expected type `tp` */
@@ -57,7 +58,10 @@ object Implicits {
* @param refs the implicit references made visible by the current context
* @param outerCtx the next outer context that makes visible further implicits
*/
- class ContextualImplicits(val refs: Set[TermRef], val outerCtx: Context)(implicit val ctx: Context) extends ImplicitRefs {
+ class ContextualImplicits(val refs: Set[TermRef], val outerCtx: Context)(initctx: Context) extends ImplicitRefs {
+ implicit val ctx: Context =
+ if (initctx == NoContext) initctx else initctx retractMode Mode.ImplicitsEnabled
+
private val eligibleCache = new mutable.HashMap[Type, List[TermRef]]
/** The implicit references that are eligible for type `tp`. */
@@ -76,7 +80,7 @@ object Implicits {
override def toString = {
val own = s"(implicits: ${refs mkString ","})"
- if (outerCtx == NoContext) own else own +"\n " + outerCtx.implicits
+ if (outerCtx == NoContext) own else own + "\n " + outerCtx.implicits
}
}
@@ -144,7 +148,7 @@ trait ImplicitRunInfo { self: RunInfo =>
(implicitScope(pre).companionRefs /: tp.classSymbols)(addClassScope)
case _ =>
tp.namedParts.flatMap(implicitScope(_).companionRefs)
- })
+ })(ctx)
/** The implicit scope of a type
* @param isLifted Type `tp` is the result of a `liftToClasses` application
@@ -168,12 +172,11 @@ trait Implicits { self: Typer =>
import tpd._
- override def viewExists(from: Type, to: Type)(implicit ctx: Context): Boolean = !(
- from.isError
- || to.isError
- || (ctx.mode is Mode.ImplicitsDisabled)
- || (inferView(dummyTreeOfType(from), to) eq EmptyTree)
- )
+ override def viewExists(from: Type, to: Type)(implicit ctx: Context): Boolean = (
+ !from.isError
+ && !to.isError
+ && (ctx.mode is Mode.ImplicitsEnabled)
+ && (inferView(dummyTreeOfType(from), to) ne EmptyTree))
/** Find an implicit conversion to apply to given tree `from` so that the
* result is compatible with type `to`.
@@ -210,15 +213,13 @@ trait Implicits { self: Typer =>
/** An implicit search; parameters as in `inferImplicit` */
class ImplicitSearch(pt: Type, argument: Tree, pos: Position)(implicit ctx: Context) {
- println(s"implicit search in ${ctx.owner} scope ${ctx.implicits}")
-
/** Try to typecheck an implicit reference */
def typedImplicit(ref: TermRef)(implicit ctx: Context): SearchResult = {
val id = Ident(ref).withPos(pos)
val tree =
if (argument.isEmpty) adapt(id, pt)
else typedApply(id, ref, argument :: Nil, pt)
- if (tree.tpe.isError) NoImplicitMatches // todo: replace by checking if local errors were reported in ctx.
+ if (tree.tpe.isError) NoImplicitMatches // todo: replace by checking if local errors were reported in ctx.
else SearchSuccess(ref, tree, ctx.typerState)
}
@@ -229,7 +230,7 @@ trait Implicits { self: Typer =>
*/
private def rankImplicits(pending: List[TermRef], acc: List[SearchSuccess]): List[SearchSuccess] = pending match {
case ref :: pending1 =>
- typedImplicit(ref)(ctx.fresh.withNewTyperState.addMode(ImplicitsDisabled)) match {
+ typedImplicit(ref)(ctx.fresh.withNewTyperState.retractMode(ImplicitsEnabled)) match {
case fail: SearchFailure =>
rankImplicits(pending1, acc)
case best @ SearchSuccess(bestRef, _, _) =>
@@ -273,15 +274,19 @@ trait Implicits { self: Typer =>
/** The expected type where parameters and uninstantiated typevars
* are replaced by wildcard types
*/
- val wildPt: Type = (new WildApprox) apply pt
+ val wildPt: Type = {
+ val result = (new WildApprox) apply pt
+ if (argument.isEmpty) result
+ else ViewProto(argument.tpe, result)
+ }
/** Find a unique best implicit reference */
def bestImplicit: SearchResult = {
- searchImplicits(ctx.implicits.eligible(wildPt)) match {
- case result: SearchSuccess => result
- case result: AmbiguousImplicits => result
- case NoImplicitMatches => searchImplicits(implicitScope(wildPt).eligible)
- }
+ searchImplicits(ctx.implicits.eligible(wildPt)) match {
+ case result: SearchSuccess => result
+ case result: AmbiguousImplicits => result
+ case NoImplicitMatches => searchImplicits(implicitScope(wildPt).eligible)
+ }
}
def implicitScope(tp: Type): OfTypeImplicits = ctx.runInfo.implicitScope(tp)
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index efaa48554..46dd9b0ad 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -63,8 +63,8 @@ object Inferencing {
case class FunProto(args: List[untpd.Tree], override val resultType: Type, typer: Typer)(implicit ctx: Context) extends UncachedGroundType with ProtoType {
private var myTypedArgs: List[Tree] = null
- def isMatchedBy(tp: Type)(implicit ctx: Context) =
- ctx.typer.isApplicableToTrees(tp, typedArgs, resultType)
+ def isMatchedBy(tp: Type)(implicit ctx: Context) =
+ typer.isApplicableToTrees(tp, typedArgs, resultType)
def argsAreTyped: Boolean = myTypedArgs != null
@@ -75,6 +75,12 @@ object Inferencing {
}
}
+ case class ViewProto(argType: Type, override val resultType: Type)(implicit ctx: Context) extends CachedGroundType with ProtoType {
+ def isMatchedBy(tp: Type)(implicit ctx: Context) =
+ ctx.typer.isApplicableToTypes(tp, argType :: Nil, resultType)
+ override def computeHash = doHash(argType, resultType)
+ }
+
case class PolyProto(nargs: Int, override val resultType: Type) extends UncachedGroundType
/** The normalized form of a type
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index 88bb3d4d8..1890822b6 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -29,7 +29,7 @@ object Mode {
val Pattern = newMode(0, "Pattern")
val Type = newMode(1, "Type")
- val ImplicitsDisabled = newMode(2, "ImplicitsDisabled")
+ val ImplicitsEnabled = newMode(2, "ImplicitsEnabled")
val InSuperInit = newMode(3, "InSuperInit")
val PatternOrType = Pattern | Type
diff --git a/tests/pos/implicits1.scala b/tests/pos/implicits1.scala
index bedcc11b7..4eae69325 100644
--- a/tests/pos/implicits1.scala
+++ b/tests/pos/implicits1.scala
@@ -1,8 +1,10 @@
-class X extends Object
+class X(elem: Int) extends Object
object Implicits {
- implicit val impl: X = new X
+ implicit val impl: X = new X(0)
+
+ implicit def conv(x: Int): X = new X(x)
val a: Object = "abc"
val b: Any = "abc"
@@ -14,4 +16,6 @@ object Implicits {
val y: Int = foo(1)
+ val z: X = 3
+
}