summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-04-30 05:18:20 -0700
committerPaul Phillips <paulp@improving.org>2013-04-30 05:18:20 -0700
commitbf0db36d8bbb0ac7faa0652b98458cfebca8e78a (patch)
treed3746ffa180541b3b7c6a60c5b1cd3bf272a7c37
parentfc14edde4cd0dde064b78b0bde35adbfd561597d (diff)
parent71581425746e9d3239998569d6f85c710efbf17b (diff)
downloadscala-bf0db36d8bbb0ac7faa0652b98458cfebca8e78a.tar.gz
scala-bf0db36d8bbb0ac7faa0652b98458cfebca8e78a.tar.bz2
scala-bf0db36d8bbb0ac7faa0652b98458cfebca8e78a.zip
Merge pull request #2428 from hubertp/issue/7291
SI-7291: Don't throw exceptions while encountering diverging expansion.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala72
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala82
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala60
-rw-r--r--src/compiler/scala/tools/reflect/ToolBoxFactory.scala17
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala5
-rw-r--r--test/files/neg/t696.check10
-rw-r--r--test/files/neg/t696.scala7
-rw-r--r--test/files/run/t7291.check2
-rw-r--r--test/files/run/t7291.scala19
10 files changed, 165 insertions, 117 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 89fc55bc2c..a0660ce71d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -21,47 +21,65 @@ trait ContextErrors {
import global._
import definitions._
- object ErrorKinds extends Enumeration {
- type ErrorKind = Value
- val Normal, Access, Ambiguous, Divergent = Value
- }
-
- import ErrorKinds.ErrorKind
-
- trait AbsTypeError extends Throwable {
+ abstract class AbsTypeError extends Throwable {
def errPos: Position
def errMsg: String
- def kind: ErrorKind
+ override def toString() = "[Type error at:" + errPos + "] " + errMsg
}
- case class NormalTypeError(underlyingTree: Tree, errMsg: String, kind: ErrorKind = ErrorKinds.Normal)
- extends AbsTypeError {
-
- def errPos:Position = underlyingTree.pos
- override def toString() = "[Type error at:" + underlyingTree.pos + "] " + errMsg
+ abstract class TreeTypeError extends AbsTypeError {
+ def underlyingTree: Tree
+ def errPos = underlyingTree.pos
}
- case class SymbolTypeError(underlyingSym: Symbol, errMsg: String, kind: ErrorKind = ErrorKinds.Normal)
+ case class NormalTypeError(underlyingTree: Tree, errMsg: String)
+ extends TreeTypeError
+
+ case class AccessTypeError(underlyingTree: Tree, errMsg: String)
+ extends TreeTypeError
+
+ case class AmbiguousTypeError(errPos: Position, errMsg: String)
+ extends AbsTypeError
+
+ case class SymbolTypeError(underlyingSym: Symbol, errMsg: String)
extends AbsTypeError {
def errPos = underlyingSym.pos
}
- case class TypeErrorWrapper(ex: TypeError, kind: ErrorKind = ErrorKinds.Normal)
+ case class TypeErrorWrapper(ex: TypeError)
extends AbsTypeError {
def errMsg = ex.msg
def errPos = ex.pos
}
- case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError, kind: ErrorKind = ErrorKinds.Normal)
+ case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError)
extends AbsTypeError {
def errMsg = ex.msg
def errPos = tree.pos
}
- case class AmbiguousTypeError(underlyingTree: Tree, errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Ambiguous) extends AbsTypeError
+ // Unlike other type errors diverging implicit expansion
+ // will be re-issued explicitly on failed implicit argument search.
+ // This is because we want to:
+ // 1) provide better error message than just "implicit not found"
+ // 2) provide the type of the implicit parameter for which we got diverging expansion
+ // (pt at the point of divergence gives less information to the user)
+ // Note: it is safe to delay error message generation in this case
+ // becasue we don't modify implicits' infos.
+ case class DivergentImplicitTypeError(underlyingTree: Tree, pt0: Type, sym: Symbol)
+ extends TreeTypeError {
+ def errMsg: String = errMsgForPt(pt0)
+ def withPt(pt: Type): AbsTypeError = this.copy(pt0 = pt)
+ private def errMsgForPt(pt: Type) =
+ s"diverging implicit expansion for type ${pt}\nstarting with ${sym.fullLocationString}"
+ }
+
+ case class AmbiguousImplicitTypeError(underlyingTree: Tree, errMsg: String)
+ extends TreeTypeError
- case class PosAndMsgTypeError(errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError
+ case class PosAndMsgTypeError(errPos: Position, errMsg: String)
+ extends AbsTypeError
object ErrorUtils {
def issueNormalTypeError(tree: Tree, msg: String)(implicit context: Context) {
@@ -72,10 +90,6 @@ trait ContextErrors {
issueTypeError(SymbolTypeError(sym, msg))
}
- def issueDivergentImplicitsError(tree: Tree, msg: String)(implicit context: Context) {
- issueTypeError(NormalTypeError(tree, msg, ErrorKinds.Divergent))
- }
-
def issueAmbiguousTypeError(pre: Type, sym1: Symbol, sym2: Symbol, err: AmbiguousTypeError)(implicit context: Context) {
context.issueAmbiguousError(pre, sym1, sym2, err)
}
@@ -830,7 +844,7 @@ trait ContextErrors {
underlyingSymbol(sym).fullLocationString + " cannot be accessed in " +
location + explanation
}
- NormalTypeError(tree, errMsg, ErrorKinds.Access)
+ AccessTypeError(tree, errMsg)
}
def NoMethodInstanceError(fn: Tree, args: List[Tree], msg: String) =
@@ -875,7 +889,7 @@ trait ContextErrors {
"argument types " + argtpes.mkString("(", ",", ")") +
(if (pt == WildcardType) "" else " and expected result type " + pt)
val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, msg0)
- issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg))
+ issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(pos, msg))
setErrorOnLastTry(lastTry, tree)
} else setError(tree) // do not even try further attempts because they should all fail
// even if this is not the last attempt (because of the SO's possibility on the horizon)
@@ -889,7 +903,7 @@ trait ContextErrors {
def AmbiguousExprAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, pt: Type, lastTry: Boolean) = {
val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, "expected type " + pt)
- issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg))
+ issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(pos, msg))
setErrorOnLastTry(lastTry, tree)
}
@@ -1174,7 +1188,7 @@ trait ContextErrors {
if (explanation == "") "" else "\n" + explanation
)
}
- context.issueAmbiguousError(AmbiguousTypeError(tree, tree.pos,
+ context.issueAmbiguousError(AmbiguousImplicitTypeError(tree,
if (isView) viewMsg
else s"ambiguous implicit values:\n${coreMsg}match expected type $pt")
)
@@ -1182,9 +1196,7 @@ trait ContextErrors {
}
def DivergingImplicitExpansionError(tree: Tree, pt: Type, sym: Symbol)(implicit context0: Context) =
- issueDivergentImplicitsError(tree,
- "diverging implicit expansion for type "+pt+"\nstarting with "+
- sym.fullLocationString)
+ issueTypeError(DivergentImplicitTypeError(tree, pt, sym))
}
object NamesDefaultsErrorsGen {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index c26ad3e61d..e3bb595bd7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -1189,12 +1189,12 @@ trait Contexts { self: Analyzer =>
errorBuffer.clear()
this
}
- def clearErrors(kind: ErrorKinds.ErrorKind): this.type = {
- errorBuffer.retain(_.kind != kind)
+ def clearErrors(removeF: PartialFunction[AbsTypeError, Boolean]): this.type = {
+ errorBuffer.retain(!PartialFunction.cond(_)(removeF))
this
}
- def retainErrors(kind: ErrorKinds.ErrorKind): this.type = {
- errorBuffer.retain(_.kind == kind)
+ def retainErrors(leaveF: PartialFunction[AbsTypeError, Boolean]): this.type = {
+ errorBuffer.retain(PartialFunction.cond(_)(leaveF))
this
}
def clearAllWarnings(): this.type = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index b0c8baae20..875aa5a9d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -80,8 +80,11 @@ trait Implicits {
printTyping("typing implicit: %s %s".format(tree, context.undetparamsString))
val implicitSearchContext = context.makeImplicit(reportAmbiguous)
val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit
- if (saveAmbiguousDivergent && implicitSearchContext.hasErrors) {
- context.updateBuffer(implicitSearchContext.reportBuffer.errors.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent))
+ if (result.isFailure && saveAmbiguousDivergent && implicitSearchContext.hasErrors) {
+ context.updateBuffer(implicitSearchContext.reportBuffer.errors.collect {
+ case dte: DivergentImplicitTypeError => dte
+ case ate: AmbiguousImplicitTypeError => ate
+ })
debuglog("update buffer: " + implicitSearchContext.reportBuffer.errors)
}
printInference("[infer implicit] inferred " + result)
@@ -152,6 +155,7 @@ trait Implicits {
def isFailure = false
def isAmbiguousFailure = false
+ def isDivergent = false
final def isSuccess = !isFailure
}
@@ -159,6 +163,11 @@ trait Implicits {
override def isFailure = true
}
+ lazy val DivergentSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) {
+ override def isFailure = true
+ override def isDivergent = true
+ }
+
lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) {
override def isFailure = true
override def isAmbiguousFailure = true
@@ -397,22 +406,18 @@ trait Implicits {
(context.openImplicits find { case (tp, tree1) => tree1.symbol == tree.symbol && dominates(pt, tp)}) match {
case Some(pending) =>
//println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG
- throw DivergentImplicit
+ DivergentSearchFailure
case None =>
try {
context.openImplicits = (pt, tree) :: context.openImplicits
// println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG
- typedImplicit0(info, ptChecked, isLocal)
- } catch {
- case ex: DivergentImplicit =>
+ val result = typedImplicit0(info, ptChecked, isLocal)
+ if (result.isDivergent) {
//println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG
- if (context.openImplicits.tail.isEmpty) {
- if (!(pt.isErroneous))
- DivergingImplicitExpansionError(tree, pt, info.sym)(context)
- SearchFailure
- } else {
- throw DivergentImplicit
- }
+ if (context.openImplicits.tail.isEmpty && !pt.isErroneous)
+ DivergingImplicitExpansionError(tree, pt, info.sym)(context)
+ }
+ result
} finally {
context.openImplicits = context.openImplicits.tail
}
@@ -588,7 +593,7 @@ trait Implicits {
case Some(err) =>
log("implicit adapt failed: " + err.errMsg)
return fail(err.errMsg)
- case None =>
+ case None =>
}
if (Statistics.canEnable) Statistics.incCounter(typedImplicits)
@@ -637,7 +642,7 @@ trait Implicits {
context.firstError match {
case Some(err) =>
return fail("type parameters weren't correctly instantiated outside of the implicit tree: " + err.errMsg)
- case None =>
+ case None =>
}
// filter out failures from type inference, don't want to remove them from undetParams!
@@ -676,7 +681,7 @@ trait Implicits {
context.firstError match {
case Some(err) =>
fail("typing TypeApply reported errors for the implicit tree: " + err.errMsg)
- case None =>
+ case None =>
val result = new SearchResult(itree2, subst)
if (Statistics.canEnable) Statistics.incCounter(foundImplicits)
printInference("[success] found %s for pt %s".format(result, ptInstantiated))
@@ -789,16 +794,21 @@ trait Implicits {
/** Preventing a divergent implicit from terminating implicit search,
* so that if there is a best candidate it can still be selected.
*/
- private var divergence = false
- private val divergenceHandler: PartialFunction[Throwable, SearchResult] = {
- var remaining = 1;
- { case x: DivergentImplicit if remaining > 0 =>
- remaining -= 1
- divergence = true
- log("discarding divergent implicit during implicit search")
+ object DivergentImplicitRecovery {
+ // symbol of the implicit that caused the divergence.
+ // Initially null, will be saved on first diverging expansion.
+ private var implicitSym: Symbol = _
+ private var countdown: Int = 1
+
+ def sym: Symbol = implicitSym
+ def apply(search: SearchResult, i: ImplicitInfo): SearchResult =
+ if (search.isDivergent && countdown > 0) {
+ countdown -= 1
+ implicitSym = i.sym
+ log("discarding divergent implicit ${implicitSym} during implicit search")
SearchFailure
- }
- }
+ } else search
+ }
/** Sorted list of eligible implicits.
*/
@@ -826,15 +836,15 @@ trait Implicits {
@tailrec private def rankImplicits(pending: Infos, acc: Infos): Infos = pending match {
case Nil => acc
case i :: is =>
- def tryImplicitInfo(i: ImplicitInfo) =
- try typedImplicit(i, ptChecked = true, isLocal)
- catch divergenceHandler
-
- tryImplicitInfo(i) match {
+ DivergentImplicitRecovery(typedImplicit(i, ptChecked = true, isLocal), i) match {
+ case sr if sr.isDivergent =>
+ Nil
case sr if sr.isFailure =>
// We don't want errors that occur during checking implicit info
// to influence the check of further infos.
- context.reportBuffer.retainErrors(ErrorKinds.Divergent)
+ context.reportBuffer.retainErrors {
+ case err: DivergentImplicitTypeError => true
+ }
rankImplicits(is, acc)
case newBest =>
best = newBest
@@ -882,10 +892,9 @@ trait Implicits {
/* If there is no winner, and we witnessed and caught divergence,
* now we can throw it for the error message.
*/
- if (divergence)
- throw DivergentImplicit
-
- if (invalidImplicits.nonEmpty)
+ if (DivergentImplicitRecovery.sym != null) {
+ DivergingImplicitExpansionError(tree, pt, DivergentImplicitRecovery.sym)(context)
+ } else if (invalidImplicits.nonEmpty)
setAddendum(pos, () =>
"\n Note: implicit "+invalidImplicits.head+" is not applicable here"+
" because it comes after the application point and it lacks an explicit result type")
@@ -1438,6 +1447,3 @@ object ImplicitsStats {
val implicitCacheAccs = Statistics.newCounter ("implicit cache accesses", "typer")
val implicitCacheHits = Statistics.newSubCounter("implicit cache hits", implicitCacheAccs)
}
-
-class DivergentImplicit extends Exception
-object DivergentImplicit extends DivergentImplicit
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 95a9cea066..4b7260c798 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -150,15 +150,19 @@ trait Typers extends Adaptations with Tags {
} else {
mkArg = gen.mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
if (!param.hasDefault && !paramFailed) {
- context.reportBuffer.errors.find(_.kind == ErrorKinds.Divergent) match {
- case Some(divergentImplicit) =>
+ context.reportBuffer.errors.collectFirst {
+ case dte: DivergentImplicitTypeError => dte
+ } match {
+ case Some(divergent) =>
// DivergentImplicit error has higher priority than "no implicit found"
// no need to issue the problem again if we are still in silent mode
if (context.reportErrors) {
- context.issue(divergentImplicit)
- context.reportBuffer.clearErrors(ErrorKinds.Divergent)
+ context.issue(divergent.withPt(paramTp))
+ context.reportBuffer.clearErrors {
+ case dte: DivergentImplicitTypeError => true
+ }
}
- case None =>
+ case _ =>
NoImplicitFoundError(fun, param)
}
paramFailed = true
@@ -1627,22 +1631,27 @@ trait Typers extends Adaptations with Tags {
/** Makes sure that the first type tree in the list of parent types is always a class.
* If the first parent is a trait, prepend its supertype to the list until it's a class.
-*/
- private def normalizeFirstParent(parents: List[Tree]): List[Tree] = parents match {
- case first :: rest if treeInfo.isTraitRef(first) =>
- def explode(supertpt: Tree, acc: List[Tree]): List[Tree] = {
- if (treeInfo.isTraitRef(supertpt)) {
- val supertpt1 = typedType(supertpt)
- if (!supertpt1.isErrorTyped) {
- val supersupertpt = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus
- return explode(supersupertpt, supertpt1 :: acc)
- }
- }
- if (supertpt.tpe.typeSymbol == AnyClass) supertpt setType AnyRefClass.tpe
- supertpt :: acc
- }
- explode(first, Nil) ++ rest
- case _ => parents
+ */
+ private def normalizeFirstParent(parents: List[Tree]): List[Tree] = {
+ @annotation.tailrec
+ def explode0(parents: List[Tree]): List[Tree] = {
+ val supertpt :: rest = parents // parents is always non-empty here - it only grows
+ if (supertpt.tpe.typeSymbol == AnyClass) {
+ supertpt setType AnyRefTpe
+ parents
+ } else if (treeInfo isTraitRef supertpt) {
+ val supertpt1 = typedType(supertpt)
+ def supersuper = TypeTree(supertpt1.tpe.firstParent) setPos supertpt.pos.focus
+ if (supertpt1.isErrorTyped) rest
+ else explode0(supersuper :: supertpt1 :: rest)
+ } else parents
+ }
+
+ def explode(parents: List[Tree]) =
+ if (treeInfo isTraitRef parents.head) explode0(parents)
+ else parents
+
+ if (parents.isEmpty) Nil else explode(parents)
}
/** Certain parents are added in the parser before it is known whether
@@ -4683,12 +4692,11 @@ trait Typers extends Adaptations with Tags {
case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
}
val (result, accessibleError) = silent(_.makeAccessible(tree1, sym, qual.tpe, qual)) match {
+ case SilentTypeError(err: AccessTypeError) =>
+ (tree1, Some(err))
case SilentTypeError(err) =>
- if (err.kind != ErrorKinds.Access) {
- context issue err
- return setError(tree)
- }
- else (tree1, Some(err))
+ context issue err
+ return setError(tree)
case SilentResultValue(treeAndPre) =>
(stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None)
}
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
index 66dda2b530..6fb8b4ea37 100644
--- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
+++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala
@@ -181,16 +181,15 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
(currentTyper, tree) => {
trace("inferring implicit %s (macros = %s): ".format(if (isView) "view" else "value", !withMacrosDisabled))(showAttributed(pt, true, true, settings.Yshowsymkinds.value))
val context = currentTyper.context
- analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos) match {
- case failure if failure.tree.isEmpty =>
- trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits: ")(failure.tree)
- context.firstError foreach { err =>
- throw ToolBoxError("reflective implicit search has failed: %s".format(err.errMsg))
- }
- EmptyTree
- case success =>
- success.tree
+ val result = analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)
+ if (result.isFailure) {
+ // @H: what's the point of tracing an empty tree?
+ trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits: ")(result.tree)
+ context.firstError foreach { err =>
+ throw ToolBoxError("reflective implicit search has failed: %s".format(err.errMsg))
+ }
}
+ result.tree
})
def compile(expr0: Tree): () => Any = {
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 43b8bd2738..792ca6efa6 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -15,7 +15,7 @@ import scala.reflect.internal.util.{ SourceFile, BatchSourceFile, Position, NoPo
import scala.tools.nsc.reporters._
import scala.tools.nsc.symtab._
import scala.tools.nsc.doc.ScaladocAnalyzer
-import scala.tools.nsc.typechecker.{ Analyzer, DivergentImplicit }
+import scala.tools.nsc.typechecker.Analyzer
import symtab.Flags.{ACCESSOR, PARAMACCESSOR}
import scala.annotation.{ elidable, tailrec }
import scala.language.implicitConversions
@@ -1210,9 +1210,6 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
case ex: TypeError =>
debugLog("type error caught: "+ex)
alt
- case ex: DivergentImplicit =>
- debugLog("divergent implicit caught: "+ex)
- alt
}
}
diff --git a/test/files/neg/t696.check b/test/files/neg/t696.check
index ac26a864a5..b7bc5cdf98 100644
--- a/test/files/neg/t696.check
+++ b/test/files/neg/t696.check
@@ -1,5 +1,9 @@
-t696.scala:4: error: diverging implicit expansion for type TypeUtil0.Type[Any]
+t696.scala:5: error: diverging implicit expansion for type TypeUtil0.Type[Any]
starting with method WithType in object TypeUtil0
- as[Any](null);
+ as[Any](null)
^
-one error found
+t696.scala:6: error: diverging implicit expansion for type TypeUtil0.Type[X]
+starting with method WithType in object TypeUtil0
+ def foo[X]() = as[X](null)
+ ^
+two errors found
diff --git a/test/files/neg/t696.scala b/test/files/neg/t696.scala
index a06a32141a..ca76f7ef6c 100644
--- a/test/files/neg/t696.scala
+++ b/test/files/neg/t696.scala
@@ -1,6 +1,7 @@
object TypeUtil0 {
- trait Type[+T];
+ trait Type[+T]
implicit def WithType[S,T](implicit tpeS : Type[S], tpeT : Type[T]) : Type[S with T] = null
- as[Any](null);
- def as[T](x : Any)(implicit tpe : Type[T]) = null;
+ def as[T](x : Any)(implicit tpe : Type[T]) = null
+ as[Any](null)
+ def foo[X]() = as[X](null)
}
diff --git a/test/files/run/t7291.check b/test/files/run/t7291.check
new file mode 100644
index 0000000000..c07ba986a3
--- /dev/null
+++ b/test/files/run/t7291.check
@@ -0,0 +1,2 @@
+conjure
+traversable
diff --git a/test/files/run/t7291.scala b/test/files/run/t7291.scala
new file mode 100644
index 0000000000..30c4261a81
--- /dev/null
+++ b/test/files/run/t7291.scala
@@ -0,0 +1,19 @@
+trait Fooable[T]
+object Fooable {
+ implicit def conjure[T]: Fooable[T] = {
+ println("conjure")
+ new Fooable[T]{}
+ }
+
+}
+
+object Test {
+ implicit def traversable[T, Coll[_] <: Traversable[_]](implicit
+elem: Fooable[T]): Fooable[Coll[T]] = {
+ println("traversable")
+ new Fooable[Coll[T]]{}
+ }
+ def main(args: Array[String]) {
+ implicitly[Fooable[List[Any]]]
+ }
+}