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.scala91
1 files changed, 59 insertions, 32 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 192917d4aa..837ccf7e06 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -13,11 +13,12 @@ package scala
package tools.nsc
package typechecker
-import scala.collection.{mutable, immutable}
-import scala.reflect.internal.util.{ Statistics, ListOfNil }
+import scala.collection.{immutable, mutable}
+import scala.reflect.internal.util.{ListOfNil, Statistics}
import mutable.ListBuffer
import symtab.Flags._
import Mode._
+import scala.reflect.macros.whitebox
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -1690,7 +1691,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
supertpts mapConserve (tpt => checkNoEscaping.privates(context.owner, tpt))
}
catch {
- case ex: TypeError =>
+ case ex: TypeError if !global.propagateCyclicReferences =>
// fallback in case of cyclic errors
// @H none of the tests enter here but I couldn't rule it out
// upd. @E when a definition inherits itself, we end up here
@@ -1751,13 +1752,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
context.deprecationWarning(parent.pos, psym, report, version)
}
- if (psym.isSealed && !phase.erasedTypes)
- if (sameSourceFile)
- psym addChild context.owner
- else
- pending += ParentSealedInheritanceError(parent, psym)
- if (psym.isLocalToBlock && !phase.erasedTypes)
- psym addChild context.owner
val parentTypeOfThis = parent.tpe.dealias.typeOfThis
if (!(selfType <:< parentTypeOfThis) &&
@@ -2033,7 +2027,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// use typedValDef instead. this version is called after creating a new context for the ValDef
private def typedValDefImpl(vdef: ValDef) = {
val sym = vdef.symbol.initialize
- val typedMods = typedModifiers(vdef.mods)
+ val typedMods = if (nme.isLocalName(sym.name) && sym.isPrivateThis && !vdef.mods.isPrivateLocal) {
+ // SI-10009 This tree has been given a field symbol by `enterGetterSetter`, patch up the
+ // modifiers accordingly so that we can survive resetAttrs and retypechecking.
+ // Similarly, we use `sym.name` rather than `vdef.name` below to use the local name.
+ typedModifiers(vdef.mods.copy(flags = sym.flags, privateWithin = tpnme.EMPTY))
+ } else typedModifiers(vdef.mods)
sym.annotations.map(_.completeInfo())
val tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt))
@@ -2041,7 +2040,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// allow trait accessors: it's the only vehicle we have to hang on to annotations that must be passed down to
// the field that's mixed into a subclass
- if (sym.hasAnnotation(definitions.VolatileAttr) && !((sym hasFlag MUTABLE) || (sym hasFlag ACCESSOR) && sym.owner.isTrait))
+ if (sym.hasAnnotation(definitions.VolatileAttr) && !((sym hasFlag MUTABLE | LAZY) || (sym hasFlag ACCESSOR) && sym.owner.isTrait))
VolatileValueError(vdef)
val rhs1 =
@@ -2068,7 +2067,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
} else tpt1.tpe
transformedOrTyped(vdef.rhs, EXPRmode | BYVALmode, tpt2)
}
- treeCopy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
+ treeCopy.ValDef(vdef, typedMods, sym.name, tpt1, checkDead(rhs1)) setType NoType
}
/** Enter all aliases of local parameter accessors.
@@ -2568,7 +2567,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// TODO: add fallback __match sentinel to predef
val matchStrategy: Tree =
- if (!(settings.Xexperimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
+ if (!(settings.Yvirtpatmat && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match)), reportAmbiguousErrors = false) orElse (_ => null)
if (matchStrategy ne null) // virtualize
@@ -3415,7 +3414,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// governed by a) the argument types and b) the expected type
val args1 = typedArgs(args, forArgMode(fun, mode))
val pts = args1.map(_.tpe.deconst)
- val clone = fun.symbol.cloneSymbol
+ val clone = fun.symbol.cloneSymbol.withoutAnnotations
val cloneParams = pts map (pt => clone.newValueParameter(currentUnit.freshTermName()).setInfo(pt))
val resultType = if (isFullyDefined(pt)) pt else ObjectTpe
clone.modifyInfo(mt => copyMethodType(mt, cloneParams, resultType))
@@ -4638,22 +4637,55 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
val opeqStart = if (Statistics.canEnable) Statistics.startTimer(failedOpEqNanos) else null
- def onError(reportError: => Tree): Tree = fun match {
- case Select(qual, name)
- if !mode.inPatternMode && nme.isOpAssignmentName(newTermName(name.decode)) && !qual.exists(_.isErroneous) =>
+ def isConversionCandidate(qual: Tree, name: Name): Boolean =
+ !mode.inPatternMode && nme.isOpAssignmentName(TermName(name.decode)) && !qual.exists(_.isErroneous)
+ def reportError(error: SilentTypeError): Tree = {
+ error.reportableErrors foreach context.issue
+ error.warnings foreach { case (p, m) => context.warning(p, m) }
+ args foreach (arg => typed(arg, mode, ErrorType))
+ setError(tree)
+ }
+ def advice1(convo: Tree, errors: List[AbsTypeError], err: SilentTypeError): List[AbsTypeError] =
+ errors.map { e =>
+ if (e.errPos == tree.pos) {
+ val header = f"${e.errMsg}%n Expression does not convert to assignment because:%n "
+ val expansion = f"%n expansion: ${show(convo)}"
+ NormalTypeError(tree, err.errors.flatMap(_.errMsg.lines.toList).mkString(header, f"%n ", expansion))
+ } else e
+ }
+ def advice2(errors: List[AbsTypeError]): List[AbsTypeError] =
+ errors.map { e =>
+ if (e.errPos == tree.pos) {
+ val msg = f"${e.errMsg}%n Expression does not convert to assignment because receiver is not assignable."
+ NormalTypeError(tree, msg)
+ } else e
+ }
+ def onError(error: SilentTypeError): Tree = fun match {
+ case Select(qual, name) if isConversionCandidate(qual, name) =>
val qual1 = typedQualifier(qual)
if (treeInfo.isVariableOrGetter(qual1)) {
if (Statistics.canEnable) Statistics.stopTimer(failedOpEqNanos, opeqStart)
- convertToAssignment(fun, qual1, name, args)
+ val erred = qual1.isErroneous || args.exists(_.isErroneous)
+ if (erred) reportError(error) else {
+ val convo = convertToAssignment(fun, qual1, name, args)
+ silent(op = _.typed1(convo, mode, pt)) match {
+ case SilentResultValue(t) => t
+ case err: SilentTypeError => reportError(SilentTypeError(advice1(convo, error.errors, err), error.warnings))
+ }
+ }
}
else {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
- reportError
+ val Apply(Select(qual2, _), args2) = tree
+ val erred = qual2.isErroneous || args2.exists(_.isErroneous)
+ reportError {
+ if (erred) error else SilentTypeError(advice2(error.errors), error.warnings)
+ }
}
case _ =>
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, appStart)
- reportError
+ reportError(error)
}
val silentResult = silent(
op = _.typed(fun, mode.forFunMode, funpt),
@@ -4678,13 +4710,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
tryTypedApply(fun2, args)
else
doTypedApply(tree, fun2, args, mode, pt)
- 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)
- })
+ case err: SilentTypeError => onError(err)
}
}
@@ -4727,7 +4753,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
Select(vble.duplicate, prefix) setPos fun.pos.focus, args) setPos tree.pos.makeTransparent
) setPos tree.pos
- def mkUpdate(table: Tree, indices: List[Tree]) = {
+ def mkUpdate(table: Tree, indices: List[Tree]) =
gen.evalOnceAll(table :: indices, context.owner, context.unit) {
case tab :: is =>
def mkCall(name: Name, extraArgs: Tree*) = (
@@ -4742,9 +4768,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
)
case _ => EmptyTree
}
- }
- val tree1 = qual match {
+ val assignment = qual match {
case Ident(_) =>
mkAssign(qual)
@@ -4760,7 +4785,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case _ => UnexpectedTreeAssignmentConversionError(qual)
}
}
- typed1(tree1, mode, pt)
+ assignment
}
def typedSuper(tree: Super) = {
@@ -5561,6 +5586,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
try runTyper() catch {
+ case ex: CyclicReference if global.propagateCyclicReferences =>
+ throw ex
case ex: TypeError =>
tree.clearType()
// The only problematic case are (recoverable) cyclic reference errors which can pop up almost anywhere.