@@ -353,7 +353,21 @@ object SymDenotations {
353
353
/** The completer of this denotation. @pre: Denotation is not yet completed */
354
354
final def completer : LazyType = myInfo.asInstanceOf [LazyType ]
355
355
356
- /** Make sure this denotation is completed */
356
+ /** If this denotation is not completed, run the completer.
357
+ * The resulting info might be another completer.
358
+ *
359
+ * @see ensureCompleted
360
+ */
361
+ final def completeOnce ()(implicit ctx : Context ): Unit = myInfo match {
362
+ case myInfo : LazyType =>
363
+ completeFrom(myInfo)
364
+ case _ =>
365
+ }
366
+
367
+ /** Make sure this denotation is fully completed.
368
+ *
369
+ * @see completeOnce
370
+ */
357
371
final def ensureCompleted ()(implicit ctx : Context ): Unit = info
358
372
359
373
/** The symbols defined in this class or object.
@@ -370,7 +384,7 @@ object SymDenotations {
370
384
case cinfo : LazyType =>
371
385
val knownDecls = cinfo.decls
372
386
if (knownDecls ne EmptyScope ) knownDecls
373
- else { completeFrom(cinfo ); unforcedDecls } // complete-once
387
+ else { completeOnce( ); unforcedDecls }
374
388
case _ => info.decls
375
389
}
376
390
@@ -505,20 +519,33 @@ object SymDenotations {
505
519
/** is this symbol the result of an erroneous definition? */
506
520
def isError : Boolean = false
507
521
508
- /** Make denotation not exist */
509
- final def markAbsent (): Unit =
522
+ /** Make denotation not exist.
523
+ * @pre `isCompleting` is false, or this is a ModuleCompleter or SymbolLoader
524
+ */
525
+ final def markAbsent ()(implicit ctx : Context ): Unit = {
526
+ if (isCompleting)
527
+ assert(myInfo.isInstanceOf [ModuleCompleter | SymbolLoader ],
528
+ s " Illegal call to `markAbsent()` while completing $this using completer $myInfo" )
510
529
myInfo = NoType
530
+ }
511
531
512
- /** Is symbol known to not exist, or potentially not completed yet? */
513
- final def unforcedIsAbsent (implicit ctx : Context ): Boolean =
514
- myInfo == NoType ||
515
- (this .is(ModuleVal , butNot = Package )) && moduleClass.unforcedIsAbsent
516
-
517
- /** Is symbol known to not exist? */
518
- final def isAbsent (implicit ctx : Context ): Boolean = {
519
- ensureCompleted()
520
- (myInfo `eq` NoType ) ||
521
- (this .is(ModuleVal , butNot = Package )) && moduleClass.isAbsent
532
+ /** Is symbol known to not exist?
533
+ * @param canForce If this is true, the info may be forced to avoid a false-negative result
534
+ */
535
+ @ tailrec
536
+ final def isAbsent (canForce : Boolean = true )(implicit ctx : Context ): Boolean = myInfo match {
537
+ case myInfo : ModuleCompleter =>
538
+ // Instead of completing the ModuleCompleter, we can check whether
539
+ // the module class is absent, which might require less completions.
540
+ myInfo.moduleClass.isAbsent(canForce)
541
+ case _ : SymbolLoader if canForce =>
542
+ // Completing a SymbolLoader might call `markAbsent()`
543
+ completeOnce()
544
+ isAbsent(canForce)
545
+ case _ =>
546
+ // Otherwise, no completion is necessary, see the preconditions of `markAbsent()`.
547
+ (myInfo `eq` NoType ) ||
548
+ is(ModuleVal , butNot = Package ) && moduleClass.isAbsent(canForce)
522
549
}
523
550
524
551
/** Is this symbol the root class or its companion object? */
@@ -639,7 +666,7 @@ object SymDenotations {
639
666
final def isCoDefinedWith (other : Symbol )(implicit ctx : Context ): Boolean =
640
667
(this .effectiveOwner == other.effectiveOwner) &&
641
668
( ! this .effectiveOwner.is(PackageClass )
642
- || this .unforcedIsAbsent || other.unforcedIsAbsent
669
+ || this .isAbsent(canForce = false ) || other.isAbsent(canForce = false )
643
670
|| { // check if they are defined in the same file(or a jar)
644
671
val thisFile = this .symbol.associatedFile
645
672
val thatFile = other.associatedFile
@@ -792,7 +819,7 @@ object SymDenotations {
792
819
}
793
820
794
821
if (pre eq NoPrefix ) true
795
- else if (isAbsent) false
822
+ else if (isAbsent() ) false
796
823
else {
797
824
val boundary = accessBoundary(owner)
798
825
@@ -1611,7 +1638,7 @@ object SymDenotations {
1611
1638
}
1612
1639
1613
1640
final override def derivesFrom (base : Symbol )(implicit ctx : Context ): Boolean =
1614
- ! isAbsent &&
1641
+ ! isAbsent() &&
1615
1642
base.isClass &&
1616
1643
( (symbol eq base)
1617
1644
|| (baseClassSet contains base)
@@ -1990,7 +2017,7 @@ object SymDenotations {
1990
2017
1991
2018
/** Register companion class */
1992
2019
override def registerCompanion (companion : Symbol )(implicit ctx : Context ) =
1993
- if (companion.isClass && ! unforcedIsAbsent && ! companion.unforcedIsAbsent )
2020
+ if (companion.isClass && ! isAbsent(canForce = false ) && ! companion.isAbsent(canForce = false ) )
1994
2021
myCompanion = companion
1995
2022
1996
2023
override def registeredCompanion (implicit ctx : Context ) = { ensureCompleted(); myCompanion }
@@ -2072,7 +2099,7 @@ object SymDenotations {
2072
2099
}
2073
2100
case nil =>
2074
2101
val directMembers = super .computeNPMembersNamed(name)
2075
- if (acc.exists) acc.union(directMembers.filterWithPredicate(! _.symbol.isAbsent))
2102
+ if (acc.exists) acc.union(directMembers.filterWithPredicate(! _.symbol.isAbsent() ))
2076
2103
else directMembers
2077
2104
}
2078
2105
if (symbol `eq` defn.ScalaPackageClass ) {
0 commit comments