-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Macros] Type-check attached macro arguments. #63154
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
Conversation
Type wrappers were invoking CustomAttrDeclRequest with a decl context of the attached nominal type rather than its decl context, so the request was invoked twice for the same custom attributes with different decl contexts.
invalid macro attributes in `findMacroForCustomAttr`.
@swift-ci please smoke test |
type checking macro attribute arguments into two different requests.
@swift-ci please smoke test |
@@ -3590,7 +3590,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator, | |||
if (auto macro = dyn_cast<MacroDecl>(decl)) { | |||
// Macro can only be used in an expansion. If we end up here, it's | |||
// because we found a macro but are missing the leading '#'. | |||
if (!locator->isForMacroExpansion()) { | |||
if (!(locator->isForMacroExpansion() || locator->getAnchor().isImplicit())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this be replaced with a different locator check to cover attached macros, or... ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was going back and forth between generalizing MacroExpansionExpr
to work for attached macros, or providing "this is an attached macro" through some other mechanism, e.g. a dedicated SolutionApplicationTarget::Kind
. If we decide on a common approach for no-argument macros across attached and freestanding, I think generalizing MacroExpansionExpr
makes the most sense.
llvm::TinyPtrVector<ValueDecl *> macros; | ||
findMacroForCustomAttr(attr, dc, macros); | ||
if (!macros.empty()) | ||
return nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, so MacroOrNominalTypeDecl
will go away again. Sorry for the detour.
/// Resolve a given custom attribute to an attached macro declaration. | ||
class ResolveAttachedMacroRequest | ||
: public SimpleRequest<ResolveAttachedMacroRequest, | ||
MacroDecl *(CustomAttr *, DeclContext *), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this return a ConcreteDeclRef
that points at the MacroDecl
, so we also have the inferred generic arguments? Otherwise, they won't be captured anywhere.
@@ -17,7 +17,7 @@ | |||
// REQUIRES: OS=macosx | |||
|
|||
@attached(accessor) | |||
macro myPropertyWrapper: Void = | |||
macro myPropertyWrapper() = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noted this offline, but we should consider this change in the context of expression macros as well. Perhaps macros should always have argument lists, but can be used without parentheses if all parameters have default arguments.
To type-check macro arguments, we build an overload set from all of the attached macro declarations found in
findMacroForCustomAttr
, and then form aCallExpr
with the overload set as the callee with the custom attribute arguments (or an implicit empty argument list). The concreteDeclRefExpr
written back to the type-checked AST is the resolved macro decl for the given arguments.Note that this change prevents macros from being declared using a
: Void
type annotation, because we always build aCallExpr
to resolve the macro reference; a call to a macro declaration with typeVoid
would result in the errorcannot call value of non-function type 'Void'
.