Skip to content

Commit e4ba457

Browse files
authored
Merge pull request scala#6631 from retronym/topic/lightweight-context-3
Reducing the footprint of Context
2 parents 8dfed29 + 23cc067 commit e4ba457

File tree

3 files changed

+23
-37
lines changed

3 files changed

+23
-37
lines changed

src/compiler/scala/tools/nsc/typechecker/Contexts.scala

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,6 @@ trait Contexts { self: Analyzer =>
222222
*/
223223
var enclMethod: Context = _
224224

225-
/** Variance relative to enclosing class */
226-
var variance: Variance = Variance.Invariant
227-
228225
private var _undetparams: List[Symbol] = List()
229226

230227
protected def outerDepth = if (outerIsNoContext) 0 else outer.depth
@@ -247,8 +244,6 @@ trait Contexts { self: Analyzer =>
247244
openImplicits.nonEmpty && openImplicits.exists(x => !x.isView)
248245
}
249246

250-
/* For a named application block (`Tree`) the corresponding `NamedApplyInfo`. */
251-
var namedApplyBlockInfo: Option[(Tree, NamedApplyInfo)] = None
252247
var prefix: Type = NoPrefix
253248

254249
def inSuperInit_=(value: Boolean) = this(SuperInit) = value
@@ -278,10 +273,6 @@ trait Contexts { self: Analyzer =>
278273

279274
def defaultModeForTyped: Mode = if (inTypeConstructorAllowed) Mode.NOmode else Mode.EXPRmode
280275

281-
/** To enrich error messages involving default arguments.
282-
When extending the notion, group diagnostics in an object. */
283-
var diagUsedDefaults: Boolean = false
284-
285276
/** Saved type bounds for type parameters which are narrowed in a GADT. */
286277
var savedTypeBounds: List[(Symbol, Type)] = List()
287278

@@ -489,8 +480,6 @@ trait Contexts { self: Analyzer =>
489480
new Context(tree, owner, scope, unit, this, reporter)
490481

491482
// Fields that are directly propagated
492-
c.variance = variance
493-
c.diagUsedDefaults = diagUsedDefaults
494483
c.openImplicits = openImplicits
495484
c.contextMode = contextMode // note: ConstructorSuffix, a bit within `mode`, is conditionally overwritten below.
496485

@@ -1382,7 +1371,7 @@ trait Contexts { self: Analyzer =>
13821371

13831372
protected def addDiagString(msg: String)(implicit context: Context): String = {
13841373
val diagUsedDefaultsMsg = "Error occurred in an application involving default arguments."
1385-
if (context.diagUsedDefaults && !(msg endsWith diagUsedDefaultsMsg)) msg + "\n" + diagUsedDefaultsMsg
1374+
if (context.contextMode.inAny(ContextMode.DiagUsedDefaults) && !(msg endsWith diagUsedDefaultsMsg)) msg + "\n" + diagUsedDefaultsMsg
13861375
else msg
13871376
}
13881377

@@ -1621,6 +1610,9 @@ object ContextMode {
16211610
/** Should a dead code warning be issued for a Nothing-typed argument to the current application. */
16221611
final val SuppressDeadArgWarning: ContextMode = 1 << 17
16231612

1613+
/** Were default arguments used? */
1614+
final val DiagUsedDefaults: ContextMode = 1 << 18
1615+
16241616
/** TODO: The "sticky modes" are EXPRmode, PATTERNmode, TYPEmode.
16251617
* To mimic the sticky mode behavior, when captain stickyfingers
16261618
* comes around we need to propagate those modes but forget the other
@@ -1645,6 +1637,7 @@ object ContextMode {
16451637
SuperInit -> "SuperInit",
16461638
SecondTry -> "SecondTry",
16471639
TypeConstructorAllowed -> "TypeConstructorAllowed",
1640+
DiagUsedDefaults -> "DiagUsedDefaults",
16481641
SuppressDeadArgWarning -> "SuppressDeadArgWarning"
16491642
)
16501643
}

src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ trait NamesDefaults { self: Analyzer =>
5151
vargss: List[List[Tree]],
5252
blockTyper: Typer
5353
) { }
54+
object NamedApplyBlock {
55+
private[this] val tag = reflect.classTag[NamedApplyInfo]
56+
def unapply(b: Tree): Option[NamedApplyInfo] = b match {
57+
case _: Block => b.attachments.get[NamedApplyInfo](tag)
58+
case _ => None
59+
}
60+
}
5461

5562
private def nameOfNamedArg(arg: Tree) = Some(arg) collect { case NamedArg(Ident(name), _) => name }
5663
def isNamedArg(arg: Tree) = arg match {
@@ -193,15 +200,13 @@ trait NamesDefaults { self: Analyzer =>
193200

194201
val b = Block(List(vd), baseFunTransformed)
195202
.setType(baseFunTransformed.tpe).setPos(baseFun.pos.makeTransparent)
196-
context.namedApplyBlockInfo =
197-
Some((b, NamedApplyInfo(Some(newQual), defaultTargs, Nil, blockTyper)))
203+
b.updateAttachment(NamedApplyInfo(Some(newQual), defaultTargs, Nil, blockTyper))
198204
b
199205
}
200206

201207
def blockWithoutQualifier(defaultQual: Option[Tree]) = {
202208
val b = atPos(baseFun.pos)(Block(Nil, baseFun).setType(baseFun.tpe))
203-
context.namedApplyBlockInfo =
204-
Some((b, NamedApplyInfo(defaultQual, defaultTargs, Nil, blockTyper)))
209+
b.updateAttachment(NamedApplyInfo(defaultQual, defaultTargs, Nil, blockTyper))
205210
b
206211
}
207212

@@ -328,17 +333,14 @@ trait NamesDefaults { self: Analyzer =>
328333
}
329334

330335
// begin transform
331-
if (isNamedApplyBlock(tree)) {
332-
context.namedApplyBlockInfo.get._1
333-
} else tree match {
336+
tree match {
337+
case NamedApplyBlock(info) => tree
334338
// `fun` is typed. `namelessArgs` might be typed or not, if they are types are kept.
335339
case Apply(fun, namelessArgs) =>
336340
val transformedFun = transformNamedApplication(typer, mode, pt)(fun, x => x)
337341
if (transformedFun.isErroneous) setError(tree)
338342
else {
339-
assert(isNamedApplyBlock(transformedFun), transformedFun)
340-
val NamedApplyInfo(qual, targs, vargss, blockTyper) =
341-
context.namedApplyBlockInfo.get._2
343+
val NamedApplyBlock(NamedApplyInfo(qual, targs, vargss, blockTyper)) = transformedFun
342344
val Block(stats, funOnly) = transformedFun
343345

344346
// type the application without names; put the arguments in definition-site order
@@ -374,8 +376,7 @@ trait NamesDefaults { self: Analyzer =>
374376
val res = blockTyper.doTypedApply(tree, expr, refArgs, mode, pt)
375377
res.setPos(res.pos.makeTransparent)
376378
val block = Block(stats ::: valDefs.flatten, res).setType(res.tpe).setPos(tree.pos.makeTransparent)
377-
context.namedApplyBlockInfo =
378-
Some((block, NamedApplyInfo(qual, targs, vargss :+ refArgs, blockTyper)))
379+
block.updateAttachment(NamedApplyInfo(qual, targs, vargss :+ refArgs, blockTyper))
379380
block
380381
case _ => tree
381382
}

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -690,12 +690,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
690690
val context1 = context.makeSilent(reportAmbiguousErrors, newtree)
691691
context1.undetparams = context.undetparams
692692
context1.savedTypeBounds = context.savedTypeBounds
693-
context1.namedApplyBlockInfo = context.namedApplyBlockInfo
694693
val typer1 = newTyper(context1)
695694
val result = op(typer1)
696695
context.undetparams = context1.undetparams
697696
context.savedTypeBounds = context1.savedTypeBounds
698-
context.namedApplyBlockInfo = context1.namedApplyBlockInfo
699697

700698
// If we have a successful result, emit any warnings it created.
701699
if (!context1.reporter.hasErrors)
@@ -3298,11 +3296,6 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
32983296
}
32993297
}
33003298

3301-
/** Is `tree` a block created by a named application?
3302-
*/
3303-
def isNamedApplyBlock(tree: Tree) =
3304-
context.namedApplyBlockInfo exists (_._1 == tree)
3305-
33063299
def callToCompanionConstr(context: Context, calledFun: Symbol) = {
33073300
calledFun.isConstructor && {
33083301
val methCtx = context.enclMethod
@@ -3534,7 +3527,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
35343527
} else if (!allArgsArePositional(argPos) && !sameLength(formals, params))
35353528
// !allArgsArePositional indicates that named arguments are used to re-order arguments
35363529
duplErrorTree(MultipleVarargError(tree))
3537-
else if (allArgsArePositional(argPos) && !isNamedApplyBlock(fun)) {
3530+
else if (allArgsArePositional(argPos) && !NamedApplyBlock.unapply(fun).isDefined) {
35383531
// if there's no re-ordering, and fun is not transformed, no need to transform
35393532
// more than an optimization, e.g. important in "synchronized { x = update-x }"
35403533
checkNotMacro()
@@ -3573,13 +3566,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
35733566
val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
35743567
if (fun1.isErroneous) duplErrTree
35753568
else {
3576-
assert(isNamedApplyBlock(fun1), fun1)
3577-
val NamedApplyInfo(qual, targs, previousArgss, _) = context.namedApplyBlockInfo.get._2
3569+
val NamedApplyBlock(NamedApplyInfo(qual, targs, previousArgss, _)) = fun1
35783570
val blockIsEmpty = fun1 match {
35793571
case Block(Nil, _) =>
35803572
// if the block does not have any ValDef we can remove it. Note that the call to
35813573
// "transformNamedApplication" is always needed in order to obtain targs/previousArgss
3582-
context.namedApplyBlockInfo = None
3574+
fun1.attachments.remove[NamedApplyInfo]
35833575
true
35843576
case _ => false
35853577
}
@@ -3595,7 +3587,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
35953587
} else if (lencmp2 == 0) {
35963588
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
35973589
checkNotMacro()
3598-
context.diagUsedDefaults = true
3590+
context.set(ContextMode.DiagUsedDefaults)
35993591
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
36003592
} else {
36013593
rollbackNamesDefaultsOwnerChanges()
@@ -3607,7 +3599,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
36073599

36083600
if (!sameLength(formals, args) || // wrong nb of arguments
36093601
(args exists isNamedArg) || // uses a named argument
3610-
isNamedApplyBlock(fun)) { // fun was transformed to a named apply block =>
3602+
NamedApplyBlock.unapply(fun).isDefined) { // fun was transformed to a named apply block =>
36113603
// integrate this application into the block
36123604
if (isApplyDynamicNamed(fun) && isDynamicRewrite(fun)) typedNamedApply(tree, fun, args, mode, pt)
36133605
else tryNamesDefaults

0 commit comments

Comments
 (0)