Skip to content

Commit 8f0d12b

Browse files
authored
Refactorings and fixes to erased definition handling (#23404)
These are cleanups and bug-fixes. They don't change the semantics of erasedDefinitions
2 parents 7093dad + 1079192 commit 8f0d12b

File tree

13 files changed

+88
-166
lines changed

13 files changed

+88
-166
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ class Compiler {
9292
new ExplicitSelf, // Make references to non-trivial self types explicit as casts
9393
new StringInterpolatorOpt, // Optimizes raw and s and f string interpolators by rewriting them to string concatenations or formats
9494
new DropBreaks) :: // Optimize local Break throws by rewriting them
95-
List(new PruneErasedDefs, // Drop erased definitions from scopes and simplify erased expressions
96-
new UninitializedDefs, // Replaces `compiletime.uninitialized` by `_`
95+
List(new UninitializedDefs, // Replaces `compiletime.uninitialized` by `_`
9796
new InlinePatterns, // Remove placeholders of inlined patterns
9897
new VCInlineMethods, // Inlines calls to value class methods
9998
new SeqLiterals, // Express vararg arguments as arrays

compiler/src/dotty/tools/dotc/ast/TreeInfo.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -588,14 +588,18 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
588588
case New(_) | Closure(_, _, _) =>
589589
Pure
590590
case TypeApply(fn, _) =>
591-
if (fn.symbol.is(Erased) || fn.symbol == defn.QuotedTypeModule_of || fn.symbol == defn.Predef_classOf) Pure else exprPurity(fn)
591+
if tree.tpe.isInstanceOf[MethodOrPoly] then exprPurity(fn)
592+
else if fn.symbol == defn.QuotedTypeModule_of || fn.symbol == defn.Predef_classOf then Pure
593+
else if fn.symbol == defn.Compiletime_erasedValue && tree.tpe.dealias.isInstanceOf[ConstantType] then Pure
594+
else Impure
592595
case Apply(fn, args) =>
593-
if isPureApply(tree, fn) then
594-
minOf(exprPurity(fn), args.map(exprPurity)) `min` Pure
595-
else if fn.symbol.is(Erased) then
596-
Pure
596+
val factorPurity = minOf(exprPurity(fn), args.map(exprPurity))
597+
if tree.tpe.isInstanceOf[MethodOrPoly] then // no evaluation
598+
factorPurity `min` Pure
599+
else if isPureApply(tree, fn) then
600+
factorPurity `min` Pure
597601
else if fn.symbol.isStableMember /* && fn.symbol.is(Lazy) */ then
598-
minOf(exprPurity(fn), args.map(exprPurity)) `min` Idempotent
602+
factorPurity `min` Idempotent
599603
else
600604
Impure
601605
case Typed(expr, _) =>

compiler/src/dotty/tools/dotc/cc/ccConfig.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ object ccConfig:
5656

5757
/** Not used currently. Handy for trying out new features */
5858
def newScheme(using ctx: Context): Boolean =
59-
ctx.settings.XdropComments.value
59+
Feature.sourceVersion.stable.isAtLeast(SourceVersion.`3.7`)
6060

6161
end ccConfig

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,15 @@ class ElimErasedValueType extends MiniPhase with InfoTransformer { thisPhase =>
107107
(sym1.owner.derivesFrom(defn.PolyFunctionClass) ||
108108
sym2.owner.derivesFrom(defn.PolyFunctionClass))
109109

110+
def oneErasedInline =
111+
sym1.isInlineMethod && !sym1.isRetainedInlineMethod
112+
|| sym2.isInlineMethod && !sym2.isRetainedInlineMethod
113+
110114
// super-accessors start as private, and their expanded name can clash after
111115
// erasure. TODO: Verify that this is OK.
112116
def bothSuperAccessors = sym1.name.is(SuperAccessorName) && sym2.name.is(SuperAccessorName)
113-
if (sym1.name != sym2.name && !bothSuperAccessors ||
114-
!info1.matchesLoosely(info2) && !bothPolyApply)
117+
if (sym1.name != sym2.name && !bothSuperAccessors
118+
|| !info1.matchesLoosely(info2) && !bothPolyApply && !oneErasedInline)
115119
report.error(DoubleDefinition(sym1, sym2, root), root.srcPos)
116120
}
117121
while (opc.hasNext) {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import StdNames.*
2020
import config.Feature
2121
import inlines.Inlines.inInlineMethod
2222
import util.Property
23+
import inlines.Inlines
24+
import reporting.InlinedAnonClassWarning
2325

2426
object FirstTransform {
2527
val name: String = "firstTransform"
@@ -207,6 +209,11 @@ class FirstTransform extends MiniPhase with SymTransformer { thisPhase =>
207209
case _ => tree
208210
}
209211

212+
override def transformTypeDef(tree: TypeDef)(using Context): Tree =
213+
if tree.symbol.isAnonymousClass && Inlines.inInlineMethod then
214+
report.warning(InlinedAnonClassWarning(), tree.symbol.sourcePos)
215+
tree
216+
210217
/** Perform one of the following simplification if applicable:
211218
*
212219
* true && y ==> y

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package dotty.tools
22
package dotc
33
package transform
44

5-
import dotty.tools.dotc.core.Contexts.*
6-
import dotty.tools.dotc.core.Decorators.*
7-
import dotty.tools.dotc.core.Symbols.*
8-
import dotty.tools.dotc.core.Flags.*
9-
import dotty.tools.dotc.core.Types.*
10-
import dotty.tools.dotc.transform.MegaPhase.MiniPhase
11-
import dotty.tools.dotc.inlines.Inlines
5+
import core.*
6+
import Contexts.*, Decorators.*, Symbols.*, Flags.*, Types.*
7+
import MegaPhase.MiniPhase
8+
import inlines.Inlines
9+
import ast.tpd
10+
1211

1312
/** Check that `tree.rhs` can be right hand-side of an `inline` value definition. */
1413
class InlineVals extends MiniPhase:
@@ -38,7 +37,10 @@ class InlineVals extends MiniPhase:
3837
tpt.tpe.widenTermRefExpr.dealiasKeepOpaques.normalized match
3938
case tp: ConstantType =>
4039
if !isPureExpr(rhs) then
41-
def details = if enclosingInlineds.isEmpty then "" else i"but was: $rhs"
40+
def details =
41+
if enclosingInlineds.nonEmpty || rhs.isInstanceOf[tpd.Inlined]
42+
then i" but was: $rhs"
43+
else ""
4244
report.error(em"inline value must be pure$details", rhs.srcPos)
4345
case tp =>
4446
if tp.typeSymbol.is(Opaque) then

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

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
335335
}
336336
}
337337

338-
private object dropInlines extends TreeMap {
339-
override def transform(tree: Tree)(using Context): Tree = tree match {
340-
case tree @ Inlined(call, _, expansion) =>
341-
val newExpansion = PruneErasedDefs.trivialErasedTree(tree)
342-
cpy.Inlined(tree)(call, Nil, newExpansion)
343-
case _ => super.transform(tree)
344-
}
345-
}
346-
347338
def checkUsableAsValue(tree: Tree)(using Context): Tree =
348339
def unusable(msg: Symbol => Message) =
349340
errorTree(tree, msg(tree.symbol))
@@ -414,26 +405,13 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
414405
checkUsableAsValue(tree) match
415406
case tree1: Select => transformSelect(tree1, Nil)
416407
case tree1 => tree1
417-
case tree: Apply =>
418-
val methType = tree.fun.tpe.widen.asInstanceOf[MethodType]
419-
val app =
420-
if (methType.hasErasedParams)
421-
tpd.cpy.Apply(tree)(
422-
tree.fun,
423-
tree.args.zip(methType.erasedParams).map((arg, isErased) =>
424-
if !isErased then arg
425-
else
426-
if methType.isResultDependent then
427-
Checking.checkRealizable(arg.tpe, arg.srcPos, "erased argument")
428-
if (methType.isImplicitMethod && arg.span.isSynthetic)
429-
arg match
430-
case _: RefTree | _: Apply | _: TypeApply if arg.symbol.is(Erased) =>
431-
dropInlines.transform(arg)
432-
case _ =>
433-
PruneErasedDefs.trivialErasedTree(arg)
434-
else dropInlines.transform(arg)))
435-
else
436-
tree
408+
case app: Apply =>
409+
val methType = app.fun.tpe.widen.asInstanceOf[MethodType]
410+
if (methType.hasErasedParams)
411+
for (arg, isErased) <- app.args.lazyZip(methType.erasedParams) do
412+
if isErased then
413+
if methType.isResultDependent then
414+
Checking.checkRealizable(arg.tpe, arg.srcPos, "erased argument")
437415
def app1 =
438416
// reverse order of transforming args and fun. This way, we get a chance to see other
439417
// well-formedness errors before reporting errors in possible inferred type args of fun.
@@ -499,7 +477,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
499477
registerIfHasMacroAnnotations(tree)
500478
checkErasedDef(tree)
501479
Checking.checkPolyFunctionType(tree.tpt)
502-
val tree1 = cpy.ValDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
480+
val tree1 = cpy.ValDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt))
503481
if tree1.removeAttachment(desugar.UntupledParam).isDefined then
504482
checkStableSelection(tree.rhs)
505483
processValOrDefDef(super.transform(tree1))
@@ -508,7 +486,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
508486
checkErasedDef(tree)
509487
Checking.checkPolyFunctionType(tree.tpt)
510488
annotateContextResults(tree)
511-
val tree1 = cpy.DefDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt), rhs = normalizeErasedRhs(tree.rhs, tree.symbol))
489+
val tree1 = cpy.DefDef(tree)(tpt = makeOverrideTypeDeclared(tree.symbol, tree.tpt))
512490
processValOrDefDef(superAcc.wrapDefDef(tree1)(super.transform(tree1).asInstanceOf[DefDef]))
513491
case tree: TypeDef =>
514492
registerIfHasMacroAnnotations(tree)
@@ -632,12 +610,6 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
632610
Checking.checkAndAdaptExperimentalImports(trees)
633611
super.transformStats(trees, exprOwner, wrapResult)
634612

