summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-04-12 16:08:27 +0000
committerMartin Odersky <odersky@gmail.com>2011-04-12 16:08:27 +0000
commitc28aed1ab1cc02b6b5c202344e3a652f76af64e3 (patch)
tree748197f425f409572d25cedaf7e65b90dfa20bb3 /src
parentca05143ea7c07e0e84e8fd66259df27392213861 (diff)
downloadscala-c28aed1ab1cc02b6b5c202344e3a652f76af64e3.tar.gz
scala-c28aed1ab1cc02b6b5c202344e3a652f76af64e3.tar.bz2
scala-c28aed1ab1cc02b6b5c202344e3a652f76af64e3.zip
Closes #4275.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala59
2 files changed, 53 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 45724f96dd..d198303d66 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -234,13 +234,6 @@ trait Infer {
def explainTypes(tp1: Type, tp2: Type) =
withDisambiguation(tp1, tp2)(global.explainTypes(tp1, tp2))
- def accessError(tree: Tree, sym: Symbol, pre: Type, explanation: String): Tree = {
- val realsym = underlying(sym)
- errorTree(tree, realsym + realsym.locationString + " cannot be accessed in " +
- (if (sym.isClassConstructor) context.enclClass.owner else pre.widen) +
- explanation)
- }
-
/* -- Tests & Checks---------------------------------------------------- */
/** Check that <code>sym</code> is defined and accessible as a member of
@@ -269,7 +262,7 @@ trait Infer {
Console.println(tree)
Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
}
- accessError(tree, sym, pre,
+ new AccessError(tree, sym, pre,
if (settings.check.isDefault) {
analyzer.lastAccessCheckDetails
} else {
@@ -297,10 +290,10 @@ trait Infer {
if (settings.debug.value) ex.printStackTrace
val sym2 = underlying(sym1)
val itype = pre.memberType(sym2)
- accessError(tree, sym, pre,
+ new AccessError(tree, sym, pre,
"\n because its instance type "+itype+
(if ("malformed type: "+itype.toString==ex.msg) " is malformed"
- else " contains a "+ex.msg))
+ else " contains a "+ex.msg)).emit()
ErrorType
}
if (pre.isInstanceOf[SuperType])
@@ -1699,6 +1692,21 @@ trait Infer {
// Side effects tree with symbol and type
tree setSymbol resSym setType resTpe
}
+
+ case class AccessError(tree: Tree, sym: Symbol, pre: Type, explanation: String) extends Tree {
+ override def pos = tree.pos
+ override def hasSymbol = tree.hasSymbol
+ override def symbol = tree.symbol
+ override def symbol_=(x: Symbol) = tree.symbol = x
+ setError(this)
+
+ def emit(): Tree = {
+ val realsym = underlying(sym)
+ errorTree(tree, realsym + realsym.locationString + " cannot be accessed in " +
+ (if (sym.isClassConstructor) context.enclClass.owner else pre.widen) +
+ explanation)
+ }
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3afbc5640b..7ccef83d49 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -991,6 +991,32 @@ trait Typers extends Modes {
doAdapt(pt)
}
+ /** Try o apply an implicit conversion to `qual' to that it contains
+ * a method `name`. If that's ambiguous try taking arguments into account using `adaptToArguments`.
+ */
+ def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int): Tree = {
+ try {
+ adaptToMember(qual, HasMember(name))
+ } catch {
+ case ex: TypeError =>
+ // this happens if implicits are ambiguous; try again with more context info.
+ // println("last ditch effort: "+qual+" . "+name)
+ context.tree match {
+ case Apply(tree1, args) if tree1 eq tree => // try handling the arguments
+ // println("typing args: "+args)
+ 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)
+ throw ex
+ }
+ }
+ }
+
/** Try to apply an implicit conversion to `qual' to that it contains a
* member `name` of arbitrary type.
* If no conversion is found, return `qual' unchanged.
@@ -3452,8 +3478,6 @@ trait Typers extends Modes {
* @return ...
*/
def typedSelect(qual: Tree, name: Name): Tree = {
-
-
val sym =
if (tree.symbol != NoSymbol) {
if (phase.erasedTypes && qual.isInstanceOf[Super])
@@ -3472,26 +3496,9 @@ trait Typers extends Modes {
member(qual, name)
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
- 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)
- context.tree match {
- case Apply(tree1, args) if tree1 eq tree => // try handling the arguments
- // println("typing args: "+args)
- 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)
- throw ex
- }
- }
+ val qual1 =
+ if (member(qual, name) != NoSymbol) qual
+ else adaptToMemberWithArgs(tree, qual, name, mode)
if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
@@ -3567,6 +3574,10 @@ trait Typers extends Modes {
qual // you only get to see the wrapped tree after running this check :-p
}) setType qual.tpe,
name)
+ case accErr: Inferencer#AccessError =>
+ val qual1 = adaptToMemberWithArgs(tree, qual, name, mode)
+ if (qual1 ne qual) typed(Select(qual1, name) setPos tree.pos, mode, pt)
+ else accErr.emit()
case _ =>
result
}
@@ -3713,10 +3724,10 @@ trait Typers extends Modes {
if (inaccessibleSym eq NoSymbol) {
error(tree.pos, "not found: "+decodeWithKind(name, context.owner))
}
- else accessError(
+ else new AccessError(
tree, inaccessibleSym, context.enclClass.owner.thisType,
inaccessibleExplanation
- )
+ ).emit()
defSym = context.owner.newErrorSymbol(name)
}
}