mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Avoid member attribute cycle in ResolveMacroRequest
If we have a custom attribute on a type that does a qualified lookup into the same type, we need to be able to expand member attribute macros for that type. As such, the check to see if we already have a nominal for the attribute would hit a cycle. Limit this check such that it only applies to local vars, which is the only case where it actually matters. rdar://163961797
This commit is contained in:
@@ -3172,7 +3172,7 @@ bool CustomAttr::shouldPreferPropertyWrapperOverMacro() const {
|
|||||||
// if one exists. This is necessary since we don't properly support peer
|
// if one exists. This is necessary since we don't properly support peer
|
||||||
// declarations in local contexts, so want to use a property wrapper if one
|
// declarations in local contexts, so want to use a property wrapper if one
|
||||||
// exists.
|
// exists.
|
||||||
if (auto *D = owner.getAsDecl()) {
|
if (auto *D = getOwner().getAsDecl()) {
|
||||||
if ((isa<VarDecl>(D) || isa<PatternBindingDecl>(D)) &&
|
if ((isa<VarDecl>(D) || isa<PatternBindingDecl>(D)) &&
|
||||||
D->getDeclContext()->isLocalContext()) {
|
D->getDeclContext()->isLocalContext()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2242,8 +2242,12 @@ ResolveMacroRequest::evaluate(Evaluator &evaluator,
|
|||||||
// So bail out to prevent diagnostics from the contraint system.
|
// So bail out to prevent diagnostics from the contraint system.
|
||||||
if (auto *attr = macroRef.getAttr()) {
|
if (auto *attr = macroRef.getAttr()) {
|
||||||
// If we already resolved this CustomAttr to a nominal, this isn't for a
|
// If we already resolved this CustomAttr to a nominal, this isn't for a
|
||||||
// macro.
|
// macro. This can only currently be the case for property wrappers, so
|
||||||
if (attr->getNominalDecl())
|
// limit the check here to avoid request cycles for member attribute macros
|
||||||
|
// in cases where the attribute refers to a nested type in the type it's
|
||||||
|
// attached to, since the qualified lookup there needs to expand member
|
||||||
|
// attributes.
|
||||||
|
if (attr->shouldPreferPropertyWrapperOverMacro() && attr->getNominalDecl())
|
||||||
return ConcreteDeclRef();
|
return ConcreteDeclRef();
|
||||||
|
|
||||||
auto foundMacros = namelookup::lookupMacros(dc, macroRef.getModuleName(),
|
auto foundMacros = namelookup::lookupMacros(dc, macroRef.getModuleName(),
|
||||||
|
|||||||
10
test/NameLookup/rdar163961797.swift
Normal file
10
test/NameLookup/rdar163961797.swift
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// RUN: %target-typecheck-verify-swift
|
||||||
|
|
||||||
|
// Make sure we don't end up with a request cycle here, since looking up 'S.Actor'
|
||||||
|
// requires expanding member attribute macros for 'S'.
|
||||||
|
@S.Actor
|
||||||
|
struct S {
|
||||||
|
@globalActor actor Actor: GlobalActor {
|
||||||
|
public static let shared = S.Actor()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user