Skip to content

Commit 56f6933

Browse files
authored
Merge pull request #1655 from dotty-staging/change-future-defs-ok
Fix #1637: Future defs are always OK
2 parents a0dcc08 + 1dea991 commit 56f6933

File tree

12 files changed

+42
-99
lines changed

12 files changed

+42
-99
lines changed

src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -647,21 +647,16 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
647647
def rawowner: Symbol = {
648648
originalOwner
649649
}
650-
def originalOwner: Symbol = {
650+
def originalOwner: Symbol =
651651
// used to populate the EnclosingMethod attribute.
652652
// it is very tricky in presence of classes(and annonymous classes) defined inside supper calls.
653-
try {
654-
if (sym.exists) {
655-
val original = toDenot(sym).initial
656-
val validity = original.validFor
657-
val shiftedContext = ctx.withPhase(validity.phaseId)
658-
val r = toDenot(sym)(shiftedContext).maybeOwner.lexicallyEnclosingClass(shiftedContext)
659-
r
660-
} else NoSymbol
661-
} catch {
662-
case e: NotDefinedHere => NoSymbol // todo: do we have a method to tests this?
663-
}
664-
}
653+
if (sym.exists) {
654+
val original = toDenot(sym).initial
655+
val validity = original.validFor
656+
val shiftedContext = ctx.withPhase(validity.phaseId)
657+
val r = toDenot(sym)(shiftedContext).maybeOwner.lexicallyEnclosingClass(shiftedContext)
658+
r
659+
} else NoSymbol
665660
def parentSymbols: List[Symbol] = toDenot(sym).info.parents.map(_.typeSymbol)
666661
def superClass: Symbol = {
667662
val t = toDenot(sym).asClass.superClass

src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
292292
// ------ Making references ------------------------------------------------------
293293

294294
def prefixIsElidable(tp: NamedType)(implicit ctx: Context) = {
295-
def test(implicit ctx: Context) = tp.prefix match {
295+
val typeIsElidable = tp.prefix match {
296296
case NoPrefix =>
297297
true
298298
case pre: ThisType =>
@@ -306,10 +306,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
306306
case _ =>
307307
false
308308
}
309-
try test || tp.symbol.is(JavaStatic) || tp.symbol.hasAnnotation(defn.ScalaStaticAnnot)
310-
catch { // See remark in SymDenotations#accessWithin
311-
case ex: NotDefinedHere => test(ctx.addMode(Mode.FutureDefsOK))
312-
}
309+
typeIsElidable ||
310+
tp.symbol.is(JavaStatic) ||
311+
tp.symbol.hasAnnotation(defn.ScalaStaticAnnot)
313312
}
314313

315314
def needsSelect(tp: Type)(implicit ctx: Context) = tp match {
@@ -602,7 +601,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
602601
loop(from.owner, from :: froms, to :: tos)
603602
else {
604603
//println(i"change owner ${from :: froms}%, % ==> $tos of $tree")
605-
new TreeTypeMap(oldOwners = from :: froms, newOwners = tos)(ctx.addMode(Mode.FutureDefsOK)).apply(tree)
604+
new TreeTypeMap(oldOwners = from :: froms, newOwners = tos).apply(tree)
606605
}
607606
}
608607
loop(from, Nil, to :: Nil)
@@ -628,7 +627,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
628627
traverseChildren(tree)
629628
}
630629
}
631-
traverser.traverse(tree)(ctx.addMode(Mode.FutureDefsOK))
630+
traverser.traverse(tree)
632631
tree
633632
}
634633

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -633,14 +633,10 @@ class Definitions {
633633
name.startsWith(prefix) && name.drop(prefix.length).forall(_.isDigit)
634634
}
635635

636-
def isBottomClass(cls: Symbol) = cls == NothingClass || cls == NullClass
637-
def isBottomType(tp: Type) = {
638-
def test(implicit ctx: Context) = tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass)
639-
try test
640-
catch { // See remark in SymDenotations#accessWithin
641-
case ex: NotDefinedHere => test(ctx.addMode(Mode.FutureDefsOK))
642-
}
643-
}
636+
def isBottomClass(cls: Symbol) =
637+
cls == NothingClass || cls == NullClass
638+
def isBottomType(tp: Type) =
639+
tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass)
644640

645641
def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function)
646642
def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.AbstractFunction)

src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package core
44

5-
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation, NotDefinedHereDenotation }
5+
import SymDenotations.{ SymDenotation, ClassDenotation, NoDenotation }
66
import Contexts.{Context, ContextBase}
77
import Names.{Name, PreName}
88
import Names.TypeName
@@ -131,16 +131,9 @@ object Denotations {
131131
*/
132132
def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): Denotation
133133

