summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala24
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala52
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala91
9 files changed, 143 insertions, 55 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index fcfcc8feb9..0910dca445 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -655,9 +655,6 @@ trait ContextErrors {
def ParentFinalInheritanceError(parent: Tree, mixin: Symbol) =
NormalTypeError(parent, "illegal inheritance from final "+mixin)
- def ParentSealedInheritanceError(parent: Tree, psym: Symbol) =
- NormalTypeError(parent, "illegal inheritance from sealed " + psym )
-
def ParentSelfTypeConformanceError(parent: Tree, selfType: Type) =
NormalTypeError(parent,
"illegal inheritance;\n self-type "+selfType+" does not conform to "+
@@ -1172,6 +1169,9 @@ trait ContextErrors {
def MissingParameterOrValTypeError(vparam: Tree) =
issueNormalTypeError(vparam, "missing parameter type")
+ def ParentSealedInheritanceError(parent: Tree, psym: Symbol) =
+ NormalTypeError(parent, "illegal inheritance from sealed " + psym )
+
def RootImportError(tree: Tree) =
issueNormalTypeError(tree, "_root_ cannot be imported")
@@ -1211,7 +1211,7 @@ trait ContextErrors {
"pass-by-name arguments not allowed for case class parameters"
case AbstractVar =>
- "only classes can have declared but undefined members" + abstractVarMessage(sym)
+ "only traits and abstract classes can have declared but undefined members" + abstractVarMessage(sym)
}
issueSymbolTypeError(sym, msg)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index c73ea54c3d..d349597b14 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -60,7 +60,7 @@ trait Contexts { self: Analyzer =>
private lazy val allImportInfos =
mutable.Map[CompilationUnit, List[ImportInfo]]() withDefaultValue Nil
- def warnUnusedImports(unit: CompilationUnit) = {
+ def warnUnusedImports(unit: CompilationUnit) = if (!unit.isJava) {
for (imps <- allImportInfos.remove(unit)) {
for (imp <- imps.reverse.distinct) {
val used = allUsedSelectors(imp)
@@ -1192,6 +1192,28 @@ trait Contexts { self: Analyzer =>
}
res
}
+
+ final def lookupCompanionOf(original: Symbol): Symbol = {
+ if (original.isModuleClass) original.sourceModule
+ else lookupScopeEntry(original) match {
+ case null => NoSymbol
+ case entry => entry.owner.lookupCompanion(original)
+ }
+ }
+
+ /** Search scopes in current and enclosing contexts for the definition of `symbol` */
+ private def lookupScopeEntry(symbol: Symbol): ScopeEntry = {
+ var res: ScopeEntry = null
+ var ctx = this
+ while (res == null && ctx.outer != ctx) {
+ val s = ctx.scope lookupSymbolEntry symbol
+ if (s != null)
+ res = s
+ else
+ ctx = ctx.outer
+ }
+ res
+ }
} //class Context
/** A `Context` focussed on an `Import` tree */
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 97de2b6c85..5f4fa499b6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -105,7 +105,7 @@ trait EtaExpansion { self: Analyzer =>
val origTpe = sym.tpe
val isRepeated = definitions.isRepeatedParamType(origTpe)
// SI-4176 Don't leak A* in eta-expanded function types. See t4176b.scala
- val droppedStarTpe = if (settings.etaExpandKeepsStar) origTpe else dropIllegalStarTypes(origTpe)
+ val droppedStarTpe = dropIllegalStarTypes(origTpe)
val valDef = ValDef(Modifiers(SYNTHETIC | PARAM), sym.name.toTermName, TypeTree(droppedStarTpe), EmptyTree)
(valDef, isRepeated)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 0071d66eb9..e8147dbf3a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -936,10 +936,8 @@ trait Infer extends Checkable {
def infer_s = map3(tparams, tvars, targs)((tparam, tvar, targ) => s"$tparam=$tvar/$targ") mkString ","
printTyping(tree, s"infer expr instance from pt=$pt, $infer_s")
- // SI-7899 inferring by-name types is unsound. The correct behaviour is conditional because the hole is
- // exploited in Scalaz (Free.scala), as seen in: run/t7899-regression.
- def dropByNameIfStrict(tp: Type): Type = if (settings.inferByName) tp else dropByName(tp)
- def targsStrict = if (targs eq null) null else targs mapConserve dropByNameIfStrict
+ // SI-7899 inferring by-name types is unsound
+ def targsStrict = if (targs eq null) null else targs mapConserve dropByName
if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
substExpr(tree, tparams, targsStrict, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index d11417192d..0f257d3717 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -132,7 +132,11 @@ trait MethodSynthesis {
// only one symbol can have `tree.pos`, the others must focus their position
// normally the field gets the range position, but if there is none, give it to the getter
+ //
+ // SI-10009 the tree's modifiers can be temporarily out of sync with the new symbol's flags.
+ // typedValDef corrects this later on.
tree.symbol = fieldSym orElse (getterSym setPos tree.pos)
+
val namer = namerOf(tree.symbol)
// the valdef gets the accessor symbol for a lazy val (too much going on in its RHS)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 78e8c8c073..395bda234b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -115,7 +115,7 @@ trait Namers extends MethodSynthesis {
protected def owner = context.owner
def contextFile = context.unit.source.file
def typeErrorHandler[T](tree: Tree, alt: T): PartialFunction[Throwable, T] = {
- case ex: TypeError =>
+ case ex: TypeError if !global.propagateCyclicReferences =>
// H@ need to ensure that we handle only cyclic references
TypeSigError(tree, ex)
alt
@@ -220,7 +220,10 @@ trait Namers extends MethodSynthesis {
private def inCurrentScope(m: Symbol): Boolean = {
if (owner.isClass) owner == m.owner
- else m.owner.isClass && context.scope == m.owner.info.decls
+ else context.scope.lookupSymbolEntry(m) match {
+ case null => false
+ case entry => entry.owner eq context.scope
+ }
}
/** Enter symbol into context's scope and return symbol itself */
@@ -902,9 +905,10 @@ trait Namers extends MethodSynthesis {
// Annotations on ValDefs can be targeted towards the following: field, getter, setter, beanGetter, beanSetter, param.
// The defaults are:
// - (`val`-, `var`- or plain) constructor parameter annotations end up on the parameter, not on any other entity.
- // - val/var member annotations solely end up on the underlying field, except in traits (@since 2.12),
+ // - val/var member annotations solely end up on the underlying field, except in traits and for all lazy vals (@since 2.12),
// where there is no field, and the getter thus holds annotations targeting both getter & field.
- // As soon as there is a field/getter (in subclasses mixing in the trait), we triage the annotations.
+ // As soon as there is a field/getter (in subclasses mixing in the trait, or after expanding the lazy val during the fields phase),
+ // we triage the annotations.
//
// TODO: these defaults can be surprising for annotations not meant for accessors/fields -- should we revisit?
// (In order to have `@foo val X` result in the X getter being annotated with `@foo`, foo needs to be meta-annotated with @getter)
@@ -918,15 +922,17 @@ trait Namers extends MethodSynthesis {
BeanPropertyAnnotationLimitationError(tree)
}
+ val canTriageAnnotations = isSetter || !fields.getterTreeAnnotationsTargetFieldAndGetter(owner, mods)
+
def filterAccessorAnnotations: AnnotationInfo => Boolean =
- if (isSetter || !owner.isTrait)
+ if (canTriageAnnotations)
annotationFilter(if (isSetter) SetterTargetClass else GetterTargetClass, defaultRetention = false)
else (ann =>
annotationFilter(FieldTargetClass, defaultRetention = true)(ann) ||
annotationFilter(GetterTargetClass, defaultRetention = true)(ann))
def filterBeanAccessorAnnotations: AnnotationInfo => Boolean =
- if (isSetter || !owner.isTrait)
+ if (canTriageAnnotations)
annotationFilter(if (isSetter) BeanSetterTargetClass else BeanGetterTargetClass, defaultRetention = false)
else (ann =>
annotationFilter(FieldTargetClass, defaultRetention = true)(ann) ||
@@ -1028,12 +1034,33 @@ trait Namers extends MethodSynthesis {
private def templateSig(templ: Template): Type = {
val clazz = context.owner
+
+ val parentTrees = typer.typedParentTypes(templ)
+
+ val pending = mutable.ListBuffer[AbsTypeError]()
+ parentTrees foreach { tpt =>
+ val ptpe = tpt.tpe
+ if(!ptpe.isError) {
+ val psym = ptpe.typeSymbol
+ val sameSourceFile = context.unit.source.file == psym.sourceFile
+
+ if (psym.isSealed && !phase.erasedTypes)
+ if (sameSourceFile)
+ psym addChild context.owner
+ else
+ pending += ParentSealedInheritanceError(tpt, psym)
+ if (psym.isLocalToBlock && !phase.erasedTypes)
+ psym addChild context.owner
+ }
+ }
+ pending.foreach(ErrorUtils.issueTypeError)
+
def checkParent(tpt: Tree): Type = {
if (tpt.tpe.isError) AnyRefTpe
else tpt.tpe
}
- val parents = typer.typedParentTypes(templ) map checkParent
+ val parents = parentTrees map checkParent
enterSelf(templ.self)
@@ -1827,6 +1854,12 @@ trait Namers extends MethodSynthesis {
abstract class TypeCompleter extends LazyType {
val tree: Tree
+ override def forceDirectSuperclasses: Unit = {
+ tree.foreach {
+ case dt: DefTree => global.withPropagateCyclicReferences(Option(dt.symbol).map(_.maybeInitialize))
+ case _ =>
+ }
+ }
}
def mkTypeCompleter(t: Tree)(c: Symbol => Unit) = new LockingTypeCompleter with FlagAgnosticCompleter {
@@ -1923,10 +1956,7 @@ trait Namers extends MethodSynthesis {
// use the lower-level scan through the current Context as a fall back.
if (!currentRun.compiles(owner)) owner.initialize
original.companionSymbol orElse {
- ctx.lookup(original.name.companionName, owner).suchThat(sym =>
- (original.isTerm || sym.hasModuleFlag) &&
- (sym isCoDefinedWith original)
- )
+ ctx.lookupCompanionOf(original)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
index 1df3449ce6..cd0c292d90 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
@@ -123,7 +123,7 @@ trait PatternTypers {
}
private def boundedArrayType(bound: Type): Type = {
- val tparam = context.owner freshExistential "" setInfo (TypeBounds upper bound)
+ val tparam = context.owner.freshExistential("", 0) setInfo (TypeBounds upper bound)
newExistentialType(tparam :: Nil, arrayType(tparam.tpe_*))
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 08cd5e5450..45dfb427f0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1158,6 +1158,7 @@ abstract class RefChecks extends Transform {
}
}
checkUndesiredProperties(rtpe.typeSymbol, tree.pos)
+ checkUndesiredProperties(rtpe.typeSymbol.primaryConstructor, tree.pos)
tree
}
@@ -1412,6 +1413,12 @@ abstract class RefChecks extends Transform {
transformTrees(annots flatMap (_.args))
}
+ def checkIsElisible(sym: Symbol) = if (sym ne null) sym.elisionLevel.foreach { level =>
+ if (!sym.isMethod || sym.isAccessor || sym.isLazy || sym.isDeferred)
+ reporter.error(sym.pos, s"${sym.name}: Only methods can be marked @elidable.")
+ }
+ if (settings.isScala213) checkIsElisible(tree.symbol)
+
tree match {
case m: MemberDef =>
val sym = m.symbol
@@ -1425,7 +1432,7 @@ abstract class RefChecks extends Transform {
analyzer.ImplicitAmbiguousMsg.check(sym) foreach messageWarning("implicitAmbiguous")
case tpt@TypeTree() =>
- if(tpt.original != null) {
+ if (tpt.original != null) {
tpt.original foreach {
case dc@TypeTreeWithDeferredRefCheck() =>
applyRefchecksToAnnotations(dc.check()) // #2416
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.