Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Drop copied parent refinements before generating bytecode #21733

Merged
merged 4 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class Compiler {
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
new CountOuterAccesses) :: // Identify outer accessors that can be dropped
List(new DropOuterAccessors, // Drop unused outer accessors
new DropParentRefinements, // Drop parent refinements from a template
new CheckNoSuperThis, // Check that supercalls don't contain references to `this`
new Flatten, // Lift all inner classes to package scope
new TransformWildcards, // Replace wildcards with default values
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package dotty.tools.dotc.transform

import dotty.tools.dotc.transform.MegaPhase.MiniPhase
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer
import dotty.tools.dotc.typer.Typer

object DropParentRefinements:
val name: String = "dropParentRefinements"
val description: String = "drop parent refinements from a template"

/** Drop parent refinements from a template. because they are generated without
KacperFKorban marked this conversation as resolved.
Show resolved Hide resolved
* an implementation. These refinements are unusally required for tracked
* members with more specific types.
*/
class DropParentRefinements extends MiniPhase with IdentityDenotTransformer:
thisPhase =>
import tpd.*

override def phaseName: String = DropParentRefinements.name

override def description: String = DropParentRefinements.description

override def runsAfterGroupsOf: Set[String] = Set(CountOuterAccesses.name)

override def changesMembers: Boolean = true // the phase drops parent refinements

override def transformTemplate(tree: tpd.Template)(using Context): tpd.Tree =
val newBody = tree.body.filter(!_.hasAttachment(Typer.RefinementFromParent))
tree.body.foreach { member =>
if member.hasAttachment(Typer.RefinementFromParent) then
member.symbol.dropAfter(thisPhase)
}
cpy.Template(tree)(body = newBody)
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/Getters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class Getters extends MiniPhase with SymTransformer { thisPhase =>
override def transformValDef(tree: ValDef)(using Context): Tree =
val sym = tree.symbol
if !sym.is(Method) then return tree
val getterDef = DefDef(sym.asTerm, tree.rhs).withSpan(tree.span)
val getterDef = DefDef(sym.asTerm, tree.rhs).withSpan(tree.span).withAttachmentsFrom(tree)
if !sym.is(Mutable) then return getterDef
ensureSetter(sym.asTerm)
if !newSetters.contains(sym.setter) then return getterDef
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -877,16 +877,16 @@ class Namer { typer: Typer =>
protected def addAnnotations(sym: Symbol): Unit = original match {
case original: untpd.MemberDef =>
lazy val annotCtx = annotContext(original, sym)
original.setMods:
original.setMods:
mbovel marked this conversation as resolved.
Show resolved Hide resolved
original.mods.withAnnotations :
original.mods.annotations.mapConserve: annotTree =>
original.mods.annotations.mapConserve: annotTree =>
val cls = typedAheadAnnotationClass(annotTree)(using annotCtx)
if (cls eq sym)
report.error(em"An annotation class cannot be annotated with iself", annotTree.srcPos)
annotTree
else
val ann =
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
val ann =
if cls.is(JavaDefined) then Checking.checkNamedArgumentForJavaAnnotation(annotTree, cls.asClass)
else annotTree
val ann1 = Annotation.deferred(cls)(typedAheadExpr(ann)(using annotCtx))
sym.addAnnotation(ann1)
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ object Typer {
/** An attachment for GADT constraints that were inferred for a pattern. */
val InferredGadtConstraints = new Property.StickyKey[core.GadtConstraint]

/** Indicates that a definition was copied over from the parent refinements */
val RefinementFromParent = new Property.StickyKey[Unit]

/** An attachment on a Select node with an `apply` field indicating that the `apply`
* was inserted by the Typer.
*/
Expand Down Expand Up @@ -3081,7 +3084,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
( if sym.isType then TypeDef(sym.asType)
else if sym.is(Method) then DefDef(sym.asTerm)
else ValDef(sym.asTerm)
).withSpan(impl.span.startPos)
).withSpan(impl.span.startPos).withAttachment(RefinementFromParent, ())
body ++ refinements
case None =>
body
Expand Down
2 changes: 1 addition & 1 deletion tests/printing/transformed/lazy-vals-legacy.check
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[[syntax trees at end of MegaPhase{dropOuterAccessors, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // tests/printing/transformed/lazy-vals-legacy.scala
[[syntax trees at end of MegaPhase{dropOuterAccessors, dropParentRefinements, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // tests/printing/transformed/lazy-vals-legacy.scala
package <empty> {
@SourceFile("tests/printing/transformed/lazy-vals-legacy.scala") final module
class A extends Object {
Expand Down
2 changes: 1 addition & 1 deletion tests/printing/transformed/lazy-vals-new.check
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[[syntax trees at end of MegaPhase{dropOuterAccessors, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // tests/printing/transformed/lazy-vals-new.scala
[[syntax trees at end of MegaPhase{dropOuterAccessors, dropParentRefinements, checkNoSuperThis, flatten, transformWildcards, moveStatic, expandPrivate, restoreScopes, selectStatic, Collect entry points, collectSuperCalls, repeatableAnnotations}]] // tests/printing/transformed/lazy-vals-new.scala
package <empty> {
@SourceFile("tests/printing/transformed/lazy-vals-new.scala") final module
class A extends Object {
Expand Down
1 change: 1 addition & 0 deletions tests/run/i21213-min.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
9 changes: 9 additions & 0 deletions tests/run/i21213-min.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import scala.language.experimental.modularity
import scala.language.future

sealed abstract class Foo(tracked val discriminator: String)
class Bar extends Foo("bar")

val bar: Foo = Bar()
object Test extends App:
println(bar.discriminator)
1 change: 1 addition & 0 deletions tests/run/i21213.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
10 changes: 10 additions & 0 deletions tests/run/i21213.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import scala.language.experimental.modularity
import scala.language.future

enum Foo(tracked val discriminator: String):
case Bar() extends Foo("bar")
case Baz() extends Foo("baz")

val bar: Foo = Foo.Bar()
object Test extends App:
println(bar.discriminator)
Loading