summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-10-07 14:10:34 +0000
committerMartin Odersky <odersky@gmail.com>2009-10-07 14:10:34 +0000
commit9f121f57e034a7feb07bad7f67403f3ac75b46d4 (patch)
treedd68aed8983422a39dbc867397762a7bc5e5a9f8 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parentad62d9f8b00d328c099268366ae05c5122915fa6 (diff)
downloadscala-9f121f57e034a7feb07bad7f67403f3ac75b46d4.tar.gz
scala-9f121f57e034a7feb07bad7f67403f3ac75b46d4.tar.bz2
scala-9f121f57e034a7feb07bad7f67403f3ac75b46d4.zip
Fixed #1000, #2060
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala106
1 files changed, 61 insertions, 45 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 52f4952060..df17dcc416 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -225,27 +225,6 @@ trait Typers { self: Analyzer =>
}
}
- /** Infer an implicit conversion (``view'') that makes a member available.
- * @param tree The tree which needs to be converted.
- * @param from The source type of the conversion
- * @param name The name of the member that needs to be available
- * @param tp The expected type of the member that needs to be available
- */
- def inferView(tree: Tree, from: Type, name: Name, tp: Type): Tree = {
- val to = refinedType(List(WildcardType), NoSymbol)
- var psym = if (name.isTypeName) to.typeSymbol.newAbstractType(tree.pos, name)
- else to.typeSymbol.newValue(tree.pos, name)
- psym = to.decls enter psym
- psym setInfo tp
- try {
- inferView(tree, from, to, true)
- } catch {
- case ex: AssertionError =>
- println("inverView "+tree+", from = "+from+", name = "+name+" tp = "+tp)
- throw ex
- }
- }
-
import infer._
private var namerCache: Namer = null
@@ -604,10 +583,23 @@ trait Typers { self: Analyzer =>
(checkAccessible(tree, sym, pre, site), pre)
}
+ /** Is `sym` defined in package object of package `pkg`?
+ */
private def isInPackageObject(sym: Symbol, pkg: Symbol) =
- pkg.isPackageClass &&
- sym.owner.isPackageObjectClass &&
- sym.owner.owner == pkg
+ pkg.isPackageClass && {
+ sym.alternatives forall { sym =>
+ !sym.owner.isPackage && {
+ sym.owner.isPackageObjectClass &&
+ sym.owner.owner == pkg ||
+ pkg.isInitialized && {
+ // need to be careful here to not get a cyclic reference during bootstrap
+ val pkgobj = pkg.info.member(nme.PACKAGEkw)
+ pkgobj.isInitialized &&
+ (pkgobj.info.member(sym.name).alternatives contains sym)
+ }
+ }
+ }
+ }
/** Post-process an identifier or selection node, performing the following:
* 1. Check that non-function pattern expressions are stable
@@ -995,33 +987,58 @@ trait Typers { self: Analyzer =>
adapt(tree, mode, pt)
}
- /**
- * @param qual ...
- * @param name ...
- * @param tp ...
- * @return ...
- */
- def adaptToMember(qual: Tree, name: Name, tp: Type): Tree = {
+ def adaptToMember(qual: Tree, searchTemplate: Type): Tree = {
val qtpe = qual.tpe.widen
if (qual.isTerm &&
((qual.symbol eq null) || !qual.symbol.isTerm || qual.symbol.isValue) &&
- phase.id <= currentRun.typerPhase.id && !qtpe.isError && !tp.isError &&
+ phase.id <= currentRun.typerPhase.id && !qtpe.isError &&
qtpe.typeSymbol != NullClass && qtpe.typeSymbol != NothingClass && qtpe != WildcardType &&
context.implicitsEnabled) { // don't try to adapt a top-level type that's the subject of an implicit search
// this happens because, if isView, typedImplicit tries to apply the "current" implicit value to
// a value that needs to be coerced, so we check whether the implicit value has an `apply` method
// (if we allow this, we get divergence, e.g., starting at `conforms` during ant quick.bin)
// note: implicit arguments are still inferred (this kind of "chaining" is allowed)
- val coercion = inferView(qual, qtpe, name, tp)
+ val coercion = inferView(qual, qtpe, searchTemplate, true)
if (coercion != EmptyTree)
typedQualifier(atPos(qual.pos)(Apply(coercion, List(qual))))
- else qual
- } else qual
+ else
+ qual
+ } else {
+ qual
+ }
}
+ /** Try to apply an implicit conversion to `qual' to that it contains
+ * a method `name` which can be applied to arguments `args' with expected type `pt'.
+ * If `pt' is defined, there is a fallback to try again with pt = ?.
+ * This helps avoiding propagating result information to far and solves
+ * #1756.
+ * If no conversion is found, return `qual' unchanged.
+ *
+ */
+ def adaptToArguments(qual: Tree, name: Name, args: List[Tree], pt: Type): Tree = {
+ def doAdapt(restpe: Type) =
+ //util.trace("adaptToArgs "+qual+", name = "+name+", argtpes = "+(args map (_.tpe))+", pt = "+pt+" = ")
+ adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), restpe))
+ if (pt != WildcardType) {
+ silent(_ => doAdapt(pt)) match {
+ case result: Tree if result != qual =>
+ result
+ case _ =>
+ if (settings.debug.value) log("fallback on implicits in adaptToArguments: "+qual+" . "+name)
+ doAdapt(WildcardType)
+ }
+ } else
+ doAdapt(pt)
+ }
+
+ /** 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.
+ */
def adaptToName(qual: Tree, name: Name) =
if (member(qual, name)(context.owner) != NoSymbol) qual
- else adaptToMember(qual, name, WildcardType)
+ else adaptToMember(qual, HasMember(name))
private def typePrimaryConstrBody(clazz : Symbol, cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
// XXX: see about using the class's symbol....
@@ -2997,19 +3014,18 @@ trait Typers { self: Analyzer =>
}
}
if (errorInResult(fun) || (args exists errorInResult)) {
+ if (printTypings) println("second try for: "+fun+" and "+args)
val Select(qual, name) = fun
val args1 = tryTypedArgs(args, argMode(fun, mode), ex)
val qual1 =
- if ((args1 ne null) && !pt.isError) {
- def templateArgType(arg: Tree) =
- new BoundedWildcardType(mkTypeBounds(arg.tpe, AnyClass.tpe))
- val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "typer$dummy")
- adaptToMember(qual, name, MethodType(dummyMethod.newSyntheticValueParams(args1 map templateArgType), pt))
- } else qual
+ if ((args1 ne null) && !pt.isError) adaptToArguments(qual, name, args1, pt)
+ else qual
if (qual1 ne qual) {
val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
return typed1(tree1, mode | SNDTRYmode, pt)
}
+ } else if (printTypings) {
+ println("no second try for "+fun+" and "+args+" because error not in result:"+ex.pos+"!="+tree.pos)
}
reportTypeError(tree.pos, ex)
setError(tree)
@@ -3774,10 +3790,10 @@ trait Typers { self: Analyzer =>
tree.tpe = null
if (tree.hasSymbol) tree.symbol = NoSymbol
}
- if (printTypings) println("typing "+tree+", "+context.undetparams+(mode & TYPEPATmode)); //DEBUG
+ if (printTypings) println("typing "+tree+", pt = "+pt+", undetparams = "+context.undetparams+", implicits-enabled = "+context.implicitsEnabled+", silent = "+context.reportGeneralErrors); //DEBUG
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
- if (printTypings) println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams+", pt = "+pt); //DEBUG
+ if (printTypings) println("typed "+tree1+":"+tree1.tpe+(if (isSingleType(tree1.tpe)) " with underlying "+tree1.tpe.widen else "")+", undetparams = "+context.undetparams+", pt = "+pt); //DEBUG
tree1.tpe = addAnnotations(tree1, tree1.tpe)
@@ -3791,7 +3807,7 @@ trait Typers { self: Analyzer =>
case ex: ControlException => throw ex
case ex: TypeError =>
tree.tpe = null
- //Console.println("caught "+ex+" in typed");//DEBUG
+ if (printTypings) println("caught "+ex+" in typed: "+tree);//DEBUG
reportTypeError(tree.pos, ex)
setError(tree)
case ex: Exception =>