635-
/** Transforms the rhs tree into a its default tree if it is in an `erased` val/def.
636-
* Performed to shrink the tree that is known to be erased later.
637-
*/
638-
private def normalizeErasedRhs(rhs: Tree, sym: Symbol)(using Context) =
639-
if (sym.isEffectivelyErased) dropInlines.transform(rhs) else rhs
640-
641613
private def registerNeedsInlining(tree: Tree)(using Context): Unit =
642614
if tree.symbol.is(Inline) && !Inlines.inInlineMethod && !ctx.mode.is(Mode.NoInline) then
643615
ctx.compilationUnit.needsInlining = true

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

Lines changed: 0 additions & 88 deletions
This file was deleted.

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ class ResolveSuper extends MiniPhase with IdentityDenotTransformer { thisPhase =
3737

3838
override def description: String = ResolveSuper.description
3939

40-
override def runsAfter: Set[String] = Set(ElimByName.name, // verified empirically, need to figure out what the reason is.
41-
PruneErasedDefs.name) // Erased decls make `isCurrent` work incorrectly
40+
override def runsAfter: Set[String] = Set(ElimByName.name) // verified empirically, need to figure out what the reason is.
4241

4342
override def changesMembers: Boolean = true // the phase adds super accessors
4443

sbt-bridge/test/xsbt/CompileProgressSpecification.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CompileProgressSpecification {
6363
"staging",
6464
"splicing",
6565
"pickleQuotes",
66-
"MegaPhase{pruneErasedDefs,...,arrayConstructors}",
66+
"MegaPhase{uninitialized,...,arrayConstructors}",
6767
"erasure",
6868
"constructors",
6969
"genBCode"

0 commit comments

Comments
 (0)