summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Cunei <antonio.cunei@epfl.ch>2010-09-14 14:41:27 +0000
committerAntonio Cunei <antonio.cunei@epfl.ch>2010-09-14 14:41:27 +0000
commit153a9df5a1e3100cbe192f7498938066664d9aff (patch)
treecfa1c67e28cf3df7bdc173cb006d4443045d78d1
parent62fce2ceab1bc85319afbe17d4717bf03e563b45 (diff)
downloadscala-153a9df5a1e3100cbe192f7498938066664d9aff.tar.gz
scala-153a9df5a1e3100cbe192f7498938066664d9aff.tar.bz2
scala-153a9df5a1e3100cbe192f7498938066664d9aff.zip
Merged revisions 22983 via svnmerge from
https://lampsvn.epfl.ch/svn-repos/scala/scala/trunk ........ r22983 | moors | 2010-09-14 16:23:28 +0200 (Tue, 14 Sep 2010) | 5 lines closes #1693: improve implicit conversion disambiguation by incorporating the expected type of the member that triggered the conversion back-ported fix by Martin in embeddings branch. review by odersky (just in case it shouldn't have been back-ported) ........
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala35
-rw-r--r--test/files/neg/implicits.check11
-rw-r--r--test/files/pos/t1693.scala9
4 files changed, 42 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 28c4b67db9..900f7e471b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -214,8 +214,8 @@ trait Contexts { self: Analyzer =>
def make(tree: Tree): Context =
make(tree, owner)
- def makeSilent(reportAmbiguousErrors: Boolean): Context = {
- val c = make(tree)
+ def makeSilent(reportAmbiguousErrors: Boolean, newtree: Tree = tree): Context = {
+ val c = make(newtree)
c.reportGeneralErrors = false
c.reportAmbiguousErrors = reportAmbiguousErrors
c
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cbb872c3ed..8c1ac9a816 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -692,14 +692,18 @@ trait Typers { self: Analyzer =>
else qual.tpe.nonLocalMember(name)
}
- def silent[T](op: Typer => T): Any /* in fact, TypeError or T */ = {
+ def silent[T](op: Typer => T,
+ reportAmbiguousErrors: Boolean = context.reportAmbiguousErrors,
+ newtree: Tree = context.tree): Any /* in fact, TypeError or T */ = {
val rawTypeStart = startCounter(rawTypeFailed)
val findMemberStart = startCounter(findMemberFailed)
val subtypeStart = startCounter(subtypeFailed)
val failedSilentStart = startTimer(failedSilentNanos)
try {
- if (context.reportGeneralErrors) {
- val context1 = context.makeSilent(context.reportAmbiguousErrors)
+ if (context.reportGeneralErrors ||
+ reportAmbiguousErrors != context.reportAmbiguousErrors ||
+ newtree != context.tree) {
+ val context1 = context.makeSilent(reportAmbiguousErrors, newtree)
context1.undetparams = context.undetparams
context1.savedTypeBounds = context.savedTypeBounds
context1.namedApplyBlockInfo = context.namedApplyBlockInfo
@@ -3331,7 +3335,9 @@ trait Typers { self: Analyzer =>
val funpt = if (isPatternMode) pt else WildcardType
val appStart = startTimer(failedApplyNanos)
val opeqStart = startTimer(failedOpEqNanos)
- silent(_.typed(fun, funMode(mode), funpt)) match {
+ silent(_.typed(fun, funMode(mode), funpt),
+ if ((mode & EXPRmode) != 0) false else context.reportAmbiguousErrors,
+ if ((mode & EXPRmode) != 0) tree else context.tree) match {
case fun1: Tree =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
incCounter(typedApplyCount)
@@ -3523,7 +3529,26 @@ trait Typers { self: Analyzer =>
member(qual, name)
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
- val qual1 = adaptToName(qual, name)
+ val qual1 = try {
+ adaptToName(qual, name)
+ } catch {
+ case ex: TypeError =>
+ // this happens if implicits are ambiguous; try again with more context info.
+ // println("last ditch effort: "+qual+" . "+name) // DEBUG
+ context.tree match {
+ case Apply(tree1, args) if tree1 eq tree => // try handling the arguments
+ // println("typing args: "+args) // DEBUG
+ silent(_.typedArgs(args, mode)) match {
+ case args: List[_] =>
+ adaptToArguments(qual, name, args.asInstanceOf[List[Tree]], WildcardType)
+ case _ =>
+ throw ex
+ }
+ case _ =>
+ // println("not in an apply: "+context.tree+"/"+tree) // DEBUG
+ throw ex
+ }
+ }
if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
diff --git a/test/files/neg/implicits.check b/test/files/neg/implicits.check
index 337560f423..d975ccfa84 100644
--- a/test/files/neg/implicits.check
+++ b/test/files/neg/implicits.check
@@ -1,12 +1,3 @@
-implicits.scala:21: error: type mismatch;
- found : Pos
- required: ?{val +: ?}
-Note that implicit conversions are not applicable because they are ambiguous:
- both method any2plus in object Sub of type (x: Any)Sub.Plus
- and method pos2int in object Super of type (p: Pos)Int
- are possible conversion functions from Pos to ?{val +: ?}
- f(p+1)
- ^
implicits.scala:38: error: type mismatch;
found : test2.HSome[java.lang.String,test2.HMap]
required: Int
@@ -17,4 +8,4 @@ implicits.scala:46: error: type mismatch;
required: scala.List[Mxml]
children.toList.flatMap ( e => {
^
-three errors found
+two errors found
diff --git a/test/files/pos/t1693.scala b/test/files/pos/t1693.scala
new file mode 100644
index 0000000000..f3615f4756
--- /dev/null
+++ b/test/files/pos/t1693.scala
@@ -0,0 +1,9 @@
+object Test {
+ class Foo
+ class SomeOps(x : Foo) { def foo(x: String) = 1 }
+ class OtherOps(x : Foo) { def foo(x: Int) = 1 }
+ implicit def mkSomeOps(x: Foo) : SomeOps = new SomeOps(x)
+ implicit def mkOtherOps(x: Foo) : OtherOps = new OtherOps(x)
+
+ (new Foo).foo(1)
+} \ No newline at end of file