Skip to content

Macro declarations #62204

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

Merged
merged 21 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8adee85
[Macros] Add support for explicit generic arguments of macros.
DougGregor Nov 18, 2022
7157510
[Macros] Parse macro declarations.
DougGregor Nov 18, 2022
b29fcb4
[Macros] Parse macro declarations fully, and treat them as normal dec…
DougGregor Nov 19, 2022
813dc12
[Macros] Use the external module/type name in lieu of macro registrat…
DougGregor Nov 22, 2022
cc142d4
[Macros] Use the resolved macro for evaluation.
DougGregor Nov 22, 2022
e67c546
[Macros] Resolve in-process macros via external type name.
DougGregor Nov 23, 2022
4ce0834
[Macros] Serialization support for macro declarations.
DougGregor Nov 25, 2022
1a124e7
[Macros] Implement AST printing and module interface generation for m…
DougGregor Nov 25, 2022
3c80b71
[Macros] Fix end location of macro declarations with where clauses
DougGregor Nov 26, 2022
4f823c6
[Macros] Ensure that macros cannot return opaque result types
DougGregor Nov 26, 2022
e2c66cb
[Macros] Check access control and availability
DougGregor Nov 26, 2022
ab9608c
[Macros] Add tests for redeclarations of macros
DougGregor Nov 26, 2022
1a10009
[Macro] Diagnose macros declared in nested scopes
DougGregor Nov 26, 2022
a9ee5dd
[Macros] Don't allow local names to shadow macro names.
DougGregor Nov 26, 2022
af6b30a
[Code completion] Add code completion support for macro expansions.
DougGregor Nov 27, 2022
d9f5aa0
[Mangling] Add a mangling for macro declarations.
DougGregor Nov 27, 2022
bbbc346
[Macros] Treat MacroDecl as a local context, like functions are.
DougGregor Nov 27, 2022
c8819bd
[Indexing] Index macro expansion expressions.
DougGregor Nov 27, 2022
69cdb52
Fix for builds without the Swift Swift parser
DougGregor Nov 27, 2022
e6ed154
Macro tests only run in CI for macOS at the moment
DougGregor Nov 28, 2022
64f2c8e
Address a few comments about the specialization arguments constraint.
DougGregor Nov 28, 2022
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 docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ Entities
entity-spec ::= decl-name label-list? type 'v' ACCESSOR // variable
entity-spec ::= decl-name type 'fp' // generic type parameter
entity-spec ::= decl-name type 'fo' // enum element (currently not used)
entity-spec ::= decl-name label-list? type generic-signature? 'fm' // macro
entity-spec ::= identifier 'Qa' // associated type declaration

ACCESSOR ::= 'm' // materializeForSet
Expand Down
6 changes: 0 additions & 6 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1439,12 +1439,6 @@ class ASTContext final {
/// The declared interface type of Builtin.TheTupleType.
BuiltinTupleType *getBuiltinTupleType();

/// Finds the loaded compiler plugins with the given name.
TinyPtrVector<CompilerPlugin *> getLoadedPlugins(StringRef name);

/// Add a loaded plugin with the given name.
void addLoadedPlugin(StringRef name, CompilerPlugin *plugin);

/// Finds the address of the given symbol. If `libraryHandleHint` is non-null,
/// search within the library.
void *getAddressOfSymbol(const char *name, void *libraryHandleHint = nullptr);
Expand Down
29 changes: 29 additions & 0 deletions include/swift/AST/ASTScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,35 @@ class EnumElementScope : public ASTScopeImpl {
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);
};

class MacroDeclScope final : public ASTScopeImpl {
public:
MacroDecl *const decl;

MacroDeclScope(MacroDecl *e) : decl(e) {}
virtual ~MacroDeclScope() {}

protected:
ASTScopeImpl *expandSpecifically(ScopeCreator &scopeCreator) override;

private:
void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &);

public:
std::string getClassName() const override;
SourceRange
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;

protected:
void printSpecifics(llvm::raw_ostream &out) const override;

