Skip to content

Commit 56893de

Browse files
committed
Split Symbol.newType into 2 methods and add tests
1 parent 61764dd commit 56893de

File tree

11 files changed

+96
-19
lines changed

11 files changed

+96
-19
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,11 +2649,15 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
26492649
def newBind(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol =
26502650
checkValidFlags(flags.toTermFlags, Flags.validBindFlags)
26512651
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | dotc.core.Flags.Case, tpe)
2652-
2653-
def newType(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol =
2652+
2653+
def newTypeAlias(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol =
2654+
checkValidFlags(flags.toTypeFlags, Flags.validTypeFlags)
2655+
dotc.core.Symbols.newSymbol(owner, name.toTypeName, flags | dotc.core.Flags.Deferred, dotc.core.Types.TypeAlias(tpe), privateWithin)
2656+
2657+
def newBoundedType(owner: Symbol, name: String, flags: Flags, tpe: TypeBounds, privateWithin: Symbol): Symbol =
26542658
checkValidFlags(flags.toTypeFlags, Flags.validTypeFlags)
26552659
dotc.core.Symbols.newSymbol(owner, name.toTypeName, flags | dotc.core.Flags.Deferred, tpe, privateWithin)
2656-
2660+
26572661
def noSymbol: Symbol = dotc.core.Symbols.NoSymbol
26582662

26592663
private inline def checkValidFlags(inline flags: Flags, inline valid: Flags): Unit =
@@ -2995,6 +2999,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
29952999
// Keep: aligned with Quotes's `newBind` doc
29963000
private[QuotesImpl] def validBindFlags: Flags = Case // Flags that could be allowed: Implicit | Given | Erased
29973001

3002+
// Keep: aligned with Quotes's 'newType' doc
29983003
private[QuotesImpl] def validTypeFlags: Flags = Private | Protected | Override | Deferred | Final | Infix | Local
29993004

30003005
end Flags

library/src/scala/quoted/Quotes.scala

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,23 +3963,41 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
39633963
// Keep: `flags` doc aligned with QuotesImpl's `validBindFlags`
39643964
def newBind(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol
39653965

3966-
/** Generate a new type symbol with the given parent, name and type
3967-
*
3966+
/** Generate a new type symbol for a type alias with the given parent, name and type
3967+
*
3968+
* This symbol starts without an accompanying definition.
3969+
* It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
3970+
* this symbol to the TypeDef constructor.
3971+
*
3972+
* @param parent The owner of the type
3973+
* @param name The name of the type
3974+
* @param flags extra flags to with which symbol can be constructed. `Deferred` flag will be added. Can be `Private` | `Protected` | `Override` | `Deferred` | `Final` | `Infix` | `Local`
3975+
* @param tpe The rhs the type alias
3976+
* @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
3977+
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
3978+
* direct or indirect children of the reflection context's owner.
3979+
*/
3980+
@experimental
3981+
// Keep: `flags` doc aligned with QuotesImpl's `validTypeFlags`
3982+
def newTypeAlias(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol
3983+
3984+
/** Generate a new type symbol for a type bounds with the given parent, name and type
3985+
*
39683986
* This symbol starts without an accompanying definition.
39693987
* It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
39703988
* this symbol to the TypeDef constructor.
39713989
*
39723990
* @param parent The owner of the type
39733991
* @param name The name of the type
39743992
* @param flags extra flags to with which symbol can be constructed. `Deferred` flag will be added. Can be `Private` | `Protected` | `Override` | `Deferred` | `Final` | `Infix` | `Local`
3975-
* @param tpe The rhs or bounds of the type
3993+
* @param tpe The bounds of the type
39763994
* @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
39773995
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
39783996
* direct or indirect children of the reflection context's owner.
39793997
*/
39803998
@experimental
39813999
// Keep: `flags` doc aligned with QuotesImpl's `validTypeFlags`
3982-
def newType(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol
4000+
def newBoundedType(parent: Symbol, name: String, flags: Flags, tpe: TypeBounds, privateWithin: Symbol): Symbol
39834001

39844002
/** Definition not available */
39854003
def noSymbol: Symbol
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//> using options -experimental -Yno-experimental
2+
import scala.quoted.*
3+
4+
inline def testMacro = ${ testImpl }
5+
6+
transparent inline def transparentTestMacro = ${ testImpl }
7+
8+
def testImpl(using Quotes): Expr[Object] = {
9+
import quotes.reflect.*
10+
11+
def makeType(owner: Symbol): Symbol =
12+
Symbol.newBoundedType(owner, "mytype", Flags.EmptyFlags, TypeBounds.lower(TypeRepr.of[String]), Symbol.noSymbol)
13+
14+
val typeDef = TypeDef(makeType(Symbol.spliceOwner))
15+
// Expr printer does not work here, see comment:
16+
// https://github.com/scala/scala3/pull/20347#issuecomment-2096824617
17+
assert(typeDef.toString == "TypeDef(mytype,TypeTree[TypeBounds(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class java)),object lang),String),TypeRef(ThisType(TypeRef(NoPrefix,module class scala)),class Any))])")
18+
19+
val clsSymbol = Symbol.newClass(Symbol.spliceOwner, "CLS", List(TypeRepr.of[Object]), sym => List(makeType(sym)), None)
20+
val classDef: ClassDef = ClassDef(clsSymbol, List(TypeTree.of[Object]), List(TypeDef(clsSymbol.typeMember("mytype"))))
21+
Block(List(classDef), Apply(Select(New(TypeIdent(clsSymbol)), clsSymbol.primaryConstructor), List.empty)).asExprOf[Object]
22+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//> using options -experimental -Yno-experimental
2+
def test =
3+
testMacro
4+
transparentTestMacro
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//> using options -experimental -Yno-experimental
2+
import scala.quoted.*
3+
4+
inline def testMacro = ${ testImpl }
5+
6+
transparent inline def transparentTestMacro = ${ testImpl }
7+
8+
def testImpl(using Quotes): Expr[Object] = {
9+
import quotes.reflect.*
10+
11+
def makeType(owner: Symbol): Symbol =
12+
Symbol.newTypeAlias(owner, "mytype", Flags.EmptyFlags, TypeRepr.of[String], Symbol.noSymbol)
13+
14+
val clsSymbol = Symbol.newClass(Symbol.spliceOwner, "CLS", List(TypeRepr.of[Object]), sym => List(makeType(sym)), None)
15+
val classDef: ClassDef = ClassDef(clsSymbol, List(TypeTree.of[Object]), List(TypeDef(clsSymbol.typeMember("mytype"))))
16+
17+
Block(List(classDef), Apply(Select(New(TypeIdent(clsSymbol)), clsSymbol.primaryConstructor), List.empty)).asExprOf[Object]
18+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//> using options -experimental -Yno-experimental
2+
def test =
3+
testMacro
4+
transparentTestMacro
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//> using options -experimental -Yno-experimental
2+
import scala.quoted.*
3+
4+
inline def testMacro = ${ testImpl }
5+
6+
def testImpl(using Quotes): Expr[Unit] = {
7+
import quotes.reflect.*
8+
val sym = Symbol.newTypeAlias(Symbol.spliceOwner, "mytype", Flags.EmptyFlags, TypeRepr.of[String], Symbol.noSymbol)
9+
val typeDef = TypeDef(sym)
10+
assert(typeDef.show == "type mytype = java.lang.String")
11+
12+
Block(List(typeDef), '{()}.asTerm).asExprOf[Unit]
13+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
//> using options -experimental -Yno-experimental
2+
def test = testMacro

tests/pos-macros/quoted-sym-newtype/Macro_1.scala

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

tests/pos-macros/quoted-sym-newtype/Test_2.scala

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

tests/run-tasty-inspector/stdlibExperimentalDefinitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ val experimentalDefinitionInLibrary = Set(
6363
"scala.quoted.Quotes.reflectModule.SymbolModule.newModule",
6464
"scala.quoted.Quotes.reflectModule.SymbolModule.freshName",
6565
"scala.quoted.Quotes.reflectModule.SymbolMethods.info",
66+
// Added for 3.6.0, stabilize after feedback.
67+
"scala.quoted.Quotes.reflectModule.SymbolModule.newBoundedType",
68+
"scala.quoted.Quotes.reflectModule.SymbolModule.newTypeAlias",
6669

6770
// New feature: functions with erased parameters.
6871
// Need erasedDefinitions enabled.

0 commit comments

Comments
 (0)