Skip to content

Commit 24826e0

Browse files
authored
Merge pull request #29775 from hborla/parse-type-eraser-attribute
[Parse] Add an attribute for typeEraser.
2 parents 6d20882 + ffba71b commit 24826e0

File tree

10 files changed

+86
-0
lines changed

10 files changed

+86
-0
lines changed

include/swift/AST/Attr.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ SIMPLE_DECL_ATTR(_inheritsConvenienceInitializers,
519519
APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove,
520520
93)
521521

522+
DECL_ATTR(_typeEraser, TypeEraser,
523+
OnProtocol | UserInaccessible | NotSerialized |
524+
ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove,
525+
94)
526+
522527
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
523528
OnFunc |
524529
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,

include/swift/AST/Attr.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,21 @@ class DynamicReplacementAttr final
11081108
}
11091109
};
11101110

1111+
/// The \c @_typeEraser(TypeEraserType) attribute.
1112+
class TypeEraserAttr final : public DeclAttribute {
1113+
TypeLoc TypeEraserLoc;
1114+
public:
1115+
TypeEraserAttr(SourceLoc atLoc, SourceRange range, TypeLoc typeEraserLoc)
1116+
: DeclAttribute(DAK_TypeEraser, atLoc, range, /*Implicit=*/false),
1117+
TypeEraserLoc(typeEraserLoc) {}
1118+
1119+
const TypeLoc &getTypeEraserLoc() const { return TypeEraserLoc; }
1120+
1121+
static bool classof(const DeclAttribute *DA) {
1122+
return DA->getKind() == DAK_TypeEraser;
1123+
}
1124+
};
1125+
11111126
/// Represents any sort of access control modifier.
11121127
class AbstractAccessControlAttr : public DeclAttribute {
11131128
protected:

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,11 @@ ERROR(attr_dynamic_replacement_expected_for,none,
14901490
ERROR(attr_dynamic_replacement_expected_colon,none,
14911491
"expected ':' after @_dynamicReplacement(for", ())
14921492

1493+
ERROR(attr_type_eraser_expected_type_name,none,
1494+
"expected a type name in @_typeEraser()", ())
1495+
ERROR(attr_type_eraser_expected_rparen,none,
1496+
"expected ')' after type name for @_typeEraser", ())
1497+
14931498
ERROR(attr_private_import_expected_rparen,none,
14941499
"expected ')' after function name for @_private", ())
14951500
ERROR(attr_private_import_expected_sourcefile, none,

lib/AST/Attr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,8 @@ StringRef DeclAttribute::getAttrName() const {
10941094
return "objc";
10951095
case DAK_DynamicReplacement:
10961096
return "_dynamicReplacement";
1097+
case DAK_TypeEraser:
1098+
return "_typeEraser";
10971099
case DAK_PrivateImport:
10981100
return "_private";
10991101
case DAK_RestatedObjCConformance:

lib/Parse/ParseDecl.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,37 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
22002200
break;
22012201
}
22022202

2203+
case DAK_TypeEraser: {
2204+
// Parse leading '('
2205+
if (Tok.isNot(tok::l_paren)) {
2206+
diagnose(Loc, diag::attr_expected_lparen, AttrName,
2207+
DeclAttribute::isDeclModifier(DK));
2208+
return false;
2209+
}
2210+
2211+
SourceLoc LParenLoc = consumeToken(tok::l_paren);
2212+
ParserResult<TypeRepr> ErasedType;
2213+
bool invalid = false;
2214+
{
2215+
// Parse type-eraser type
2216+
SyntaxParsingContext ContentContext(SyntaxContext, SyntaxKind::Type);
2217+
ErasedType = parseType(diag::attr_type_eraser_expected_type_name);
2218+
invalid = ErasedType.hasCodeCompletion() || ErasedType.isNull();
2219+
}
2220+
2221+
// Parse matching ')'
2222+
SourceLoc RParenLoc;
2223+
invalid |= parseMatchingToken(tok::r_paren, RParenLoc,
2224+
diag::attr_type_eraser_expected_rparen,
2225+
LParenLoc);
2226+
if (invalid)
2227+
return false;
2228+
2229+
Attributes.add(new (Context)
2230+
TypeEraserAttr(AtLoc, {Loc, RParenLoc}, ErasedType.get()));
2231+
break;
2232+
}
2233+
22032234
case DAK_Specialize: {
22042235
if (Tok.isNot(tok::l_paren)) {
22052236
diagnose(Loc, diag::attr_expected_lparen, AttrName,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
108108
IGNORED_ATTR(StaticInitializeObjCMetadata)
109109
IGNORED_ATTR(SynthesizedProtocol)
110110
IGNORED_ATTR(Testable)
111+
IGNORED_ATTR(TypeEraser)
111112
IGNORED_ATTR(WeakLinked)
112113
IGNORED_ATTR(PrivateImport)
113114
IGNORED_ATTR(DisfavoredOverload)

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,7 @@ namespace {
14341434
UNINTERESTING_ATTR(Convenience)
14351435
UNINTERESTING_ATTR(Semantics)
14361436
UNINTERESTING_ATTR(SetterAccess)
1437+
UNINTERESTING_ATTR(TypeEraser)
14371438
UNINTERESTING_ATTR(HasStorage)
14381439
UNINTERESTING_ATTR(UIApplicationMain)
14391440
UNINTERESTING_ATTR(UsableFromInline)

lib/Serialization/ModuleFormat.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,6 +1846,12 @@ namespace decls_block {
18461846
BCArray<IdentifierIDField>
18471847
>;
18481848

1849+
using TypeEraserDeclAttrLayout = BCRecordLayout<
1850+
TypeEraser_DECL_ATTR,
1851+
BCFixed<1>, // implicit flag
1852+
TypeIDField // type eraser type
1853+
>;
1854+
18491855
using CustomDeclAttrLayout = BCRecordLayout<
18501856
Custom_DECL_ATTR,
18511857
BCFixed<1>, // implicit flag

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
21562156
case DAK_RestatedObjCConformance:
21572157
case DAK_ClangImporterSynthesizedType:
21582158
case DAK_PrivateImport:
2159+
case DAK_TypeEraser:
21592160
llvm_unreachable("cannot serialize attribute");
21602161

21612162
case DAK_Count:

test/attr/typeEraser.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-frontend -typecheck %s -verify
2+
3+
class AnyP: P1 {}
4+
5+
@_typeEraser(AnyP) // okay
6+
protocol P1 {}
7+
8+
@_typeEraser // expected-error {{expected '(' in '_typeEraser' attribute}}
9+
protocol P2 {}
10+
11+
@_typeEraser() // expected-error {{expected a type name in @_typeEraser()}}
12+
protocol P3 {}
13+
14+
@_typeEraser(AnyP // expected-note {{to match this opening '('}}
15+
protocol P4 {} // expected-error {{expected ')' after type name for @_typeEraser}}
16+
17+
@_typeEraser(AnyP) // expected-error {{@_typeEraser may only be used on 'protocol' declarations}}
18+
func notAProtocol() {}
19+

0 commit comments

Comments
 (0)