Skip to content

Commit ca916f0

Browse files
authored
Merge branch 'main' into update-scala-settings
2 parents ad81b6f + 1cdf99f commit ca916f0

File tree

65 files changed

+1161
-280
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+1161
-280
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

+55-29
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ class JSCodeGen()(using genCtx: Context) {
927927
val className = encodeClassName(classSym)
928928
val body = js.Block(
929929
js.LoadModule(className),
930-
js.SelectStatic(className, fieldIdent)(irTpe))
930+
js.SelectStatic(fieldIdent)(irTpe))
931931
staticGetterDefs += js.MethodDef(
932932
js.MemberFlags.empty.withNamespace(js.MemberNamespace.PublicStatic),
933933
encodeStaticMemberSym(f), originalName, Nil, irTpe,
@@ -1146,42 +1146,72 @@ class JSCodeGen()(using genCtx: Context) {
11461146

11471147
private def genPrimaryJSClassCtor(dd: DefDef): PrimaryJSCtor = {
11481148
val sym = dd.symbol
1149-
val Block(stats, _) = dd.rhs: @unchecked
11501149
assert(sym.isPrimaryConstructor, s"called with non-primary ctor: $sym")
11511150

1151+
var preSuperStats = List.newBuilder[js.Tree]
11521152
var jsSuperCall: Option[js.JSSuperConstructorCall] = None
1153-
val jsStats = List.newBuilder[js.Tree]
1153+
val postSuperStats = List.newBuilder[js.Tree]
11541154

1155-
/* Move all statements after the super constructor call since JS
1156-
* cannot access `this` before the super constructor call.
1155+
/* Move param accessor initializers after the super constructor call since
1156+
* JS cannot access `this` before the super constructor call.
11571157
*
11581158
* dotc inserts statements before the super constructor call for param
11591159
* accessor initializers (including val's and var's declared in the
1160-
* params). We move those after the super constructor call, and are
1161-
* therefore executed later than for a Scala class.
1160+
* params). Those statements are assignments whose rhs'es are always simple
1161+
* Idents (the constructor params).
1162+
*
1163+
* There can also be local `val`s before the super constructor call for
1164+
* default arguments to the super constructor. These must remain before.
1165+
*
1166+
* Our strategy is therefore to move only the field assignments after the
1167+
* super constructor call. They are therefore executed later than for a
1168+
* Scala class (as specified for non-native JS classes semantics).
1169+
* However, side effects and evaluation order of all the other
1170+
* computations remains unchanged.
11621171
*/
11631172
withPerMethodBodyState(sym) {
1164-
stats.foreach {
1165-
case tree @ Apply(fun @ Select(Super(This(_), _), _), args)
1166-
if fun.symbol.isClassConstructor =>
1167-
assert(jsSuperCall.isEmpty, s"Found 2 JS Super calls at ${dd.sourcePos}")
1168-
implicit val pos: Position = tree.span
1169-
jsSuperCall = Some(js.JSSuperConstructorCall(genActualJSArgs(fun.symbol, args)))
1173+
def isThisField(tree: Tree): Boolean = tree match {
1174+
case Select(ths: This, _) => ths.symbol == currentClassSym.get
1175+
case tree: Ident => desugarIdent(tree).exists(isThisField(_))
1176+
case _ => false
1177+
}
11701178

1171-
case stat =>
1172-
val jsStat = genStat(stat)
1173-
assert(jsSuperCall.isDefined || !jsStat.isInstanceOf[js.VarDef],
1174-
"Trying to move a local VarDef after the super constructor call of a non-native JS class at " +
1175-
dd.sourcePos)
1176-
jsStats += jsStat
1179+
def rec(tree: Tree): Unit = {
1180+
tree match {
1181+
case Block(stats, expr) =>
1182+
stats.foreach(rec(_))
1183+
rec(expr)
1184+
1185+
case tree @ Apply(fun @ Select(Super(This(_), _), _), args)
1186+
if fun.symbol.isClassConstructor =>
1187+
assert(jsSuperCall.isEmpty, s"Found 2 JS Super calls at ${dd.sourcePos}")
1188+
implicit val pos: Position = tree.span
1189+
jsSuperCall = Some(js.JSSuperConstructorCall(genActualJSArgs(fun.symbol, args)))
1190+
1191+
case tree if jsSuperCall.isDefined =>
1192+
// Once we're past the super constructor call, everything goes after.
1193+
postSuperStats += genStat(tree)
1194+
1195+
case Assign(lhs, Ident(_)) if isThisField(lhs) =>
1196+
/* If that shape appears before the jsSuperCall, it is a param
1197+
* accessor initializer. We move it.
1198+
*/
1199+
postSuperStats += genStat(tree)
1200+
1201+
case stat =>
1202+
// Other statements are left before.
1203+
preSuperStats += genStat(stat)
1204+
}
11771205
}
1206+
1207+
rec(dd.rhs)
11781208
}
11791209

11801210
assert(jsSuperCall.isDefined,
11811211
s"Did not find Super call in primary JS construtor at ${dd.sourcePos}")
11821212

11831213
new PrimaryJSCtor(sym, genParamsAndInfo(sym, dd.paramss),
1184-
js.JSConstructorBody(Nil, jsSuperCall.get, jsStats.result())(dd.span))
1214+
js.JSConstructorBody(preSuperStats.result(), jsSuperCall.get, postSuperStats.result())(dd.span))
11851215
}
11861216

11871217
private def genSecondaryJSClassCtor(dd: DefDef): SplitSecondaryJSCtor = {
@@ -2213,10 +2243,7 @@ class JSCodeGen()(using genCtx: Context) {
22132243
if (isStaticModule(currentClassSym) && !isModuleInitialized.get.value &&
22142244
currentMethodSym.get.isClassConstructor) {
22152245
isModuleInitialized.get.value = true
2216-
val className = encodeClassName(currentClassSym)
2217-
val thisType = jstpe.ClassType(className)
2218-
val initModule = js.StoreModule(className, js.This()(thisType))
2219-
js.Block(superCall, initModule)
2246+
js.Block(superCall, js.StoreModule())
22202247
} else {
22212248
superCall
22222249
}
@@ -4433,13 +4460,12 @@ class JSCodeGen()(using genCtx: Context) {
44334460
js.JSSelect(qual, genPrivateFieldsSymbol()),
44344461
encodeFieldSymAsStringLiteral(sym))
44354462
} else {
4436-
js.JSPrivateSelect(qual, encodeClassName(sym.owner),
4437-
encodeFieldSym(sym))
4463+
js.JSPrivateSelect(qual, encodeFieldSym(sym))
44384464
}
44394465

44404466
(f, true)
44414467
} else if (sym.hasAnnotation(jsdefn.JSExportTopLevelAnnot)) {
4442-
val f = js.SelectStatic(encodeClassName(sym.owner), encodeFieldSym(sym))(jstpe.AnyType)
4468+
val f = js.SelectStatic(encodeFieldSym(sym))(jstpe.AnyType)
44434469
(f, true)
44444470
} else if (sym.hasAnnotation(jsdefn.JSExportStaticAnnot)) {
44454471
val jsName = sym.getAnnotation(jsdefn.JSExportStaticAnnot).get.argumentConstantString(0).getOrElse {
@@ -4465,9 +4491,9 @@ class JSCodeGen()(using genCtx: Context) {
44654491

44664492
val f =
44674493
if sym.is(JavaStatic) then
4468-
js.SelectStatic(className, fieldIdent)(irType)
4494+
js.SelectStatic(fieldIdent)(irType)
44694495
else
4470-
js.Select(qual, className, fieldIdent)(irType)
4496+
js.Select(qual, fieldIdent)(irType)
44714497

44724498
(f, boxed)
44734499
}

compiler/src/dotty/tools/backend/sjs/JSEncoding.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import dotty.tools.dotc.transform.sjs.JSSymUtils.*
1717

1818
import org.scalajs.ir
1919
import org.scalajs.ir.{Trees => js, Types => jstpe}
20-
import org.scalajs.ir.Names.{LocalName, LabelName, FieldName, SimpleMethodName, MethodName, ClassName}
20+
import org.scalajs.ir.Names.{LocalName, LabelName, SimpleFieldName, FieldName, SimpleMethodName, MethodName, ClassName}
2121
import org.scalajs.ir.OriginalName
2222
import org.scalajs.ir.OriginalName.NoOriginalName
2323
import org.scalajs.ir.UTF8String
@@ -173,7 +173,7 @@ object JSEncoding {
173173
}
174174

175175
def encodeFieldSym(sym: Symbol)(implicit ctx: Context, pos: ir.Position): js.FieldIdent =
176-
js.FieldIdent(FieldName(encodeFieldSymAsString(sym)))
176+
js.FieldIdent(FieldName(encodeClassName(sym.owner), SimpleFieldName(encodeFieldSymAsString(sym))))
177177

178178
def encodeFieldSymAsStringLiteral(sym: Symbol)(implicit ctx: Context, pos: ir.Position): js.StringLiteral =
179179
js.StringLiteral(encodeFieldSymAsString(sym))

compiler/src/dotty/tools/dotc/config/SourceVersion.scala

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum SourceVersion:
1111
case `3.3-migration`, `3.3`
1212
case `3.4-migration`, `3.4`
1313
case `3.5-migration`, `3.5`
14+
case `3.6-migration`, `3.6`
1415
// !!! Keep in sync with scala.runtime.stdlibPatches.language !!!
1516
case `future-migration`, `future`
1617

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

+12-7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ object Mode {
4141
val Pattern: Mode = newMode(0, "Pattern")
4242
val Type: Mode = newMode(1, "Type")
4343

44+
val PatternOrTypeBits: Mode = Pattern | Type
45+
4446
val ImplicitsEnabled: Mode = newMode(2, "ImplicitsEnabled")
4547
val InferringReturnType: Mode = newMode(3, "InferringReturnType")
4648

@@ -101,16 +103,19 @@ object Mode {
101103
*/
102104
val CheckBoundsOrSelfType: Mode = newMode(14, "CheckBoundsOrSelfType")
103105

104-
/** Use Scala2 scheme for overloading and implicit resolution */
105-
val OldOverloadingResolution: Mode = newMode(15, "OldOverloadingResolution")
106+
/** Use previous Scheme for implicit resolution. Currently significant
107+
* in 3.0-migration where we use Scala-2's scheme instead and in 3.5-migration
108+
* where we use the previous scheme up to 3.4 instead.
109+
*/
110+
val OldImplicitResolution: Mode = newMode(15, "OldImplicitResolution")
106111

107112
/** Treat CapturingTypes as plain AnnotatedTypes even in phase CheckCaptures.
108-
* Reuses the value of OldOverloadingResolution to save Mode bits.
109-
* This is OK since OldOverloadingResolution only affects implicit search, which
113+
* Reuses the value of OldImplicitResolution to save Mode bits.
114+
* This is OK since OldImplicitResolution only affects implicit search, which
110115
* is done during phases Typer and Inlinig, and IgnoreCaptures only has an
111116
* effect during phase CheckCaptures.
112117
*/
113-
val IgnoreCaptures = OldOverloadingResolution
118+
val IgnoreCaptures = OldImplicitResolution
114119

115120
/** Allow hk applications of type lambdas to wildcard arguments;
116121
* used for checking that such applications do not normally arise
@@ -120,8 +125,6 @@ object Mode {
120125
/** Read original positions when unpickling from TASTY */
121126
val ReadPositions: Mode = newMode(17, "ReadPositions")
122127

123-
val PatternOrTypeBits: Mode = Pattern | Type
124-
125128
/** We are elaborating the fully qualified name of a package clause.
126129
* In this case, identifiers should never be imported.
127130
*/
@@ -133,6 +136,8 @@ object Mode {
133136
/** We are typing the body of an inline method */
134137
val InlineableBody: Mode = newMode(21, "InlineableBody")
135138

139+
val NewGivenRules: Mode = newMode(22, "NewGivenRules")
140+
136141
/** We are synthesizing the receiver of an extension method */
137142
val SynthesizeExtMethodReceiver: Mode = newMode(23, "SynthesizeExtMethodReceiver")
138143

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ object Types extends TypeUtils {
7777
* | +- TypeVar
7878
* | +- HKTypeLambda
7979
* | +- MatchType
80+
* | +- FlexibleType
8081
* |
8182
* +- GroundType -+- AndType
8283
* +- OrType
@@ -3468,7 +3469,7 @@ object Types extends TypeUtils {
34683469
* `T | Null .. T`, so that `T | Null <: FlexibleType(T) <: T`.
34693470
* A flexible type will be erased to its original type `T`.
34703471
*/
3471-
case class FlexibleType(lo: Type, hi: Type) extends CachedProxyType with ValueType {
3472+
case class FlexibleType protected(lo: Type, hi: Type) extends CachedProxyType with ValueType {
34723473

34733474
override def underlying(using Context): Type = hi
34743475

@@ -3481,7 +3482,7 @@ object Types extends TypeUtils {
34813482
}
34823483

34833484
object FlexibleType {
3484-
def apply(tp: Type)(using Context): Type = tp match {
3485+
def apply(tp: Type)(using Context): FlexibleType = tp match {
34853486
case ft: FlexibleType => ft
34863487
case _ =>
34873488
// val tp1 = tp.stripNull()

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ class Inliner(val call: tpd.Tree)(using Context):
315315
case Super(qual, _) => qual
316316
case pre => pre
317317
val preLevel = classNestingLevel(inlinedMethod.owner)
318-
if preLevel > level then outerSelect(pre, inlinedMethod.owner, preLevel - level, selfSym.info)
318+
if preLevel > level then outerSelect(pre, inlinedMethod.owner.enclosingClass, preLevel - level, selfSym.info)
319319
else pre
320320

321321
val binding = accountForOpaques(

compiler/src/dotty/tools/dotc/interactive/Completion.scala

+24-7
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ object Completion:
7575
customMatcher: Option[Name => Boolean] = None
7676
)(using Context): CompletionMap =
7777
val adjustedPath = typeCheckExtensionConstructPath(untpdPath, tpdPath, pos)
78-
computeCompletions(pos, mode, rawPrefix, adjustedPath, customMatcher)
78+
computeCompletions(pos, mode, rawPrefix, adjustedPath, untpdPath, customMatcher)
7979

8080
/**
8181
* Inspect `path` to determine what kinds of symbols should be considered.
@@ -199,12 +199,16 @@ object Completion:
199199
.flatten.getOrElse(tpdPath)
200200

201201
private def computeCompletions(
202-
pos: SourcePosition, mode: Mode, rawPrefix: String, adjustedPath: List[tpd.Tree], matches: Option[Name => Boolean]
202+
pos: SourcePosition,
203+
mode: Mode, rawPrefix: String,
204+
adjustedPath: List[tpd.Tree],
205+
untpdPath: List[untpd.Tree],
206+
matches: Option[Name => Boolean]
203207
)(using Context): CompletionMap =
204208
val hasBackTick = rawPrefix.headOption.contains('`')
205209
val prefix = if hasBackTick then rawPrefix.drop(1) else rawPrefix
206210
val matches0 = matches.getOrElse(_.startsWith(prefix))
207-
val completer = new Completer(mode, pos, matches0)
211+
val completer = new Completer(mode, pos, untpdPath, matches0)
208212

209213
val result = adjustedPath match
210214
// Ignore synthetic select from `This` because in code it was `Ident`
@@ -279,6 +283,12 @@ object Completion:
279283
if denot.isType then denot.symbol.showFullName
280284
else denot.info.widenTermRefExpr.show
281285

286+
287+
def isInNewContext(untpdPath: List[untpd.Tree]): Boolean =
288+
untpdPath match
289+
case _ :: untpd.New(selectOrIdent: (untpd.Select | untpd.Ident)) :: _ => true
290+
case _ => false
291+
282292
/** Include in completion sets only symbols that
283293
* 1. is not absent (info is not NoType)
284294
* 2. are not a primary constructor,
@@ -290,7 +300,11 @@ object Completion:
290300
* 8. symbol is not a constructor proxy module when in type completion mode
291301
* 9. have same term/type kind as name prefix given so far
292302
*/
293-
def isValidCompletionSymbol(sym: Symbol, completionMode: Mode)(using Context): Boolean =
303+
def isValidCompletionSymbol(sym: Symbol, completionMode: Mode, isNew: Boolean)(using Context): Boolean =
304+
305+
lazy val isEnum = sym.is(Enum) ||
306+
(sym.companionClass.exists && sym.companionClass.is(Enum))
307+
294308
sym.exists &&
295309
!sym.isAbsent() &&
296310
!sym.isPrimaryConstructor &&
@@ -300,6 +314,7 @@ object Completion:
300314
!sym.isPackageObject &&
301315
!sym.is(Artifact) &&
302316
!(completionMode.is(Mode.Type) && sym.isAllOf(ConstructorProxyModule)) &&
317+
!(isNew && isEnum) &&
303318
(
304319
(completionMode.is(Mode.Term) && (sym.isTerm || sym.is(ModuleClass))
305320
|| (completionMode.is(Mode.Type) && (sym.isType || sym.isStableMember)))
@@ -323,7 +338,7 @@ object Completion:
323338
* For the results of all `xyzCompletions` methods term names and type names are always treated as different keys in the same map
324339
* and they never conflict with each other.
325340
*/
326-
class Completer(val mode: Mode, pos: SourcePosition, matches: Name => Boolean):
341+
class Completer(val mode: Mode, pos: SourcePosition, untpdPath: List[untpd.Tree], matches: Name => Boolean):
327342
/** Completions for terms and types that are currently in scope:
328343
* the members of the current class, local definitions and the symbols that have been imported,
329344
* recursively adding completions from outer scopes.
@@ -530,7 +545,7 @@ object Completion:
530545
// There are four possible ways for an extension method to be applicable
531546

532547
// 1. The extension method is visible under a simple name, by being defined or inherited or imported in a scope enclosing the reference.
533-
val termCompleter = new Completer(Mode.Term, pos, matches)
548+
val termCompleter = new Completer(Mode.Term, pos, untpdPath, matches)
534549
val extMethodsInScope = termCompleter.scopeCompletions.toList.flatMap:
535550
case (name, denots) => denots.collect:
536551
case d: SymDenotation if d.isTerm && d.termRef.symbol.is(Extension) => (d.termRef, name.asTermName)
@@ -557,14 +572,16 @@ object Completion:
557572
}
558573
extMethodsWithAppliedReceiver.groupByName
559574

575+
lazy val isNew: Boolean = isInNewContext(untpdPath)
576+
560577
/** Include in completion sets only symbols that
561578
* 1. match the filter method,
562579
* 2. satisfy [[Completion.isValidCompletionSymbol]]
563580
*/
564581
private def include(denot: SingleDenotation, nameInScope: Name)(using Context): Boolean =
565582
matches(nameInScope) &&
566583
completionsFilter(NoType, nameInScope) &&
567-
isValidCompletionSymbol(denot.symbol, mode)
584+
isValidCompletionSymbol(denot.symbol, mode, isNew)
568585

569586
private def extractRefinements(site: Type)(using Context): Seq[SingleDenotation] =
570587
site match

0 commit comments

Comments
 (0)