diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 60a7555456bf..5787a284d6d4 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -1074,7 +1074,7 @@ object Denotations { def filterDisjoint(denots: PreDenotation)(using Context): SingleDenotation = if (denots.exists && denots.matches(this)) NoDenotation else this def filterWithFlags(required: FlagSet, excluded: FlagSet)(using Context): SingleDenotation = - val realExcluded = if ctx.isAfterTyper then excluded else excluded | Invisible + val realExcluded = if ctx.isAfterTyper then excluded else excluded | Invisible | (if ctx.mode.is(Mode.ResolveFromTASTy) then EmptyFlags else SourceInvisible) def symd: SymDenotation = this match case symd: SymDenotation => symd case _ => symbol.denot diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index b915373da021..9939032df916 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -380,6 +380,9 @@ object Flags { /** Tracked modifier for class parameter / a class with some tracked parameters */ val (Tracked @ _, _, Dependent @ _) = newFlags(46, "tracked") + /** Symbol can not be resolved from source during typer. PROVISIONAL (possibly replace with `Invisible` with new semantics) */ + val (SourceInvisible @ _, _, _) = newFlags(47, "") + // ------------ Flags following this one are not pickled ---------------------------------- /** Symbol is not a member of its owner */ @@ -471,7 +474,7 @@ object Flags { Scala2SpecialFlags, MutableOrOpen, Opaque, Touched, JavaStatic, OuterOrCovariant, LabelOrContravariant, CaseAccessor, Tracked, Extension, NonMember, Implicit, Given, Permanent, Synthetic, Exported, - SuperParamAliasOrScala2x, Inline, Macro, ConstructorProxy, Invisible) + SuperParamAliasOrScala2x, Inline, Macro, ConstructorProxy, Invisible, SourceInvisible) /** Flags that are not (re)set when completing the denotation, or, if symbol is * a top-level class or object, when completing the denotation once the class @@ -525,7 +528,7 @@ object Flags { val RetainedModuleValAndClassFlags: FlagSet = AccessFlags | Package | Case | Synthetic | JavaDefined | JavaStatic | Artifact | - Lifted | MixedIn | Specialized | ConstructorProxy | Invisible | Erased + Lifted | MixedIn | Specialized | ConstructorProxy | Invisible | SourceInvisible | Erased /** Flags that can apply to a module val */ val RetainedModuleValFlags: FlagSet = RetainedModuleValAndClassFlags | diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index 14d7827974c0..965c3823d610 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -105,7 +105,7 @@ object Mode { /** Use previous Scheme for implicit resolution. Currently significant * in 3.0-migration where we use Scala-2's scheme instead and in 3.5 and 3.6-migration - * where we use the previous scheme up to 3.4 for comparison with the new scheme. + * where we use the previous scheme up to 3.4 for comparison with the new scheme. */ val OldImplicitResolution: Mode = newMode(15, "OldImplicitResolution") @@ -125,6 +125,9 @@ object Mode { /** Read original positions when unpickling from TASTY */ val ReadPositions: Mode = newMode(17, "ReadPositions") + /** We are resolving a SELECT name from TASTy */ + val ResolveFromTASTy: Mode = newMode(18, "ResolveFromTASTy") + /** We are elaborating the fully qualified name of a package clause. * In this case, identifiers should never be imported. */ diff --git a/compiler/src/dotty/tools/dotc/core/NamerOps.scala b/compiler/src/dotty/tools/dotc/core/NamerOps.scala index 363a01665564..c1962d9fc557 100644 --- a/compiler/src/dotty/tools/dotc/core/NamerOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NamerOps.scala @@ -110,7 +110,7 @@ object NamerOps: else NoSymbol.assertingErrorsReported(em"no companion $name in $scope") /** If a class has one of these flags, it does not get a constructor companion */ - private val NoConstructorProxyNeededFlags = Abstract | Trait | Case | Synthetic | Module | Invisible + private val NoConstructorProxyNeededFlags = Abstract | Trait | Case | Synthetic | Module | Invisible | SourceInvisible /** The flags of a constructor companion */ private val ConstructorCompanionFlags = Synthetic | ConstructorProxy diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 906e74735097..4fbfd292f7c6 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -617,7 +617,7 @@ object SymDenotations { case _ => // Otherwise, no completion is necessary, see the preconditions of `markAbsent()`. (myInfo `eq` NoType) - || is(Invisible) && ctx.isTyper + || (is(Invisible) || is(SourceInvisible) && !ctx.mode.is(Mode.ResolveFromTASTy)) && ctx.isTyper || is(ModuleVal, butNot = Package) && moduleClass.isAbsent(canForce) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 326471d8071c..f06da2dca71b 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -881,6 +881,7 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) { if flags.is(Transparent) then writeModTag(TRANSPARENT) if flags.is(Infix) then writeModTag(INFIX) if flags.is(Invisible) then writeModTag(INVISIBLE) + if flags.is(SourceInvisible) then writeModTag(SOURCEINVISIBLE) if (flags.is(Erased)) writeModTag(ERASED) if (flags.is(Exported)) writeModTag(EXPORTED) if (flags.is(Given)) writeModTag(GIVEN) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index e62db9af520a..c6a334a33473 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -754,6 +754,7 @@ class TreeUnpickler(reader: TastyReader, case EXPORTED => addFlag(Exported) case OPEN => addFlag(Open) case INVISIBLE => addFlag(Invisible) + case SOURCEINVISIBLE => addFlag(SourceInvisible) case TRANSPARENT => addFlag(Transparent) case INFIX => addFlag(Infix) case TRACKED => addFlag(Tracked) @@ -1561,7 +1562,7 @@ class TreeUnpickler(reader: TastyReader, * - sbt-test/tasty-compat/remove-override * - sbt-test/tasty-compat/move-method */ - def lookupInSuper = + def lookupInSuper(using Context) = val cls = ownerTpe.classSymbol if cls.exists then cls.asClass.classDenot @@ -1570,7 +1571,8 @@ class TreeUnpickler(reader: TastyReader, else NoDenotation - val denot = + + def searchDenot(using Context): Denotation = if owner.is(JavaAnnotation) && name == nme.CONSTRUCTOR then // #19951 Fix up to read TASTy produced before 3.5.0 -- ignore the signature ownerTpe.nonPrivateDecl(name).asSeenFrom(prefix) @@ -1578,6 +1580,20 @@ class TreeUnpickler(reader: TastyReader, val d = ownerTpe.decl(name).atSignature(sig, target) (if !d.exists then lookupInSuper else d).asSeenFrom(prefix) + val denot0 = inContext(ctx.addMode(Mode.ResolveFromTASTy)): + searchDenot // able to resolve SourceInvisible members + + val denot = + if + denot0.symbol.exists + && denot0.symbol.is(SourceInvisible) + && denot0.symbol.isDefinedInSource + then + searchDenot // fallback + else + denot0 + + makeSelect(qual, name, denot) case REPEATED => val elemtpt = readTpt() diff --git a/compiler/src/dotty/tools/dotc/transform/UnrollDefinitions.scala b/compiler/src/dotty/tools/dotc/transform/UnrollDefinitions.scala index 9cbaf7738533..e36a5e875787 100644 --- a/compiler/src/dotty/tools/dotc/transform/UnrollDefinitions.scala +++ b/compiler/src/dotty/tools/dotc/transform/UnrollDefinitions.scala @@ -26,7 +26,7 @@ import dotty.tools.unreachable /**Implementation of SIP-61. * Runs when `@unroll` annotations are found in a compilation unit, installing new definitions * - * Note that it only generates `Invisible` methods, so no interactions with Zinc/SemanticDB + * Note that it only generates `SourceInvisible` methods, so no interactions with Zinc/SemanticDB */ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer { self => @@ -127,7 +127,7 @@ class UnrollDefinitions extends MacroTransform, IdentityDenotTransformer { defdef.symbol.owner, defdef.name, defdef.symbol.flags &~ HasDefaultParams | - Invisible | Synthetic, + SourceInvisible | Synthetic, NoType, // fill in later coord = nextSymbol.span.shift(1) // shift by 1 to avoid "secondary constructor must call preceding" error ).entered diff --git a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala index ce8d19aae46a..3029ae0cc43a 100644 --- a/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala +++ b/compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala @@ -2955,6 +2955,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler def Infix: Flags = dotc.core.Flags.Infix def Inline: Flags = dotc.core.Flags.Inline def Invisible: Flags = dotc.core.Flags.Invisible + def SourceInvisible: Flags = dotc.core.Flags.SourceInvisible def JavaDefined: Flags = dotc.core.Flags.JavaDefined def JavaStatic: Flags = dotc.core.Flags.JavaStatic def JavaAnnotation: Flags = dotc.core.Flags.JavaAnnotation diff --git a/library/src/scala/quoted/Quotes.scala b/library/src/scala/quoted/Quotes.scala index fad769793bb7..21879f45ba7f 100644 --- a/library/src/scala/quoted/Quotes.scala +++ b/library/src/scala/quoted/Quotes.scala @@ -4588,6 +4588,10 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching => /** Is this symbol invisible when typechecking? */ def Invisible: Flags + /** Is this symbol invisible when typechecking? (only from source) */ + @experimental + def SourceInvisible: Flags + /** Is this symbol defined in a Java class */ def JavaDefined: Flags diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index 8f5f9d57a8a5..02291e27aca4 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -228,6 +228,7 @@ Standard-Section: "ASTs" TopLevelStat* EXPORTED -- An export forwarder OPEN -- an open class INVISIBLE -- invisible during typechecking + SOURCEINVISIBLE -- invisible in the source code TRACKED -- a tracked class parameter / a dependent class Annotation @@ -511,6 +512,7 @@ object TastyFormat { final val EMPTYCLAUSE = 45 final val SPLITCLAUSE = 46 final val TRACKED = 47 + final val SOURCEINVISIBLE = 48 // Tree Cat. 2: tag Nat final val firstNatTreeTag = SHAREDterm @@ -700,6 +702,7 @@ object TastyFormat { | EXPORTED | OPEN | INVISIBLE + | SOURCEINVISIBLE | ANNOTATION | PRIVATEqualified | PROTECTEDqualified @@ -764,6 +767,7 @@ object TastyFormat { case EXPORTED => "EXPORTED" case OPEN => "OPEN" case INVISIBLE => "INVISIBLE" + case SOURCEINVISIBLE => "SOURCEINVISIBLE" case PARAMalias => "PARAMalias" case EMPTYCLAUSE => "EMPTYCLAUSE" case SPLITCLAUSE => "SPLITCLAUSE"