Skip to content

Commit b249503

Browse files
committed
AST: Introduce @_disallowFeatureSuppression attribute.
This attribute is the inverse of the existing `@_allowFeatureSuppression` attribute. Part of rdar://125138945
1 parent 5068579 commit b249503

File tree

11 files changed

+102
-40
lines changed

11 files changed

+102
-40
lines changed

Diff for: include/swift/AST/ASTBridging.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -483,12 +483,13 @@ BridgedAlignmentAttr_createParsed(BridgedASTContext cContext,
483483
BridgedSourceLoc cAtLoc,
484484
BridgedSourceRange cRange, size_t cValue);
485485

486-
SWIFT_NAME("BridgedAllowFeatureSuppressionAttr.createParsed(_:atLoc:range:features:)")
486+
SWIFT_NAME("BridgedAllowFeatureSuppressionAttr.createParsed(_:atLoc:range:inverted:features:)")
487487
BridgedAllowFeatureSuppressionAttr
488488
BridgedAllowFeatureSuppressionAttr_createParsed(
489489
BridgedASTContext cContext,
490490
BridgedSourceLoc cAtLoc,
491491
BridgedSourceRange cRange,
492+
bool inverted,
492493
BridgedArrayRef cFeatures);
493494

494495
SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)")

Diff for: include/swift/AST/Attr.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,11 @@ class DeclAttribute : public AttributeBase {
192192
isUnsafe : 1
193193
);
194194

