summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala79
1 files changed, 50 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 93ece4c8da..2c8cc897f7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -14,7 +14,7 @@ package tools.nsc
package typechecker
import scala.collection.{mutable, immutable}
-import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance }
+import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance, ListOfNil }
import mutable.ListBuffer
import symtab.Flags._
import Mode._
@@ -76,7 +76,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case s : SilentTypeError => f(s.reportableErrors)
}
}
- class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ class SilentTypeError private(val errors: List[AbsTypeError], val warnings: List[(Position, String)]) extends SilentResult[Nothing] {
override def isEmpty = true
def err: AbsTypeError = errors.head
def reportableErrors = errors match {
@@ -87,10 +87,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
object SilentTypeError {
- def apply(errors: AbsTypeError*): SilentTypeError = new SilentTypeError(errors.toList)
+ def apply(errors: AbsTypeError*): SilentTypeError = apply(errors.toList, Nil)
+ def apply(errors: List[AbsTypeError], warnings: List[(Position, String)]): SilentTypeError = new SilentTypeError(errors, warnings)
+ // todo: this extracts only one error, should be a separate extractor.
def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
}
+ // todo: should include reporter warnings in SilentResultValue.
+ // e.g. tryTypedApply could print warnings on arguments when the typing succeeds.
case class SilentResultValue[+T](value: T) extends SilentResult[T] { override def isEmpty = false }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -147,7 +151,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
for(ar <- argResultsBuff)
paramTp = paramTp.subst(ar.subst.from, ar.subst.to)
- val res = if (paramFailed || (paramTp.isError && {paramFailed = true; true})) SearchFailure else inferImplicit(fun, paramTp, context.reportErrors, isView = false, context)
+ val res = if (paramFailed || (paramTp.isErroneous && {paramFailed = true; true})) SearchFailure else inferImplicit(fun, paramTp, context.reportErrors, isView = false, context)
argResultsBuff += res
if (res.isSuccess) {
@@ -241,7 +245,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case TypeRef(_, sym, _) if sym.isAliasType =>
val tp0 = tp.dealias
if (tp eq tp0) {
- debugwarn(s"dropExistential did not progress dealiasing $tp, see SI-7126")
+ devWarning(s"dropExistential did not progress dealiasing $tp, see SI-7126")
tp
} else {
val tp1 = dropExistential(tp0)
@@ -665,7 +669,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
@inline def wrapResult(reporter: ContextReporter, result: T) =
if (reporter.hasErrors) {
stopStats()
- SilentTypeError(reporter.errors: _*)
+ SilentTypeError(reporter.errors.toList, reporter.warnings.toList)
} else SilentResultValue(result)
try {
@@ -829,6 +833,16 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
orElse { _ =>
val resetTree = resetAttrs(original)
+ resetTree match {
+ case treeInfo.Applied(fun, targs, args) =>
+ if (fun.symbol != null && fun.symbol.isError)
+ // SI-9041 Without this, we leak error symbols past the typer!
+ // because the fallback typechecking notices the error-symbol,
+ // refuses to re-attempt typechecking, and presumes that someone
+ // else was responsible for issuing the related type error!
+ fun.setSymbol(NoSymbol)
+ case _ =>
+ }
debuglog(s"fallback on implicits: ${tree}/$resetTree")
val tree1 = typed(resetTree, mode)
// Q: `typed` already calls `pluginsTyped` and `adapt`. the only difference here is that
@@ -1012,11 +1026,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// to non-continuation types.
if (tree.tpe <:< AnyTpe) pt.dealias match {
case TypeRef(_, UnitClass, _) => // (12)
- if (settings.warnValueDiscard)
+ if (!isPastTyper && settings.warnValueDiscard)
context.warning(tree.pos, "discarded non-Unit value")
return typedPos(tree.pos, mode, pt)(Block(List(tree), Literal(Constant(()))))
case TypeRef(_, sym, _) if isNumericValueClass(sym) && isNumericSubType(tree.tpe, pt) =>
- if (settings.warnNumericWiden)
+ if (!isPastTyper && settings.warnNumericWiden)
context.warning(tree.pos, "implicit numeric widening")
return typedPos(tree.pos, mode, pt)(Select(tree, "to" + sym.name))
case _ =>
@@ -1164,7 +1178,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
def instantiatePossiblyExpectingUnit(tree: Tree, mode: Mode, pt: Type): Tree = {
- if (mode.typingExprNotFun && pt.typeSymbol == UnitClass)
+ if (mode.typingExprNotFun && pt.typeSymbol == UnitClass && !tree.tpe.isInstanceOf[MethodType])
instantiateExpectingUnit(tree, mode)
else
instantiate(tree, mode, pt)
@@ -1523,7 +1537,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val cbody1 = treeCopy.Block(cbody, preSuperStats, superCall1)
val clazz = context.owner
assert(clazz != NoSymbol, templ)
- val dummy = context.outer.owner.newLocalDummy(templ.pos)
+ // SI-9086 The position of this symbol is material: implicit search will avoid triggering
+ // cyclic errors in an implicit search in argument to the super constructor call on
+ // account of the "ignore symbols without complete info that succeed the implicit search"
+ // in this source file. See `ImplicitSearch#isValid` and `ImplicitInfo#isCyclicOrErroneous`.
+ val dummy = context.outer.owner.newLocalDummy(context.owner.pos)
val cscope = context.outer.makeNewScope(ctor, dummy)
if (dummy.isTopLevel) currentRun.symSource(dummy) = currentUnit.source.file
val cbody2 = { // called both during completion AND typing.
@@ -2013,7 +2031,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
if (mexists(vparamss)(_.symbol == superArg.symbol)) {
val alias = (
superAcc.initialize.alias
- orElse (superAcc getter superAcc.owner)
+ orElse (superAcc getterIn superAcc.owner)
filter (alias => superClazz.info.nonPrivateMember(alias.name) == alias)
)
if (alias.exists && !alias.accessed.isVariable && !isRepeatedParamType(alias.accessed.info)) {
@@ -2022,7 +2040,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case acc => acc
}
ownAcc match {
- case acc: TermSymbol if !acc.isVariable =>
+ case acc: TermSymbol if !acc.isVariable && !isByNameParamType(acc.info) =>
debuglog(s"$acc has alias ${alias.fullLocationString}")
acc setAlias alias
case _ =>
@@ -2534,7 +2552,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val default = methodSym newValueParameter (newTermName("default"), tree.pos.focus, SYNTHETIC) setInfo functionType(List(A1.tpe), B1.tpe)
val paramSyms = List(x, default)
- methodSym setInfo polyType(List(A1, B1), MethodType(paramSyms, B1.tpe))
+ methodSym setInfo genPolyType(List(A1, B1), MethodType(paramSyms, B1.tpe))
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym))
if (!paramSynthetic) methodBodyTyper.context.scope enter x
@@ -2834,7 +2852,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
ClassDef(Modifiers(FINAL), tpnme.ANON_FUN_NAME, tparams = Nil,
gen.mkTemplate(
parents = TypeTree(samClassTpFullyDefined) :: serializableParentAddendum,
- self = emptyValDef,
+ self = noSelfType,
constrMods = NoMods,
vparamss = ListOfNil,
body = List(samDef),
@@ -2903,7 +2921,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
var issuedMissingParameterTypeError = false
foreach2(fun.vparams, argpts) { (vparam, argpt) =>
if (vparam.tpt.isEmpty) {
- vparam.tpt.tpe =
+ val vparamType =
if (isFullyDefined(argpt)) argpt
else {
fun match {
@@ -2922,6 +2940,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
issuedMissingParameterTypeError = true
ErrorType
}
+ vparam.tpt.setType(vparamType)
if (!vparam.tpt.pos.isDefined) vparam.tpt setPos vparam.pos.focus
}
}
@@ -3356,7 +3375,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// defaults are needed. they are added to the argument list in named style as
// calls to the default getters. Example:
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
- checkNotMacro()
// SI-8111 transformNamedApplication eagerly shuffles around the application to preserve
// evaluation order. During this process, it calls `changeOwner` on symbols that
@@ -3403,6 +3421,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
duplErrTree
} else if (lencmp2 == 0) {
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
+ checkNotMacro()
context.diagUsedDefaults = true
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
} else {
@@ -4334,7 +4353,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def narrowRhs(tp: Type) = { val sym = context.tree.symbol
context.tree match {
case ValDef(mods, _, _, Apply(Select(`tree`, _), _)) if !mods.isMutable && sym != null && sym != NoSymbol =>
- val sym1 = if (sym.owner.isClass && sym.getter(sym.owner) != NoSymbol) sym.getter(sym.owner)
+ val sym1 = if (sym.owner.isClass && sym.getterIn(sym.owner) != NoSymbol) sym.getterIn(sym.owner)
else sym.lazyAccessorOrSelf
val pre = if (sym1.owner.isClass) sym1.owner.thisType else NoPrefix
intersectionType(List(tp, singleType(pre, sym1)))
@@ -4408,7 +4427,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
- def onError(typeErrors: Seq[AbsTypeError]): Tree = {
+ def onError(typeErrors: Seq[AbsTypeError], warnings: Seq[(Position, String)]): Tree = {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -4456,10 +4475,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
typeErrors foreach context.issue
+ warnings foreach { case (p, m) => context.warning(p, m) }
setError(treeCopy.Apply(tree, fun, args))
}
- silent(_.doTypedApply(tree, fun, args, mode, pt)) orElse onError
+ silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
+ case SilentResultValue(value) => value
+ case e: SilentTypeError => onError(e.errors, e.warnings)
+ }
}
def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = {
@@ -4510,6 +4533,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case err: SilentTypeError =>
onError({
err.reportableErrors foreach context.issue
+ err.warnings foreach { case (p, m) => context.warning(p, m) }
args foreach (arg => typed(arg, mode, ErrorType))
setError(tree)
})
@@ -5162,15 +5186,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def warn(message: String) = context.warning(lit.pos, s"possible missing interpolator: $message")
def suspiciousSym(name: TermName) = context.lookupSymbol(name, _ => true).symbol
def suspiciousExpr = InterpolatorCodeRegex findFirstIn s
- def suspiciousIdents = InterpolatorIdentRegex findAllIn s map (s => suspiciousSym(s drop 1))
+ def suspiciousIdents = InterpolatorIdentRegex findAllIn s map (s => suspiciousSym(TermName(s drop 1)))
- // heuristics - no warning on e.g. a string with only "$asInstanceOf"
- if (s contains ' ') (
- if (suspiciousExpr.nonEmpty)
- warn("detected an interpolated expression") // "${...}"
- else
- suspiciousIdents find isPlausible foreach (sym => warn(s"detected interpolated identifier `$$${sym.name}`")) // "$id"
- )
+ if (suspiciousExpr.nonEmpty)
+ warn("detected an interpolated expression") // "${...}"
+ else
+ suspiciousIdents find isPlausible foreach (sym => warn(s"detected interpolated identifier `$$${sym.name}`")) // "$id"
}
lit match {
case Literal(Constant(s: String)) if !isRecognizablyNotForInterpolation => maybeWarn(s)
@@ -5348,8 +5369,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
)
def runTyper(): Tree = {
if (retypingOk) {
- tree.tpe = null
- if (tree.hasSymbol) tree.symbol = NoSymbol
+ tree.setType(null)
+ if (tree.hasSymbolField) tree.symbol = NoSymbol
}
val alreadyTyped = tree.tpe ne null
val shouldPrint = !alreadyTyped && !phase.erasedTypes