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

Add the possibility to create a typeSymbol in the Quotes API #20347

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,11 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
def newBind(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol =
checkValidFlags(flags.toTermFlags, Flags.validBindFlags)
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | dotc.core.Flags.Case, tpe)

def newType(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol =
checkValidFlags(flags.toTypeFlags, Flags.validTypeFlags)
dotc.core.Symbols.newSymbol(owner, name.toTypeName, flags | dotc.core.Flags.Deferred, tpe, privateWithin)

def noSymbol: Symbol = dotc.core.Symbols.NoSymbol

private inline def checkValidFlags(inline flags: Flags, inline valid: Flags): Unit =
Expand Down Expand Up @@ -2953,6 +2958,9 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler

// Keep: aligned with Quotes's `newBind` doc
private[QuotesImpl] def validBindFlags: Flags = Case // Flags that could be allowed: Implicit | Given | Erased

private[QuotesImpl] def validTypeFlags: Flags = Private | Protected | Override | Deferred | Final | Infix | Local

end Flags

given FlagsMethods: FlagsMethods with
Expand Down
18 changes: 18 additions & 0 deletions library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3915,6 +3915,24 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
// Keep: `flags` doc aligned with QuotesImpl's `validBindFlags`
def newBind(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol

/** Generate a new type symbol with the given parent, name and type
*
* This symbol starts without an accompanying definition.
* It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing
* this symbol to the TypeDef constructor.
*
* @param parent The owner of the type
* @param name The name of the type
* @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`
* @param tpe The rhs or bounds of the type
* @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol.
* @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be
* direct or indirect children of the reflection context's owner.
*/
@experimental
// Keep: `flags` doc aligned with QuotesImpl's `validTypeFlags`
def newType(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol

/** Definition not available */
def noSymbol: Symbol

Expand Down
10 changes: 10 additions & 0 deletions tests/pos-macros/quoted-sym-newtype/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import scala.quoted.*

inline def testMacro = ${ testImpl }

def testImpl(using Quotes): Expr[Unit] = {
Copy link
Contributor

@jchyb jchyb May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing @experimental here and in def test I believe

import quotes.reflect.*
val sym = Symbol.newType(Symbol.spliceOwner, "mytype", Flags.EmptyFlags, TypeRepr.of[String], Symbol.noSymbol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the compiler, the info of a type symbol can either be a ClassInfo (if we're defining a class) or a TypeBounds (if we're defining a type parameter, a type alias, an abstract type member or an opaque type). So String is not a valid info, it should be TypeAlias(String), but giving the user higher-level methods like newTypeAlias and newTypeBounds would be better.

assert(TypeDef(sym).show == "type mytype = java.lang.String")
'{ () }
}
2 changes: 2 additions & 0 deletions tests/pos-macros/quoted-sym-newtype/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

def test = testMacro
Loading