195-
SWIFT_INLINE_BITFIELD_FULL(AllowFeatureSuppressionAttr, DeclAttribute, 32,
195+
SWIFT_INLINE_BITFIELD_FULL(AllowFeatureSuppressionAttr, DeclAttribute, 1+31,
196196
: NumPadBits,
197-
NumFeatures : 32
197+
Inverted : 1,
198+
199+
NumFeatures : 31
198200
);
199201
} Bits;
200202
// clang-format on
@@ -2628,14 +2630,17 @@ class AllowFeatureSuppressionAttr final
26282630
private llvm::TrailingObjects<AllowFeatureSuppressionAttr, Identifier> {
26292631
friend TrailingObjects;
26302632

2631-
/// Create an implicit @objc attribute with the given (optional) name.
2632-
AllowFeatureSuppressionAttr(SourceLoc atLoc, SourceRange range,
2633-
bool implicit, ArrayRef<Identifier> features);
2633+
AllowFeatureSuppressionAttr(SourceLoc atLoc, SourceRange range, bool implicit,
2634+
bool inverted, ArrayRef<Identifier> features);
2635+
26342636
public:
26352637
static AllowFeatureSuppressionAttr *create(ASTContext &ctx, SourceLoc atLoc,
26362638
SourceRange range, bool implicit,
2639+
bool inverted,
26372640
ArrayRef<Identifier> features);
26382641

2642+
bool getInverted() const { return Bits.AllowFeatureSuppressionAttr.Inverted; }
2643+
26392644
ArrayRef<Identifier> getSuppressedFeatures() const {
26402645
return {getTrailingObjects<Identifier>(),
26412646
Bits.AllowFeatureSuppressionAttr.NumFeatures};

Diff for: include/swift/AST/DeclAttr.def

+1
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ SIMPLE_DECL_ATTR(_noObjCBridging, NoObjCBridging,
489489
DECL_ATTR(_allowFeatureSuppression, AllowFeatureSuppression,
490490
OnAnyDecl | UserInaccessible | NotSerialized | ABIStableToAdd | APIStableToAdd | ABIStableToRemove | APIStableToRemove,
491491
157)
492+
DECL_ATTR_ALIAS(_disallowFeatureSuppression, AllowFeatureSuppression)
492493
SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics,
493494
OnAbstractFunction | OnSubscript | OnVar | OnExtension | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
494495
158)

Diff for: include/swift/Basic/Features.def

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
// imply the existence of earlier features. (This only needs to apply to
3535
// suppressible features.)
3636
//
37+
// Sometimes, certain declarations will conflict with existing declarations
38+
// when printed with a suppressible feature disabled. The attribute
39+
// @_disallowFeatureSuppression can be used to suppress feature suppression on
40+
// a particular declaration.
41+
//
3742
// If suppressing a feature in general is problematic, but it's okay to
3843
// suppress it for specific declarations, the feature can be made
3944
// conditionally suppressible. Declarations opt in to suppression with

Diff for: include/swift/Parse/Parser.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,8 @@ class Parser {
11571157
std::optional<AccessLevel> &Visibility);
11581158

11591159
ParserResult<AllowFeatureSuppressionAttr>
1160-
parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc);
1160+
parseAllowFeatureSuppressionAttribute(bool inverted, SourceLoc atLoc,
1161+
SourceLoc loc);
11611162

11621163
/// Parse the @attached or @freestanding attribute that specifies a macro
11631164
/// role.

Diff for: lib/AST/ASTBridging.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,14 @@ BridgedAllowFeatureSuppressionAttr
433433
BridgedAllowFeatureSuppressionAttr_createParsed(BridgedASTContext cContext,
434434
BridgedSourceLoc cAtLoc,
435435
BridgedSourceRange cRange,
436+
bool inverted,
436437
BridgedArrayRef cFeatures) {
437438
SmallVector<Identifier> features;
438439
for (auto elem : cFeatures.unbridged<BridgedIdentifier>())
439440
features.push_back(elem.unbridged());
440-
return AllowFeatureSuppressionAttr::create(cContext.unbridged(),
441-
cAtLoc.unbridged(), cRange.unbridged(), /*implicit*/ false, features);
441+
return AllowFeatureSuppressionAttr::create(
442+
cContext.unbridged(), cAtLoc.unbridged(), cRange.unbridged(),
443+
/*implicit*/ false, inverted, features);
442444
}
443445

444446
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,

Diff for: lib/AST/Attr.cpp

+24-17
Original file line numberDiff line numberDiff line change
@@ -1275,14 +1275,17 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
12751275
Printer << "(" << cast<AlignmentAttr>(this)->getValue() << ")";
12761276
break;
12771277

1278-
case DeclAttrKind::AllowFeatureSuppression:
1279-
Printer.printAttrName("@_allowFeatureSuppression");
1278+
case DeclAttrKind::AllowFeatureSuppression: {
1279+
auto Attr = cast<AllowFeatureSuppressionAttr>(this);
1280+
Printer.printAttrName(Attr->getInverted() ? "@_disallowFeatureSuppression"
1281+
: "@_allowFeatureSuppression");
12801282
Printer << "(";
1281-
interleave(cast<AllowFeatureSuppressionAttr>(this)->getSuppressedFeatures(),
1282-
[&](Identifier ident) { Printer << ident; },
1283-
[&] { Printer << ", "; });
1283+
interleave(
1284+
Attr->getSuppressedFeatures(),
1285+
[&](Identifier ident) { Printer << ident; }, [&] { Printer << ", "; });
12841286
Printer << ")";
12851287
break;
1288+
}
12861289

12871290
case DeclAttrKind::SILGenName:
12881291
Printer.printAttrName("@_silgen_name");
@@ -1947,7 +1950,11 @@ StringRef DeclAttribute::getAttrName() const {
19471950
case DeclAttrKind::Extern:
19481951
return "_extern";
19491952
case DeclAttrKind::AllowFeatureSuppression:
1950-
return "_allowFeatureSuppression";
1953+
if (cast<AllowFeatureSuppressionAttr>(this)->getInverted()) {
1954+
return "_disallowFeatureSuppression";
1955+
} else {
1956+
return "_allowFeatureSuppression";
1957+
}
19511958
}
19521959
llvm_unreachable("bad DeclAttrKind");
19531960
}
@@ -2932,24 +2939,24 @@ StorageRestrictionsAttr::getAccessesProperties(AccessorDecl *attachedTo) const {
29322939
{});
29332940
}
29342941