134-
/** The variant of this denotation that's current in the given context, or
135-
* `NotDefinedHereDenotation` if this denotation does not exist at current phase, but
136-
* is defined elsewhere in this run.
137-
*/
138-
def currentIfExists(implicit ctx: Context): Denotation
139-
140134
/** The variant of this denotation that's current in the given context.
141-
* If no such denotation exists: If Mode.FutureDefs is set, the
142-
* denotation with each alternative at its first point of definition,
143-
* otherwise a `NotDefinedHere` exception is thrown.
135+
* If no such denotation exists, returns the denotation with each alternative
136+
* at its first point of definition.
144137
*/
145138
def current(implicit ctx: Context): Denotation
146139

@@ -569,8 +562,6 @@ object Denotations {
569562
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
570563
def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation =
571564
derivedMultiDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
572-
def currentIfExists(implicit ctx: Context): Denotation =
573-
derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists)
574565
def current(implicit ctx: Context): Denotation =
575566
derivedMultiDenotation(denot1.current, denot2.current)
576567
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
@@ -765,7 +756,7 @@ object Denotations {
765756
* is brought forward to be valid in the new runId. Otherwise
766757
* the symbol is stale, which constitutes an internal error.
767758
*/
768-
def currentIfExists(implicit ctx: Context): SingleDenotation = {
759+
def current(implicit ctx: Context): SingleDenotation = {
769760
val currentPeriod = ctx.period
770761
val valid = myValidFor
771762
if (valid.code <= 0) {
@@ -839,24 +830,14 @@ object Denotations {
839830
// performance: Test setup: Compile everything in dotc and immediate subdirectories
840831
// 10 times. Best out of 10: 18154ms with `prev` field, 17777ms without.
841832
cnt += 1
842-
if (cnt > MaxPossiblePhaseId) return NotDefinedHereDenotation
833+
if (cnt > MaxPossiblePhaseId)
834+
return current(ctx.withPhase(coveredInterval.firstPhaseId))
843835
}
844836
cur
845837
}
846838
}
847839
}
848840

849-
def current(implicit ctx: Context): SingleDenotation = {
850-
val d = currentIfExists
851-
if (d ne NotDefinedHereDenotation) d else currentNoDefinedHere
852-
}
853-
854-
private def currentNoDefinedHere(implicit ctx: Context): SingleDenotation =
855-
if (ctx.mode is Mode.FutureDefsOK)
856-
current(ctx.withPhase(coveredInterval.firstPhaseId))
857-
else
858-
throw new NotDefinedHere(demandOutsideDefinedMsg)
859-
860841
private def demandOutsideDefinedMsg(implicit ctx: Context): String =
861842
s"demanding denotation of $this at phase ${ctx.phase}(${ctx.phaseId}) outside defined interval: defined periods are${definedPeriodsString}"
862843

@@ -1233,9 +1214,4 @@ object Denotations {
12331214
util.Stats.record("stale symbol")
12341215
override def getMessage() = msg
12351216
}
1236-
1237-
class NotDefinedHere(msg: => String) extends Exception {
1238-
util.Stats.record("not defined here")
1239-
override def getMessage() = msg
1240-
}
12411217
}

