Skip to content

Commit 3d5b4c8

Browse files
authored
Merge pull request #11803 from dotty-staging/fix-11654
Fix #11654: create new symbol for stdlib patches
2 parents 0195dff + 1edd3ca commit 3d5b4c8

File tree

4 files changed

+70
-10
lines changed

4 files changed

+70
-10
lines changed

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

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,10 +1113,49 @@ class Definitions {
11131113
* is read from a classfile.
11141114
*/
11151115
def patchStdLibClass(denot: ClassDenotation)(using Context): Unit =
1116-
11171116
def patch2(denot: ClassDenotation, patchCls: Symbol): Unit =
11181117
val scope = denot.info.decls.openForMutations
1118+
11191119
def recurse(patch: Symbol) = patch.is(Module) && scope.lookup(patch.name).exists
1120+
1121+
def makeClassSymbol(patch: Symbol, parents: List[Type], selfInfo: TypeOrSymbol) =
1122+
newClassSymbol(
1123+
owner = denot.symbol,
1124+
name = patch.name.asTypeName,
1125+
flags = patch.flags,
1126+
// need to rebuild a fresh ClassInfo
1127+
infoFn = cls => ClassInfo(
1128+
prefix = denot.symbol.thisType,
1129+
cls = cls,
1130+
declaredParents = parents, // assume parents in patch don't refer to symbols in the patch
1131+
decls = newScope,
1132+
selfInfo =
1133+
if patch.is(Module)
1134+
then TermRef(denot.symbol.thisType, patch.name.sourceModuleName)
1135+
else selfInfo // assume patch self type annotation does not refer to symbols in the patch
1136+
),
1137+
privateWithin = patch.privateWithin,
1138+
coord = denot.symbol.coord,
1139+
assocFile = denot.symbol.associatedFile
1140+
)
1141+
1142+
def makeNonClassSymbol(patch: Symbol) =
1143+
if patch.is(Inline) then
1144+
// Inline symbols contain trees in annotations, which is coupled
1145+
// with the underlying symbol.
1146+
// Changing owner for inline symbols is a simple workaround.
1147+
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1148+
patch
1149+
else
1150+
// change `info` which might contain reference to the patch
1151+
patch.copy(
1152+
owner = denot.symbol,
1153+
info =
1154+
if patch.is(Module)
1155+
then TypeRef(denot.symbol.thisType, patch.name.moduleClassName)
1156+
else patch.info // assume non-object info does not refer to symbols in the patch
1157+
)
1158+
11201159
if patchCls.exists then
11211160
val patches = patchCls.info.decls.filter(patch =>
11221161
!patch.isConstructor && !patch.isOneOf(PrivateOrSynthetic))
@@ -1126,9 +1165,16 @@ class Definitions {
11261165
for patch <- patches do
11271166
patch.ensureCompleted()
11281167
if !recurse(patch) then
1129-
patch.denot = patch.denot.copySymDenotation(owner = denot.symbol)
1130-
scope.enter(patch)
1131-
else if patch.isClass then
1168+
val sym =
1169+
patch.info match
1170+
case ClassInfo(_, _, parents, _, selfInfo) =>
1171+
makeClassSymbol(patch, parents, selfInfo)
1172+
case _ =>
1173+
makeNonClassSymbol(patch)
1174+
end match
1175+
sym.annotations = patch.annotations
1176+
scope.enter(sym)
1177+
if patch.isClass then
11321178
patch2(scope.lookup(patch.name).asClass, patch)
11331179

11341180
def patchWith(patchCls: Symbol) =

compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ object TypeTestsCasts {
8888
withMode(Mode.GadtConstraintInference) {
8989
// Why not widen type arguments here? Given the following program
9090
//
91-
// trait Tree[-T] class Ident[-T] extends Tree[T] def foo1(tree:
92-
// Tree[Int]) = tree.isInstanceOf[Ident[Int]]
91+
// trait Tree[-T] class Ident[-T] extends Tree[T]
92+
//
93+
// def foo1(tree: Tree[Int]) = tree.isInstanceOf[Ident[Int]]
9394
//
9495
// In checking whether the test tree.isInstanceOf[Ident[Int]]
9596
// is realizable, we want to constrain Ident[X] <: Tree[Int],

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,13 @@ class BootstrappedOnlyCompilationTests {
149149
// lower level of concurrency as to not kill their running VMs
150150

151151
@Test def picklingWithCompiler: Unit = {
152-
val jvmBackendFilter = FileFilter.exclude(List("BTypes.scala", "Primitives.scala")) // TODO
153-
val runtimeFilter = FileFilter.exclude(List("Tuple.scala", "stdLibPatches")) // TODO
154152
implicit val testGroup: TestGroup = TestGroup("testPicklingWithCompiler")
155153
aggregateTests(
156154
compileDir("compiler/src/dotty/tools", picklingWithCompilerOptions, recursive = false),
157155
compileDir("compiler/src/dotty/tools/dotc", picklingWithCompilerOptions, recursive = false),
158156
compileDir("library/src/scala/runtime/function", picklingWithCompilerOptions),
159-
compileFilesInDir("library/src/scala/runtime", picklingWithCompilerOptions, runtimeFilter),
160-
compileFilesInDir("compiler/src/dotty/tools/backend/jvm", picklingWithCompilerOptions, jvmBackendFilter),
157+
compileFilesInDir("library/src/scala/runtime", picklingWithCompilerOptions),
158+
compileFilesInDir("compiler/src/dotty/tools/backend/jvm", picklingWithCompilerOptions),
161159
compileDir("compiler/src/dotty/tools/dotc/ast", picklingWithCompilerOptions),
162160
compileDir("compiler/src/dotty/tools/dotc/core", picklingWithCompilerOptions, recursive = false),
163161
compileDir("compiler/src/dotty/tools/dotc/config", picklingWithCompilerOptions),

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)