public:
virtual NullablePtr<Decl> getDeclIfAny() const override { return decl; }
Decl *getDecl() const { return decl; }

protected:
NullablePtr<const GenericParamList> genericParams() const override;
};

class AbstractStmtScope : public ASTScopeImpl {
public:
SourceRange
Expand Down
48 changes: 7 additions & 41 deletions include/swift/AST/CompilerPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,10 @@ class CompilerPlugin {
// stdlib/toolchain/CompilerPluginSupport.swift.
enum class WitnessTableEntry: unsigned {
ConformanceDescriptor = 0,
// static func _name() -> (UnsafePointer<UInt8>, count: Int8)
Name = 1,
// static func _kind() -> _CompilerPluginKind
Kind = 2,
Kind = 1,
// static func _rewrite(...) -> (UnsafePointer<UInt8>?, count: Int)
Rewrite = 3,
// static func _genericSignature(...) -> (UnsafePointer<UInt8>?, count: Int)
GenericSignature = 4,
// static func _typeSignature(...) -> (UnsafePointer<UInt8>, count: Int)
TypeSignature = 5,
// static func _owningModule(...) -> (UnsafePointer<UInt8>, count: Int)
OwningModule = 6,
// static func _supplementalSignatureModules(...)
// -> (UnsafePointer<UInt8>, count: Int)
SupplementalSignatureModules = 7,
Rewrite = 2,
};

/// The plugin type metadata.
Expand All @@ -77,8 +66,6 @@ class CompilerPlugin {
void *parentLibrary;
/// The witness table proving that the plugin conforms to `_CompilerPlugin`.
const void *witnessTable;
/// The plugin name, aka. result of the `_name()` method.
StringRef name;
/// The plugin's kind, aka. result of the `_kind()` method.
Kind kind;

Expand All @@ -87,14 +74,10 @@ class CompilerPlugin {
return reinterpret_cast<const Func *const *>(witnessTable)[(unsigned)entry];
}

protected:
CompilerPlugin(const void *metadata, void *parentLibrary, ASTContext &ctx);
CompilerPlugin(
const void *metadata, void *parentLibrary, const void *witnessTable);

private:
/// Invoke the `_name` method. The caller assumes ownership of the result
/// string buffer.
StringRef invokeName() const;

/// Invoke the `_kind` method.
Kind invokeKind() const;

Expand All @@ -103,33 +86,16 @@ class CompilerPlugin {
CompilerPlugin(const CompilerPlugin &) = delete;
CompilerPlugin(CompilerPlugin &&) = default;

/// Try to resolve a compiler plugin given the metadata point.
static CompilerPlugin *fromMetatype(const void *metadata, ASTContext &ctx);

/// Invoke the `_rewrite` method. The caller assumes ownership of the result
/// string buffer and diagnostic buffers.
Optional<NullTerminatedStringRef> invokeRewrite(
StringRef targetModuleName, StringRef filePath, StringRef sourceFileText,
CharSourceRange range, ASTContext &ctx,
SmallVectorImpl<Diagnostic> &diagnostics) const;

/// Invoke the `_genericSignature` method. The caller assumes ownership of the
/// result string buffer.
Optional<StringRef> invokeGenericSignature() const;

/// Invoke the `_typeSignature` method. The caller assumes ownership of the
/// result string buffer.
StringRef invokeTypeSignature() const;

/// Invoke the `_owningModule` method. The caller assumes ownership of the
/// result string buffer.
StringRef invokeOwningModule() const;

/// Invoke the `_supplementalSignatureModules` method. The caller assumes
/// ownership of the result string buffer.
StringRef invokeSupplementalSignatureModules() const;

StringRef getName() const {
return name;
}

Kind getKind() const {
return kind;
}
Expand Down
61 changes: 33 additions & 28 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8278,44 +8278,47 @@ class MissingMemberDecl : public Decl {
/// representation in the source code, but are still declarations.
class MacroDecl : public GenericContext, public ValueDecl {
public:
/// The kind of macro, which determines how it can be used in source code.
enum Kind: uint8_t {
/// An expression macro.
Expression,
};
/// The location of the 'macro' keyword.
SourceLoc macroLoc;

/// Describes how the macro is implemented.
enum class ImplementationKind: uint8_t {
/// The macro is built-in to the compiler, linked against the same
/// underlying syntax tree libraries.
Builtin,
/// The parameter list for a function-like macro.
ParameterList *parameterList;

/// The macro was defined in a compiler plugin.
Plugin,
};
/// Where the '->' or ':' is located, for a function- or value-like macro,
/// respectively.
SourceLoc arrowOrColonLoc;

/// The kind of macro.
const Kind kind;
/// The result type.
TypeLoc resultType;

/// How the macro is implemented.
const ImplementationKind implementationKind;
/// The module name for the external macro definition.
Identifier externalModuleName;

/// Supplemental modules that should be imported when
const ArrayRef<ModuleDecl *> supplementalSignatureModules;
/// The location of the module name for the external macro definition.
SourceLoc externalModuleNameLoc;

/// An opaque handle to the representation of the macro.
void * const opaqueHandle;
/// The type name for the external macro definition.
Identifier externalMacroTypeName;

public:
MacroDecl(
Kind kind, ImplementationKind implementationKind, Identifier name,
ModuleDecl *owningModule,
ArrayRef<ModuleDecl *> supplementalSignatureModules,
void *opaqueHandle
);
/// The location of the type name for the external macro definition.
SourceLoc externalMacroTypeNameLoc;

MacroDecl(SourceLoc macroLoc, DeclName name, SourceLoc nameLoc,
GenericParamList *genericParams,
ParameterList *parameterList,
SourceLoc arrowOrColonLoc,
TypeRepr *resultType,
Identifier externalModuleName,
SourceLoc externalModuleNameLoc,
Identifier externalMacroTypeName,
SourceLoc externalMacroTypeNameLoc,
DeclContext *parent);

SourceRange getSourceRange() const;

/// Retrieve the interface type produced when expanding this macro.
Type getResultInterfaceType() const;

static bool classof(const DeclContext *C) {
if (auto D = C->getAsDecl())
return classof(D);
Expand Down Expand Up @@ -8479,6 +8482,8 @@ inline bool ValueDecl::hasCurriedSelf() const {
inline bool ValueDecl::hasParameterList() const {
if (auto *eed = dyn_cast<EnumElementDecl>(this))
return eed->hasAssociatedValues();
if (auto *macro = dyn_cast<MacroDecl>(this))
return macro->parameterList != nullptr;
return isa<AbstractFunctionDecl>(this) || isa<SubscriptDecl>(this);
}

Expand Down
6 changes: 3 additions & 3 deletions include/swift/AST/DeclContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ enum class DeclContextKind : unsigned {
EnumElementDecl,
AbstractFunctionDecl,
SerializedLocal,
Last_LocalDeclContextKind = SerializedLocal,
MacroDecl,
Last_LocalDeclContextKind = MacroDecl,

Module,
FileUnit,
GenericTypeDecl,
ExtensionDecl,
MacroDecl,
Last_DeclContextKind = MacroDecl
Last_DeclContextKind = ExtensionDecl
};

/// Kinds of DeclContexts after deserialization.
Expand Down
4 changes: 0 additions & 4 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -478,10 +478,6 @@ REMARK(warning_in_access_notes_file,none,

WARNING(compiler_plugin_not_loaded,none,
"compiler plugin not loaded: %0; loader error: %1", (StringRef, StringRef))
WARNING(compiler_plugin_missing_macro_declaration,none,
"compiler plugin module '%0' (in %1) is missing a top-level computed "
"property 'public var %2: [Any.Type]' to declare all macros; "
"undeclared macros will be ignored", (StringRef, StringRef, StringRef))

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
18 changes: 17 additions & 1 deletion include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -1999,8 +1999,24 @@ ERROR(foreign_diagnostic,none,
"%0", (StringRef))

//------------------------------------------------------------------------------
// MARK: macro expansion
// MARK: macros
//------------------------------------------------------------------------------
ERROR(expected_macro_value_type,PointsToFirstBadToken,
"expected macro value type following ':'", ())
ERROR(no_default_arg_macro,none,
"default arguments are not allowed in macros", ())
ERROR(expected_lparen_macro,PointsToFirstBadToken,
"expected '(' for macro parameters or ':' for a value-like macro", ())
ERROR(expected_type_macro_result,PointsToFirstBadToken,
"expected macro result type", ())
ERROR(macro_decl_expected_equal,PointsToFirstBadToken,
"expected '=' to introduce external macro name", ())
ERROR(macro_decl_expected_macro_module,PointsToFirstBadToken,
"expected external macro name", ())
ERROR(macro_decl_expected_period,PointsToFirstBadToken,
"expected '.' between external macro module and type name", ())
ERROR(macro_decl_expected_macro_type,PointsToFirstBadToken,
"expected external macro type name", ())

ERROR(macro_expansion_expr_expected_macro_identifier,none,
"expected a macro identifier for a pound literal expression", ())
Expand Down
27 changes: 24 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -6742,12 +6742,33 @@ ERROR(expected_macro_expansion_expr,PointsToFirstBadToken,
ERROR(macro_undefined,PointsToFirstBadToken,
"macro %0 is undefined; use `-load-plugin-library` to specify dynamic "
"libraries that contain this macro", (Identifier))
ERROR(external_macro_not_found,none,
"external implementation struct '%0.%1' could not be found in for "
"macro %2; the type must be public and provided via "
"'-load-plugin-library'", (StringRef, StringRef, DeclName))
NOTE(macro_note, none,
"macro %0: %1", (Identifier, StringRef))
"%1 (in macro %0)", (DeclName, StringRef))
WARNING(macro_warning, none,
"macro %0: %1", (Identifier, StringRef))
"%1 (in macro %0)", (DeclName, StringRef))
ERROR(macro_error, none,
"macro %0: %1", (Identifier, StringRef))
"%1 (in macro %0)", (DeclName, StringRef))
ERROR(macro_type_access,none,
"macro %select{must be declared "
"%select{private|fileprivate|internal|%error|%error}1"
"|cannot be declared "
"%select{in this context|fileprivate|internal|public|open}1}0 "
"because its %select{parameter|result type}3 uses "
"%select{a private|a fileprivate|an internal|%error|%error}2 type",
(bool, AccessLevel, AccessLevel, bool))
WARNING(macro_type_access_warn,none,
"macro %select{should be declared "
"%select{private|fileprivate|internal|%error|%error}1"
"|should not be declared %select{in this context|fileprivate|internal|public|open}1}0 "
"because its %select{parameter|result type}3 uses "
"%select{a private|a fileprivate|an internal|%error|%error}2 type",
(bool, AccessLevel, AccessLevel, bool))
ERROR(macro_in_nested,none,
"macro %0 can only be declared at file scope", (DeclName))

//------------------------------------------------------------------------------
// MARK: Move Only Errors
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6021,6 +6021,9 @@ class MacroExpansionExpr final : public Expr {
ArgumentList *ArgList;
Expr *Rewritten;

/// The referenced macro.
ConcreteDeclRef macroRef;

public:
explicit MacroExpansionExpr(SourceLoc poundLoc, DeclNameRef macroName,
DeclNameLoc macroNameLoc,
Expand Down Expand Up @@ -6053,6 +6056,9 @@ class MacroExpansionExpr final : public Expr {

SourceLoc getLoc() const { return PoundLoc; }

ConcreteDeclRef getMacroRef() const { return macroRef; }
void setMacroRef(ConcreteDeclRef ref) { macroRef = ref; }

SourceRange getSourceRange() const;

static bool classof(const Expr *E) {
Expand Down
Loading