From 663f8ecdb98528dc43a554467021faf8f031bb2e Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Mon, 17 Feb 2025 15:30:42 +0100 Subject: [PATCH 1/2] chore: Add @nowarn annotation to LazyVals. (#22270) Unsafe is planned to be removed in future Java versions. Motivication: Makes it compile on JDK 23 refs: https://openjdk.org/jeps/471 Modification: Add `@nowarn("cat=deprecation")` Result: Compiles successfully on JDK 23 [Cherry-picked 4952e0af407d652a47efb5436fe0e0f023db3367] --- .../tools/dotc/staging/CrossStageSafety.scala | 10 +++++++++- tests/neg/i22592.scala | 14 ++++++++++++++ tests/pos/i22592.scala | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i22592.scala create mode 100644 tests/pos/i22592.scala diff --git a/compiler/src/dotty/tools/dotc/staging/CrossStageSafety.scala b/compiler/src/dotty/tools/dotc/staging/CrossStageSafety.scala index 1832eeabca7e..4534af0f0883 100644 --- a/compiler/src/dotty/tools/dotc/staging/CrossStageSafety.scala +++ b/compiler/src/dotty/tools/dotc/staging/CrossStageSafety.scala @@ -189,11 +189,19 @@ class CrossStageSafety extends TreeMapWithStages { /** Check level consistency of terms references */ private def checkLevelConsistency(tree: Ident | This)(using Context): Unit = + def isStatic(pre: Type)(using Context): Boolean = pre match + case pre: NamedType => + val sym = pre.currentSymbol + sym.is(Package) || sym.isStaticOwner && isStatic(pre.prefix) + case pre: ThisType => isStatic(pre.tref) + case _ => true new TypeTraverser { def traverse(tp: Type): Unit = tp match case tp @ TermRef(NoPrefix, _) if !tp.symbol.isStatic && level != levelOf(tp.symbol) => levelError(tp.symbol, tp, tree.srcPos) + case tp: ThisType if isStatic(tp) => + // static object (OK) case tp: ThisType if level != -1 && level != levelOf(tp.cls) => levelError(tp.cls, tp, tree.srcPos) case tp: AnnotatedType => @@ -201,7 +209,7 @@ class CrossStageSafety extends TreeMapWithStages { case _ if tp.typeSymbol.is(Package) => // OK case _ => - traverseChildren(tp) + traverseChildren(tp) }.traverse(tree.tpe) private def levelError(sym: Symbol, tp: Type, pos: SrcPos)(using Context): tp.type = { diff --git a/tests/neg/i22592.scala b/tests/neg/i22592.scala new file mode 100644 index 000000000000..6a9a89cacf2a --- /dev/null +++ b/tests/neg/i22592.scala @@ -0,0 +1,14 @@ +import scala.quoted.* + +trait Foo: + def inherited = () + +class Bar extends Foo: + def local = () + def localArg(arg: Any) = () + + def macro1(using Quotes): Expr[Unit] = '{ local } // error + def macro3(using Quotes): Expr[Unit] = '{ inherited } // error + def macro4(using Quotes): Expr[Unit] = '{ this.local } // error + def macro5(using Quotes): Expr[Unit] = '{ this.inherited } // error + def macro6(using Quotes): Expr[Unit] = '{ localArg(this) } // error // error diff --git a/tests/pos/i22592.scala b/tests/pos/i22592.scala new file mode 100644 index 000000000000..f6a1f2eff696 --- /dev/null +++ b/tests/pos/i22592.scala @@ -0,0 +1,15 @@ +import scala.quoted.* + +trait Foo: + def inherited = () + +object Bar extends Foo: + def local = () + def localArg(arg: Any) = () + + def macro1(using Quotes): Expr[Unit] = '{ local } + def macro2(using Quotes): Expr[Unit] = '{ Bar.inherited } + def macro3(using Quotes): Expr[Unit] = '{ inherited } + def macro4(using Quotes): Expr[Unit] = '{ this.local } + def macro5(using Quotes): Expr[Unit] = '{ this.inherited } + def macro6(using Quotes): Expr[Unit] = '{ localArg(this) } From 91923ea2f78074cc46c82ba625e92c1625a431bc Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Tue, 22 Apr 2025 15:49:36 +0200 Subject: [PATCH 2/2] chore: Remove one test that only works with new experimental feature --- tests/neg/22145b.check | 36 ------------------------------------ tests/neg/22145b.scala | 40 ---------------------------------------- 2 files changed, 76 deletions(-) delete mode 100644 tests/neg/22145b.check delete mode 100644 tests/neg/22145b.scala diff --git a/tests/neg/22145b.check b/tests/neg/22145b.check deleted file mode 100644 index de605ce24276..000000000000 --- a/tests/neg/22145b.check +++ /dev/null @@ -1,36 +0,0 @@ --- [E008] Not Found Error: tests/neg/22145b.scala:15:19 ---------------------------------------------------------------- -15 | require(base.isWithin(p, start, end), "position is out of bounds") // error - | ^^^^^^^^^^^^^ - | value isWithin is not a member of Collection.this.Self --- [E008] Not Found Error: tests/neg/22145b.scala:28:59 ---------------------------------------------------------------- -28 | def positionAfter(p: Position): Position = self.base.positionAfter(p) // error - | ^^^^^^^^^^^^^^^^^^^^^^^ - |value positionAfter is not a member of Collection.this.Self. - |An extension method was tried, but could not be fully constructed: - | - | this.positionAfter(self.base) - | - | failed with: - | - | Found: (self.base : Collection.this.Self) - | Required: foo.Collection.given_is_Slice_Collection.Self² - | - | where: Self is a type in trait Collection - | Self² is a type in object given_is_Slice_Collection which is an alias of Collection.this.Slice - | --- [E008] Not Found Error: tests/neg/22145b.scala:29:50 ---------------------------------------------------------------- -29 | def apply(p: Position): Element = self.base.apply(p) // error - | ^^^^^^^^^^^^^^^ - |value apply is not a member of Collection.this.Self. - |An extension method was tried, but could not be fully constructed: - | - | this.apply(self.base) - | - | failed with: - | - | Found: (self.base : Collection.this.Self) - | Required: foo.Collection.given_is_Slice_Collection.Self² - | - | where: Self is a type in trait Collection - | Self² is a type in object given_is_Slice_Collection which is an alias of Collection.this.Slice - | diff --git a/tests/neg/22145b.scala b/tests/neg/22145b.scala deleted file mode 100644 index 5b8de5672fba..000000000000 --- a/tests/neg/22145b.scala +++ /dev/null @@ -1,40 +0,0 @@ -package foo - -import language.experimental.modularity - -trait Collection: - me => - - type Self - type Position - type Element - - final class Slice(private[Collection] val base: Self, val start: Position, val end: Position): - - final def apply(p: Position): Element = - require(base.isWithin(p, start, end), "position is out of bounds") // error - base.apply(p) - - end Slice - - given Slice is Collection: - - type Position = me.Position - type Element = me.Element - - extension (self: Self) - def start: Position = self.start - def end: Position = self.end - def positionAfter(p: Position): Position = self.base.positionAfter(p) // error - def apply(p: Position): Element = self.base.apply(p) // error - - end given - - extension (self: Self) - - def start: Position - def end: Position - def positionAfter(p: Position): Position - def apply(p: Position): Element - - end extension