summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Infer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Infer.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala303
1 files changed, 167 insertions, 136 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 26e4da5d79..354eb52913 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -189,7 +189,7 @@ trait Infer {
private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)
/** The context-dependent inferencer part */
- class Inferencer(context: Context) extends InferencerErrorTrees {
+ class Inferencer(context: Context) {
/* -- Error Messages --------------------------------------------------- */
def setError[T <: Tree](tree: T): T = {
def name = newTermName("<error: " + tree.symbol + ">")
@@ -203,20 +203,19 @@ trait Infer {
tree setType ErrorType
}
- protected def getContext = context
-
def error(pos: Position, msg: String) {
context.error(pos, msg)
}
-/* def makeErrorTree(tree: Tree, msg: String): Tree = {
+ def errorTree(tree: Tree, msg: String): Tree = {
if (!tree.isErroneous) error(tree.pos, msg)
setError(tree)
- }*/
+ }
def typeError(pos: Position, found: Type, req: Type) {
if (!found.isErroneous && !req.isErroneous) {
error(pos, withAddendum(pos)(typeErrorMsg(found, req)))
+
if (settings.explaintypes.value)
explainTypes(found, req)
}
@@ -229,8 +228,6 @@ trait Infer {
"type mismatch" + foundReqMsg(found, req) + missingArgsMsg
}
- // TODO: replace with standard Error tree
- // currently only used in adapt in Typers
def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = {
// If the expected type is a refinement type, and the found type is a refinement or an anon
// class, we can greatly improve the error message by retyping the tree to recover the actual
@@ -290,7 +287,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, context.enclClass.owner,
+ new AccessError(tree, sym, pre,
if (settings.check.isDefault)
analyzer.lastAccessCheckDetails
else
@@ -317,17 +314,11 @@ trait Infer {
if (settings.debug.value) ex.printStackTrace
val sym2 = underlying(sym1)
val itype = pre.memberType(sym2)
- return AccessError(tree, sym, pre, context.enclClass.owner,
+ 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))
-
-// enabling the following TypeError case
-// crashes a few examples because there are situations (like in NamesDefaults)
-// where CyclicReference is expected
-// case ex: TypeError =>
-// return TypeErrorTree(tree, ex)(context)
-
+ else " contains a "+ex.msg)).emit()
+ ErrorType
}
if (pre.isInstanceOf[SuperType])
owntype = owntype.substSuper(pre, site.symbol.thisType)
@@ -920,9 +911,7 @@ trait Infer {
false
}
- /**
- * Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
- * The chance of TypeErrors should be reduced through error trees
+ /** Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
*/
private[typechecker] def isApplicableSafe(undetparams: List[Symbol], ftpe: Type,
argtpes0: List[Type], pt: Type): Boolean = {
@@ -1103,20 +1092,37 @@ trait Infer {
*/
/** error if arguments not within bounds. */
def checkBounds(pos: Position, pre: Type, owner: Symbol,
- tparams: List[Symbol], targs: List[Type], prefix: String): Option[ErrorTree] = {
+ tparams: List[Symbol], targs: List[Type], prefix: String) = {
//@M validate variances & bounds of targs wrt variances & bounds of tparams
//@M TODO: better place to check this?
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
- if(!kindErrors.isEmpty) {
- if (targs contains WildcardType) None
- else Some(KindBoundErrors(pos, prefix, targs, tparams, kindErrors))
- } else if (!isWithinBounds(pre, owner, tparams, targs)) {
- if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous)))
- Some(NotWithinBounds(pos, prefix, targs, tparams, kindErrors))
- else None
- } else None
+ if (!kindErrors.isEmpty) {
+ if (targs contains WildcardType) ()
+ else error(pos,
+ prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
+ " do not conform to the expected kinds of the type parameters "+
+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
+ kindErrors.toList.mkString("\n", ", ", ""))
+ }
+ else if (!isWithinBounds(pre, owner, tparams, targs)) {
+ if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
+ //val bounds = instantiatedBounds(pre, owner, tparams, targs)//DEBUG
+ //println("bounds = "+bounds+", targs = "+targs+", targclasses = "+(targs map (_.getClass))+", parents = "+(targs map (_.parents)))
+ //println(List.map2(bounds, targs)((bound, targ) => bound containsType targ))
+ error(pos,
+ prefix + "type arguments " + targs.mkString("[", ",", "]") +
+ " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
+ (tparams map (_.defString)).mkString("[", ",", "]"))
+ if (settings.explaintypes.value) {
+ val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi))
+ ()
+ }
+ }
+ }
}
@@ -1160,7 +1166,7 @@ trait Infer {
* first to `strictPt` and then, if this fails, to `lenientPt`. If both
* attempts fail, an error is produced.
*/
- def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type) = {
+ def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type) {
printInference(
ptBlock("inferArgumentInstance",
"tree" -> tree,
@@ -1174,8 +1180,8 @@ trait Infer {
if ((targs eq null) || !(tree.tpe.subst(undetparams, targs) <:< strictPt)) {
targs = exprTypeArgs(undetparams, tree.tpe, lenientPt)
}
- printInference("[inferArgumentInstance] finished, targs = " + targs)
substExpr(tree, undetparams, targs, lenientPt)
+ printInference("[inferArgumentInstance] finished, targs = " + targs)
}
/** Infer type arguments `targs` for `tparams` of polymorphic expression in `tree`, given prototype `pt`.
@@ -1183,7 +1189,7 @@ trait Infer {
* Substitute `tparams` to `targs` in `tree`, after adjustment by `adjustTypeArgs`, returning the type parameters that were not determined
* If passed, infers against specified type `treeTp` instead of `tree.tp`.
*/
- def inferExprInstance(tree: Tree, tparams: List[Symbol], pt: Type = WildcardType, treeTp0: Type = null, keepNothings: Boolean = true, useWeaklyCompatible: Boolean = false): (Option[ErrorTree], List[Symbol]) = {
+ def inferExprInstance(tree: Tree, tparams: List[Symbol], pt: Type = WildcardType, treeTp0: Type = null, keepNothings: Boolean = true, useWeaklyCompatible: Boolean = false): List[Symbol] = {
val treeTp = if(treeTp0 eq null) tree.tpe else treeTp0 // can't refer to tree in default for treeTp0
printInference(
ptBlock("inferExprInstance",
@@ -1196,7 +1202,8 @@ trait Infer {
val targs = exprTypeArgs(tparams, treeTp, pt, useWeaklyCompatible)
if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
- (substExpr(tree, tparams, targs, pt), List())
+ substExpr(tree, tparams, targs, pt)
+ List()
} else {
val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, targs)
printInference(
@@ -1206,7 +1213,8 @@ trait Infer {
"leftUndet" -> leftUndet
)
)
- (substExpr(tree, okParams, okArgs, pt), leftUndet)
+ substExpr(tree, okParams, okArgs, pt)
+ leftUndet
}
}
@@ -1219,15 +1227,13 @@ trait Infer {
* @param pt ...
*/
private def substExpr(tree: Tree, undetparams: List[Symbol],
- targs: List[Type], pt: Type): Option[ErrorTree] = {
+ targs: List[Type], pt: Type) {
if (targs eq null) {
if (!tree.tpe.isErroneous && !pt.isErroneous)
- Some(PolymorphicExpressionInstantiationError(tree, undetparams, pt))
- else
- None
+ error(tree.pos, "polymorphic expression cannot be instantiated to expected type" +
+ foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt))
} else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- None
}
}
@@ -1242,7 +1248,7 @@ trait Infer {
* and that thus have not been substituted.
*/
def inferMethodInstance(fn: Tree, undetparams: List[Symbol],
- args: List[Tree], pt0: Type): Either[ErrorTree, List[Symbol]] = fn.tpe match {
+ args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
case MethodType(params0, _) =>
printInference(
ptBlock("inferMethodInstance",
@@ -1262,32 +1268,31 @@ trait Infer {
val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
methTypeArgs(undetparams, formals, restpe, argtpes, pt)
- checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ") match {
- case Some(err) =>
- Left(err)
- case _ =>
- // bounds are ok
- val treeSubst = new TreeTypeSubstituter(okparams, okargs)
- treeSubst traverseTrees fn :: args
-
- val result = leftUndet match {
- case Nil => Nil
- case xs =>
- // #3890
- val xs1 = treeSubst.typeSubst mapOver xs
- if (xs ne xs1)
- new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
-
- xs1
- }
- if (result.nonEmpty)
- printInference("inferMethodInstance, still undetermined: " + result)
+ checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")
+ val treeSubst = new TreeTypeSubstituter(okparams, okargs)
+ treeSubst traverseTrees fn :: args
- Right(result)
+ val result = leftUndet match {
+ case Nil => Nil
+ case xs =>
+ // #3890
+ val xs1 = treeSubst.typeSubst mapOver xs
+ if (xs ne xs1)
+ new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
+
+ xs1
}
+ if (result.nonEmpty)
+ printInference("inferMethodInstance, still undetermined: " + result)
+
+ result
}
catch ifNoInstance { msg =>
- Left(NoMethodInstanceError(fn, args, msg))
+ errorTree(fn, "no type parameters for " +
+ applyErrorMsg(fn, " exist so that it can be applied to arguments ", args map (_.tpe.widen), WildcardType) +
+ "\n --- because ---\n" + msg
+ )
+ Nil
}
}
@@ -1312,7 +1317,7 @@ trait Infer {
* @param undetparams the undetermined type parameters
* @param pt the expected result type of the instance
*/
- def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type): Option[ErrorTree] = {
+ def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
val pt = widen(pt0)
//println("infer constr inst "+tree+"/"+undetparams+"/"+pt0)
var restpe = tree.tpe.finalResultType
@@ -1327,14 +1332,17 @@ trait Infer {
// checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- None
- } catch ifNoInstance{ msg =>
- Some(NoConstructorInstanceError(tree, restpe, pt, msg))
+ } catch {
+ case ex: NoInstance =>
+ errorTree(tree, "constructor of type " + restpe +
+ " cannot be uniquely instantiated to expected type " + pt +
+ "\n --- because ---\n" + ex.getMessage())
}
def instError = {
if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
if (settings.explaintypes.value) explainTypes(restpe.instantiateTypeParams(undetparams, tvars), pt)
- Some(ConstrInstantiationError(tree, restpe, pt))
+ errorTree(tree, "constructor cannot be instantiated to expected type" +
+ foundReqMsg(restpe, pt))
}
if (restpe.instantiateTypeParams(undetparams, tvars) <:< pt) {
computeArgs
@@ -1352,7 +1360,6 @@ trait Infer {
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
if (isPopulated(restpe, pt1)) {
ptvars foreach instantiateTypeVar
- None
} else { if (settings.debug.value) Console.println("no instance: "); instError }
} else { if (settings.debug.value) Console.println("not a subtype " + restpe.instantiateTypeParams(undetparams, tvars) + " of " + ptWithWildcards); instError }
} else { if (settings.debug.value) Console.println("not fully defined: " + pt); instError }
@@ -1405,12 +1412,11 @@ trait Infer {
}
}
- def checkCheckable(pos: Position, tp: Type, kind: String): Option[ErrorTree] = {
+ def checkCheckable(pos: Position, tp: Type, kind: String) {
def patternWarning(tp0: Type, prefix: String) = {
context.unit.uncheckedWarning(pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure")
}
- def check(tp: Type, bound: List[Symbol]): Option[ErrorTree] = {
- implicit def listErrorsToPending(l: List[ErrorTree]): Option[ErrorTree] = if (l.isEmpty) None else Some(PendingErrors(l))
+ def check(tp: Type, bound: List[Symbol]) {
def isLocalBinding(sym: Symbol) =
sym.isAbstractType &&
((bound contains sym) ||
@@ -1422,38 +1428,36 @@ trait Infer {
case SingleType(pre, _) =>
check(pre, bound)
case TypeRef(pre, sym, args) =>
- val checkForSymAndArgs: Option[ErrorTree] = if (sym.isAbstractType) {
+ if (sym.isAbstractType) {
if (!isLocalBinding(sym)) patternWarning(tp, "abstract type ")
- None
} else if (sym.isAliasType) {
check(tp.normalize, bound)
} else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) {
- Some(TypePatternOrIsInstanceTestError(pos, tp))
+ error(pos, "type "+tp+" cannot be used in a type pattern or isInstanceOf test")
} else {
- args.map( arg => {
+ for (arg <- args) {
if (sym == ArrayClass) check(arg, bound)
- else if (arg.typeArgs.nonEmpty) None // avoid spurious warnings with higher-kinded types
- else {arg match {
+ else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types
+ else arg match {
case TypeRef(_, sym, _) if isLocalBinding(sym) =>
-
+ ;
case _ =>
patternWarning(arg, "non variable type-argument ")
- }; None}
- }).flatten
+ }
+ }
}
- List(checkForSymAndArgs, check(pre, bound)).flatten
+ check(pre, bound)
case RefinedType(parents, decls) =>
- if (decls.isEmpty) parents.map(p => check(p, bound)).flatten
- else { patternWarning(tp, "refinement "); None }
+ if (decls.isEmpty) for (p <- parents) check(p, bound)
+ else patternWarning(tp, "refinement ")
case ExistentialType(quantified, tp1) =>
check(tp1, bound ::: quantified)
case ThisType(_) =>
- None
+ ;
case NoPrefix =>
- None
+ ;
case _ =>
patternWarning(tp, "type ")
- None
}
}
check(tp, List())
@@ -1476,7 +1480,7 @@ trait Infer {
}
}
- def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Either[ErrorTree, Type] = {
+ def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Type = {
val pt = widen(pt0)
val ptparams = freeTypeParamsOfTerms.collect(pt)
val tpparams = freeTypeParamsOfTerms.collect(pattp)
@@ -1489,13 +1493,9 @@ trait Infer {
* and is a "final type", meaning final + invariant in all type parameters.
*/
if (pt.isFinalType && ptparams.isEmpty && !ptMatchesPattp)
- return Left(IncompatibleScrutineeTypeError(pos, pattp, pt))
+ error(pos, "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt))
- checkCheckable(pos, pattp, "pattern ") match {
- case Some(err) =>
- return Left(err)
- case _ => ()
- }
+ checkCheckable(pos, pattp, "pattern ")
if (pattp <:< pt) ()
else {
debuglog("free type params (1) = " + tpparams)
@@ -1517,8 +1517,10 @@ trait Infer {
// fail if we didn't allow for pattpMatchesPt.
if (isPopulated(tp, pt1) && isInstantiatable(tvars ++ ptvars) || pattpMatchesPt)
ptvars foreach instantiateTypeVar
- else
- return Left(IncompletePatternTypeError(pos, pattp, pt))
+ else {
+ error(pos, "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt))
+ return pattp
+ }
}
tvars foreach instantiateTypeVar
}
@@ -1526,22 +1528,43 @@ trait Infer {
* we have to flip the arguments so the expected type is treated as more
* general when calculating the intersection. See run/bug2755.scala.
*/
- if (tpparams.isEmpty && ptparams.nonEmpty) Right(intersect(pattp, pt))
- else Right(intersect(pt, pattp))
+ if (tpparams.isEmpty && ptparams.nonEmpty) intersect(pattp, pt)
+ else intersect(pt, pattp)
}
- def inferModulePattern(pat: Tree, pt: Type): Option[ErrorTree] =
+ def inferModulePattern(pat: Tree, pt: Type) =
if (!(pat.tpe <:< pt)) {
val ptparams = freeTypeParamsOfTerms.collect(pt)
debuglog("free type params (2) = " + ptparams)
val ptvars = ptparams map freshVar
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
- if (pat.tpe <:< pt1) {
+ if (pat.tpe <:< pt1)
ptvars foreach instantiateTypeVar
- None
- } else
- Some(PatternTypeIncompatibleWithPtError(pat, pt1, pt))
- } else None
+ else {
+ val sym = pat.tpe.typeSymbol
+ val clazz = sym.companionClass
+ val addendum = (
+ if (sym.isModuleClass && clazz.isCaseClass && (clazz isSubClass pt1.typeSymbol)) {
+ // TODO: move these somewhere reusable.
+ val typeString = clazz.typeParams match {
+ case Nil => "" + clazz.name
+ case xs => xs map (_ => "_") mkString (clazz.name + "[", ",", "]")
+ }
+ val caseString = (
+ clazz.caseFieldAccessors
+ map (_ => "_") // could use the actual param names here
+ mkString (clazz.name + "(", ",", ")")
+ )
+ (
+ "\nNote: if you intended to match against the class, try `case _: " +
+ typeString + "` or `case " + caseString + "`"
+ )
+ }
+ else ""
+ )
+ error(pat.pos, "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt) + addendum)
+ }
+ }
object toOrigin extends TypeMap {
def apply(tp: Type): Type = tp match {
@@ -1608,7 +1631,7 @@ trait Infer {
* If several alternatives match `pt`, take parameterless one.
* If no alternative matches `pt`, take the parameterless one anyway.
*/
- def inferExprAlternative(tree: Tree, pt: Type): Option[ErrorTree] = tree.tpe match {
+ def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice {
val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
val secondTry = alts0.isEmpty
@@ -1639,27 +1662,24 @@ trait Infer {
case _ =>
}
}
- Some(NoBestExprAlternativeError(tree, pt))
+ typeErrorTree(tree, tree.symbol.tpe, pt)
} else if (!competing.isEmpty) {
if (secondTry) {
- Some(NoBestExprAlternativeError(tree, pt))
+ typeErrorTree(tree, tree.symbol.tpe, pt)
} else {
if (!pt.isErroneous)
- Some(AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt))
- else
- Some(NullErrorTree) // already reported
+ context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
+ setError(tree)
}
} else {
// val applicable = alts1 filter (alt =>
// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
- None
}
}
}
- // TODO: remove once error tree refactoring is done
@inline private def wrapTypeError(expr: => Boolean): Boolean =
try expr
catch { case _: TypeError => false }
@@ -1723,7 +1743,7 @@ trait Infer {
* assignment expression.
*/
def inferMethodAlternative(tree: Tree, undetparams: List[Symbol],
- argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false): Option[ErrorTree] = tree.tpe match {
+ argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false): Unit = tree.tpe match {
case OverloadedType(pre, alts) =>
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
tryTwice {
@@ -1750,22 +1770,24 @@ trait Infer {
if (improves(alt, best)) alt else best)
val competing = applicable.dropWhile(alt => best == alt || improves(best, alt))
if (best == NoSymbol) {
- if (pt == WildcardType)
- Some(NoBestMethodAlternativeError(tree, argtpes, pt))
- else
+ if (pt == WildcardType) {
+ errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+ } else {
inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
+ }
} else if (!competing.isEmpty) {
if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous)
- Some(AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt))
- else
- Some(NullErrorTree)
+ context.ambiguousError(tree.pos, pre, best, competing.head,
+ "argument types " + argtpes.mkString("(", ",", ")") +
+ (if (pt == WildcardType) "" else " and expected result type " + pt))
+ setError(tree)
+ ()
} else {
// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
- None
}
}
- case _ => None
+ case _ =>
}
/** Try inference twice, once without views and once with views,
@@ -1773,25 +1795,18 @@ trait Infer {
*
* @param infer ...
*/
- def tryTwice(infer: => Option[ErrorTree]): Option[ErrorTree] = {
+ def tryTwice(infer: => Unit) {
if (context.implicitsEnabled) {
val reportGeneralErrors = context.reportGeneralErrors
context.reportGeneralErrors = false
- val res = try {
- context.withImplicitsDisabled(infer) match {
- case Some(err) =>
- context.reportGeneralErrors = reportGeneralErrors
- infer
- case ok => ok
- }
- } catch {
+ try context.withImplicitsDisabled(infer)
+ catch {
case ex: CyclicReference => throw ex
case ex: TypeError =>
context.reportGeneralErrors = reportGeneralErrors
infer
}
context.reportGeneralErrors = reportGeneralErrors
- res
}
else infer
}
@@ -1803,10 +1818,10 @@ trait Infer {
* @param tree ...
* @param nparams ...
*/
- def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Option[ErrorTree] = {
+ def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Unit = {
val OverloadedType(pre, alts) = tree.tpe
val sym0 = tree.symbol filter (alt => sameLength(alt.typeParams, argtypes))
- def fail(msg: String) = Some(PolyAlternativeError(tree, msg))
+ def fail(msg: String): Unit = error(tree.pos, msg)
if (sym0 == NoSymbol) return fail(
if (alts exists (_.typeParams.nonEmpty))
@@ -1820,13 +1835,12 @@ trait Infer {
else {
val sym = sym0 filter (alt => isWithinBounds(pre, alt.owner, alt.typeParams, argtypes))
if (sym == NoSymbol) {
- if (argtypes forall (x => !x.isErroneous))
- return fail(
+ if (argtypes forall (x => !x.isErroneous)) fail(
"type arguments " + argtypes.mkString("[", ",", "]") +
" conform to the bounds of none of the overloaded alternatives of\n "+sym0+
": "+sym0.info
)
- return None
+ return
}
else if (sym.isOverloaded) {
val xs = sym.alternatives
@@ -1841,7 +1855,24 @@ trait Infer {
}
// Side effects tree with symbol and type
tree setSymbol resSym setType resTpe
- None
+ }
+
+ abstract class TreeForwarder(forwardTo: Tree) extends Tree {
+ override def pos = forwardTo.pos
+ override def hasSymbol = forwardTo.hasSymbol
+ override def symbol = forwardTo.symbol
+ override def symbol_=(x: Symbol) = forwardTo.symbol = x
+ }
+
+ case class AccessError(tree: Tree, sym: Symbol, pre: Type, explanation: String) extends TreeForwarder(tree) {
+ setError(this)
+
+ // @PP: It is improbable this logic shouldn't be in use elsewhere as well.
+ private def location = if (sym.isClassConstructor) context.enclClass.owner else pre.widen
+ def emit(): Tree = {
+ val realsym = underlying(sym)
+ errorTree(tree, realsym.fullLocationString + " cannot be accessed in " + location + explanation)
+ }
}
}
}