src/dotty/tools/dotc/core/Mode.scala

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,6 @@ object Mode {
4141

4242
val InSuperCall = newMode(6, "InSuperCall")
4343

44-
/** This mode bit is set if we want to allow accessing a symbol's denotation
45-
* at a period before that symbol is first valid. An example where this is
46-
* the case is if we want to examine the environment where an access is made.
47-
* The computation might take place at an earlier phase (e.g. it is part of
48-
* some completion such as unpickling), but the environment might contain
49-
* synbols that are not yet defined in that phase.
50-
* If the mode bit is set, getting the denotation of a symbol at a phase
51-
* before the symbol is defined will return the symbol's denotation at the
52-
* first phase where it is valid, instead of throwing a NotDefinedHere error.
53-
*/
54-
val FutureDefsOK = newMode(7, "FutureDefsOK")
55-
5644
/** Allow GADTFlexType labelled types to have their bounds adjusted */
5745
val GADTflexible = newMode(8, "GADTflexible")
5846

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -645,21 +645,10 @@ object SymDenotations {
645645
final def isAccessibleFrom(pre: Type, superAccess: Boolean = false, whyNot: StringBuffer = null)(implicit ctx: Context): Boolean = {
646646

647647
/** Are we inside definition of `boundary`? */
648-
def accessWithin(boundary: Symbol) = {
649-
def test(implicit ctx: Context) =
650-
ctx.owner.isContainedIn(boundary) &&
651-
(!(this is JavaDefined) || // disregard package nesting for Java
652-
ctx.owner.enclosingPackageClass == boundary.enclosingPackageClass)
653-
try test
654-
catch {
655-
// It might be we are in a definition whose symbol is not defined at the
656-
// period where the test is made. Retry with FutureDefsOK. The reason
657-
// for not doing this outright is speed. We would like to avoid
658-
// creating a new context object each time we call accessWithin.
659-
// Note that the exception should be thrown only infrequently.
660-
case ex: NotDefinedHere => test(ctx.addMode(Mode.FutureDefsOK))
661-
}
662-
}
648+
def accessWithin(boundary: Symbol) =
649+
ctx.owner.isContainedIn(boundary) &&
650+
(!(this is JavaDefined) || // disregard package nesting for Java
651+
ctx.owner.enclosingPackageClass == boundary.enclosingPackageClass)
663652

664653
/** Are we within definition of linked class of `boundary`? */
665654
def accessWithinLinked(boundary: Symbol) = {
@@ -1872,7 +1861,6 @@ object SymDenotations {
18721861
}
18731862

18741863
@sharable val NoDenotation = new NoDenotation
1875-
@sharable val NotDefinedHereDenotation = new NoDenotation
18761864

18771865
// ---- Completion --------------------------------------------------------
18781866

src/dotty/tools/dotc/core/TypeErasure.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ object TypeErasure {
107107

108108
/** The current context with a phase no later than erasure */
109109
private def erasureCtx(implicit ctx: Context) =
110-
if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase).addMode(Mode.FutureDefsOK) else ctx
110+
if (ctx.erasedTypes) ctx.withPhase(ctx.erasurePhase) else ctx
111111

112112
/** The standard erasure of a Scala type. Value classes are erased as normal classes.
113113
*

src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,10 +1441,7 @@ object Types {
14411441
}
14421442
case d =>
14431443
if (d.validFor.runId != ctx.period.runId) loadDenot
1444-
else {
1445-
val newd = d.currentIfExists
1446-
if (newd ne NotDefinedHereDenotation) newd else loadDenot
1447-
}
1444+
else d.current
14481445
}
14491446
if (ctx.typerState.ephemeral) record("ephemeral cache miss: loadDenot")
14501447
else if (d.exists) {

src/dotty/tools/dotc/printing/Formatting.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object Formatting {
2929

3030
protected def showArg(arg: Any)(implicit ctx: Context): String = arg match {
3131
case arg: Showable =>
32-
try arg.show(ctx.addMode(Mode.FutureDefsOK))
32+
try arg.show
3333
catch {
3434
case NonFatal(ex) => s"[cannot display due to $ex, raw string = $toString]"
3535
}

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,9 +604,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
604604
// all potentially stored subpat binders
605605
val potentiallyStoredBinders = stored.unzip._1.toSet
606606
// compute intersection of all symbols in the tree `in` and all potentially stored subpat binders
607-
def computeBinders(implicit ctx: Context) = new DeepFolder[Unit]((x: Unit, t:Tree) =>
607+
new DeepFolder[Unit]((x: Unit, t: Tree) =>
608608
if (potentiallyStoredBinders(t.symbol)) usedBinders += t.symbol).apply((), in)
609-
computeBinders(ctx.addMode(Mode.FutureDefsOK)) // trigged a NotDefinedHere on $outer when compiler dotc/printing
610609

611610
if (usedBinders.isEmpty) in
612611
else {

src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,8 @@ class TreeChecker extends Phase with SymTransformer {
6969

7070
def checkCompanion(symd: SymDenotation)(implicit ctx: Context): Unit = {
7171
val cur = symd.linkedClass
72-
val prev = ctx.atPhase(ctx.phase.prev) {
73-
ct => {
74-
implicit val ctx: Context = ct.addMode(Mode.FutureDefsOK)
75-
symd.symbol.linkedClass
76-
}
72+
val prev = ctx.atPhase(ctx.phase.prev) { implicit ctx =>
73+
symd.symbol.linkedClass
7774
}
7875

7976
if (prev.exists)

tests/pos/i1637.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Main extends App {
2+
case class Foo(field: Option[String])
3+
val x: PartialFunction[Foo, Int] = { c =>
4+
c.field match {
5+
case Some(s) => 42
6+
}
7+
}
8+
}

0 commit comments

Comments
 (0)