2935-
AllowFeatureSuppressionAttr::AllowFeatureSuppressionAttr(SourceLoc atLoc,
2936-
SourceRange range,
2937-
bool implicit,
2938-
ArrayRef<Identifier> features)
2939-
: DeclAttribute(DeclAttrKind::AllowFeatureSuppression,
2940-
atLoc, range, implicit) {
2942+
AllowFeatureSuppressionAttr::AllowFeatureSuppressionAttr(
2943+
SourceLoc atLoc, SourceRange range, bool implicit, bool inverted,
2944+
ArrayRef<Identifier> features)
2945+
: DeclAttribute(DeclAttrKind::AllowFeatureSuppression, atLoc, range,
2946+
implicit) {
2947+
Bits.AllowFeatureSuppressionAttr.Inverted = inverted;
29412948
Bits.AllowFeatureSuppressionAttr.NumFeatures = features.size();
29422949
std::uninitialized_copy(features.begin(), features.end(),
29432950
getTrailingObjects<Identifier>());
29442951
}
29452952

2946-
AllowFeatureSuppressionAttr *
2947-
AllowFeatureSuppressionAttr::create(ASTContext &ctx, SourceLoc atLoc,
2948-
SourceRange range, bool implicit,
2949-
ArrayRef<Identifier> features) {
2953+
AllowFeatureSuppressionAttr *AllowFeatureSuppressionAttr::create(
2954+
ASTContext &ctx, SourceLoc atLoc, SourceRange range, bool implicit,
2955+
bool inverted, ArrayRef<Identifier> features) {
29502956
unsigned size = totalSizeToAlloc<Identifier>(features.size());
29512957
auto *mem = ctx.Allocate(size, alignof(AllowFeatureSuppressionAttr));
2952-
return new (mem) AllowFeatureSuppressionAttr(atLoc, range, implicit, features);
2958+
return new (mem)
2959+
AllowFeatureSuppressionAttr(atLoc, range, implicit, inverted, features);
29532960
}
29542961

29552962
void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {

Diff for: lib/AST/FeatureSet.cpp

+22-5
Original file line numberDiff line numberDiff line change
@@ -695,9 +695,14 @@ void FeatureSet::collectSuppressibleFeature(Feature feature,
695695
operation == Insert);
696696
}
697697

698-
static bool shouldSuppressFeature(StringRef featureName, Decl *decl) {
698+
static bool hasFeatureSuppressionAttribute(Decl *decl, StringRef featureName,
699+
bool inverted) {
699700
auto attr = decl->getAttrs().getAttribute<AllowFeatureSuppressionAttr>();
700-
if (!attr) return false;
701+
if (!attr)
702+
return false;
703+
704+
if (attr->getInverted() != inverted)
705+
return false;
701706

702707
for (auto suppressedFeature : attr->getSuppressedFeatures()) {
703708
if (suppressedFeature.is(featureName))
@@ -707,6 +712,14 @@ static bool shouldSuppressFeature(StringRef featureName, Decl *decl) {
707712
return false;
708713
}
709714

715+
static bool disallowFeatureSuppression(StringRef featureName, Decl *decl) {
716+
return hasFeatureSuppressionAttribute(decl, featureName, true);
717+
}
718+
719+
static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
720+
return hasFeatureSuppressionAttribute(decl, featureName, false);
721+
}
722+
710723
/// Go through all the features used by the given declaration and
711724
/// either add or remove them to this set.
712725
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
@@ -716,11 +729,15 @@ void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
716729
if (usesFeature##FeatureName(decl)) \
717730
collectRequiredFeature(Feature::FeatureName, operation);
718731
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
719-
if (usesFeature##FeatureName(decl)) \
720-
collectSuppressibleFeature(Feature::FeatureName, operation);
732+
if (usesFeature##FeatureName(decl)) { \
733+
if (disallowFeatureSuppression(#FeatureName, decl)) \
734+
collectRequiredFeature(Feature::FeatureName, operation); \
735+
else \
736+
collectSuppressibleFeature(Feature::FeatureName, operation); \
737+
}
721738
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
722739
if (usesFeature##FeatureName(decl)) { \
723-
if (shouldSuppressFeature(#FeatureName, decl)) \
740+
if (allowFeatureSuppression(#FeatureName, decl)) \
724741
collectSuppressibleFeature(Feature::FeatureName, operation); \
725742
else \
726743
collectRequiredFeature(Feature::FeatureName, operation); \

Diff for: lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ extension ASTGenVisitor {
345345
return nil
346346
}
347347

348+
let inverted: Bool
349+
switch node.attributeName {
350+
case "_allowFeatureSuppression":
351+
inverted = false
352+
case "_disallowFeatureSuppression":
353+
inverted = true
354+
default:
355+
return nil
356+
}
357+
348358
let features = args.compactMap(in: self) { arg -> BridgedIdentifier? in
349359
guard arg.label == nil,
350360
let declNameExpr = arg.expression.as(DeclReferenceExprSyntax.self),
@@ -361,6 +371,7 @@ extension ASTGenVisitor {
361371
self.ctx,
362372
atLoc: self.generateSourceLoc(node.atSign),
363373
range: self.generateSourceRange(node),
374+
inverted: inverted,
364375
features: features)
365376
}
366377

@@ -388,7 +399,7 @@ extension ASTGenVisitor {
388399

389400
func generateAvailableAttr(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] {
390401
guard
391-
// `@_OriginallyDefinedIn` has special argument list syntax.
402+
// `@available` has special argument list syntax.
392403
let args = node.arguments?.as(AvailabilityArgumentListSyntax.self)
393404
else {
394405
// TODO: Diagnose.

Diff for: lib/Parse/ParseDecl.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -2461,8 +2461,10 @@ Parser::parseDocumentationAttribute(SourceLoc atLoc, SourceLoc loc) {
24612461
}
24622462

24632463
ParserResult<AllowFeatureSuppressionAttr>
2464-
Parser::parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc) {
2465-
StringRef attrName = "_allowFeatureSuppression";
2464+
Parser::parseAllowFeatureSuppressionAttribute(bool inverted, SourceLoc atLoc,
2465+
SourceLoc loc) {
2466+
StringRef attrName =
2467+
inverted ? "_disallowFeatureSuppression" : "_allowFeatureSuppression";
24662468

24672469
SmallVector<Identifier, 4> features;
24682470
SourceRange parensRange;
@@ -2479,9 +2481,9 @@ Parser::parseAllowFeatureSuppressionAttribute(SourceLoc atLoc, SourceLoc loc) {
24792481
return status;
24802482

24812483
auto range = SourceRange(loc, parensRange.End);
2482-
return makeParserResult(
2483-
AllowFeatureSuppressionAttr::create(Context, loc, range, /*implicit*/ false,
2484-
features));
2484+
return makeParserResult(AllowFeatureSuppressionAttr::create(
2485+
Context, loc, range, /*implicit*/ false, /*inverted*/ inverted,
2486+
features));
24852487
}
24862488

24872489
static std::optional<MacroIntroducedDeclNameKind>
@@ -3900,7 +3902,8 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
39003902
break;
39013903
}
39023904
case DeclAttrKind::AllowFeatureSuppression: {
3903-
auto Attr = parseAllowFeatureSuppressionAttribute(AtLoc, Loc);
3905+
auto inverted = (AttrName == "_disallowFeatureSuppression");
3906+
auto Attr = parseAllowFeatureSuppressionAttribute(inverted, AtLoc, Loc);
39043907
Status |= Attr;
39053908
if (Attr.isNonNull())
39063909
Attributes.add(Attr.get());

Diff for: test/ModuleInterface/retroactive-conformances.swift

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s
2-
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface)
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name Test
2+
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name Test
33
// RUN: %FileCheck %s < %t.swiftinterface
44

55
// CHECK: #if compiler(>=5.3) && $RetroactiveAttribute
@@ -20,3 +20,12 @@
2020
extension Int: @retroactive Identifiable {
2121
public var id: Int { self }
2222
}
23+
24+
// CHECK: #if compiler(>=5.3) && $RetroactiveAttribute
25+
// CHECK: extension Swift.String : @retroactive Swift.Identifiable {
26+
// CHECK-NOT: #else
27+
// CHECK: #endif
28+
@_disallowFeatureSuppression(RetroactiveAttribute)
29+
extension String: @retroactive Identifiable {
30+
public var id: String { self }
31+
}

0 commit comments

Comments
 (0)