Skip to content

Commit 62c5b2d

Browse files
committed
Fix #11654: create new symbol for stdlib patches
1 parent 6de2883 commit 62c5b2d

File tree

3 files changed

+63
-5
lines changed

3 files changed

+63
-5
lines changed

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

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,10 +1111,32 @@ class Definitions {
11111111
* is read from a classfile.
11121112
*/
11131113
def patchStdLibClass(denot: ClassDenotation)(using Context): Unit =
1114-
11151114
def patch2(denot: ClassDenotation, patchCls: Symbol): Unit =
11161115
val scope = denot.info.decls.openForMutations
1116+
11171117
def recurse(patch: Symbol) = patch.is(Module) && scope.lookup(patch.name).exists
1118+
1119+
def makeClassSymbol(patch: Symbol, parents: List[Type], selfInfo: TypeOrSymbol) =
1120+
newClassSymbol(
1121+
owner = denot.symbol,
1122+
name = patch.name.asTypeName,
1123+
flags = patch.flags,
1124+
// need to rebuild a fresh ClassInfo
1125+
infoFn = cls => ClassInfo(
1126+
prefix = denot.symbol.thisType,
1127+
cls = cls,
1128+
declaredParents = parents, // assume parents in patch don't refer to symbols in the patch
1129+
decls = newScope,
1130+
selfInfo =
1131+
if patch.is(Module)
1132+
then TermRef(denot.symbol.thisType, patch.name.sourceModuleName)
1133+
else selfInfo // assume patch self type annotation does not refer to symbols in the patch
1134+
),
1135+
privateWithin = patch.privateWithin,
1136+
coord = denot.symbol.coord,
1137+
assocFile = denot.symbol.associatedFile
1138+
)
1139+
11181140
if patchCls.exists then
11191141
val patches = patchCls.info.decls.filter(patch =>
11201142
!patch.isConstructor && !patch.isOneOf(PrivateOrSynthetic))
@@ -1124,9 +1146,30 @@ class Definitions {
11241146
for patch <- patches do
11251147
patch.ensureCompleted()
11261148
if !recurse(patch) then
1127-
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1128-
scope.enter(patch)
1129-
else if patch.isClass then
1149+
val sym =
1150+
patch.info match
1151+
case ClassInfo(_, _, parents, _, selfInfo) =>
1152+
makeClassSymbol(patch, parents, selfInfo)
1153+
case _ =>
1154+
if patch.is(Inline) then
1155+
// Inline symbols contain trees in definitions, which is coupled
1156+
// with the underlying symbol.
1157+
// Changing owner for inline symbols is a simple workaround.
1158+
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1159+
patch
1160+
else
1161+
// change `info` which might contain reference to the patch
1162+
patch.copy(
1163+
owner = denot.symbol,
1164+
info =
1165+
if patch.is(Module)
1166+
then TypeRef(denot.symbol.thisType, patch.name.moduleClassName)
1167+
else patch.info // assume non-object info does not refer to symbols in the patch
1168+
)
1169+
end match
1170+
sym.annotations = patch.annotations
1171+
scope.enter(sym)
1172+
if patch.isClass then
11301173
patch2(scope.lookup(patch.name).asClass, patch)
11311174

11321175
def patchWith(patchCls: Symbol) =

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class BootstrappedOnlyCompilationTests {
150150

151151
@Test def picklingWithCompiler: Unit = {
152152
val jvmBackendFilter = FileFilter.exclude(List("BTypes.scala", "Primitives.scala")) // TODO
153-
val runtimeFilter = FileFilter.exclude(List("Tuple.scala", "stdLibPatches")) // TODO
153+
val runtimeFilter = FileFilter.exclude(List("Tuple.scala")) // TODO
154154
implicit val testGroup: TestGroup = TestGroup("testPicklingWithCompiler")
155155
aggregateTests(
156156
compileDir("compiler/src/dotty/tools", picklingWithCompilerOptions, recursive = false),

library/src/scala/runtime/stdLibPatches/language.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package scala.runtime.stdLibPatches
22

3+
import scala.annotation.compileTimeOnly
4+
35
/** Scala 3 additions and replacements to the `scala.language` object.
46
*/
57
object language:
@@ -29,18 +31,21 @@ object language:
2931
*
3032
* @see [[https://dotty.epfl.ch/docs/reference/other-new-features/named-typeargs]]
3133
*/
34+
@compileTimeOnly("`namedTypeArguments` can only be used at compile time in import statements")
3235
object namedTypeArguments
3336

3437
/** Experimental support for generic number literals.
3538
*
3639
* @see [[https://dotty.epfl.ch/docs/reference/changed-features/numeric-literals]]
3740
*/
41+
@compileTimeOnly("`genericNumberLiterals` can only be used at compile time in import statements")
3842
object genericNumberLiterals
3943

4044
/** Experimental support for `erased` modifier
4145
*
4246
* @see [[https://dotty.epfl.ch/docs/reference/experimental/erased-defs]]
4347
*/
48+
@compileTimeOnly("`erasedDefinitions` can only be used at compile time in import statements")
4449
object erasedDefinitions
4550

4651
end experimental
@@ -49,13 +54,15 @@ object language:
4954
* Features in this object are slated for removal. New code should not use them and
5055
* old code should migrate away from them.
5156
*/
57+
@compileTimeOnly("`deprecated` can only be used at compile time in import statements")
5258
object deprecated:
5359

5460
/** Symbol literals have been deprecated since 2.13. Since Scala 3.0 they
5561
* are no longer an official part of Scala. For compatibility with legacy software,
5662
* symbol literals are still supported with a language import, but new software
5763
* should not use them.
5864
*/
65+
@compileTimeOnly("`symbolLiterals` can only be used at compile time in import statements")
5966
object symbolLiterals
6067
end deprecated
6168

@@ -69,6 +76,7 @@ object language:
6976
* '''Why allow it?''' Not allowing auto-tupling is difficult to reconcile with
7077
* operators accepting tuples.
7178
*/
79+
@compileTimeOnly("`noAutoTupling` can only be used at compile time in import statements")
7280
object noAutoTupling
7381

7482
/** Where imported, loose equality using eqAny is disabled.
@@ -78,6 +86,7 @@ object language:
7886
*
7987
* @see [[https://dotty.epfl.ch/docs/reference/contextual/multiversal-equality]]
8088
*/
89+
@compileTimeOnly("`strictEquality` can only be used at compile time in import statements")
8190
object strictEquality
8291

8392
/** Where imported, ad hoc extensions of non-open classes in other
@@ -96,29 +105,35 @@ object language:
96105
* such extensions should be limited in scope and clearly documented.
97106
* That's why the language import is required for them.
98107
*/
108+
@compileTimeOnly("`adhocExtensions` can only be used at compile time in import statements")
99109
object adhocExtensions
100110

101111
/** Unsafe Nulls fot Explicit Nulls
102112
* Inside the "unsafe" scope, `Null` is considered as a subtype of all reference types.
103113
*
104114
* @see [[http://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html]]
105115
*/
116+
@compileTimeOnly("`unsafeNulls` can only be used at compile time in import statements")
106117
object unsafeNulls
107118

119+
@compileTimeOnly("`future` can only be used at compile time in import statements")
108120
object future
109121

122+
@compileTimeOnly("`future-migration` can only be used at compile time in import statements")
110123
object `future-migration`
111124

112125
/** Set source version to 3.0-migration.
113126
*
114127
* @see [[https://scalacenter.github.io/scala-3-migration-guide/docs/scala-3-migration-mode]]
115128
*/
129+
@compileTimeOnly("`3.0-migration` can only be used at compile time in import statements")
116130
object `3.0-migration`
117131

118132
/** Set source version to 3.0.
119133
*
120134
* @see [[https://scalacenter.github.io/scala-3-migration-guide/docs/scala-3-migration-mode]]
121135
*/
136+
@compileTimeOnly("`3.0` can only be used at compile time in import statements")
122137
object `3.0`
123138

124139
/* This can be added when we go to 3.1

0 commit comments

Comments
 (0)