mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Parse] Add an attribute for typeEraser.
This will be used for compiler-driven type erasure for dynamic replacement of functions with an opaque return type. For now, just parse the attribute and ignore it.
This commit is contained in:
@@ -519,6 +519,11 @@ SIMPLE_DECL_ATTR(_inheritsConvenienceInitializers,
|
|||||||
APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove,
|
APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove,
|
||||||
93)
|
93)
|
||||||
|
|
||||||
|
DECL_ATTR(_typeEraser, TypeEraser,
|
||||||
|
OnProtocol | UserInaccessible | NotSerialized |
|
||||||
|
ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove,
|
||||||
|
94)
|
||||||
|
|
||||||
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
|
SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction,
|
||||||
OnFunc |
|
OnFunc |
|
||||||
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
|
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
|
||||||
|
|||||||
@@ -1108,6 +1108,21 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The \c @_typeEraser(TypeEraserType) attribute.
|
||||||
|
class TypeEraserAttr final : public DeclAttribute {
|
||||||
|
TypeLoc TypeEraserLoc;
|
||||||
|
public:
|
||||||
|
TypeEraserAttr(SourceLoc atLoc, SourceRange range, TypeLoc typeEraserLoc)
|
||||||
|
: DeclAttribute(DAK_TypeEraser, atLoc, range, /*Implicit=*/false),
|
||||||
|
TypeEraserLoc(typeEraserLoc) {}
|
||||||
|
|
||||||
|
const TypeLoc &getTypeEraserLoc() const { return TypeEraserLoc; }
|
||||||
|
|
||||||
|
static bool classof(const DeclAttribute *DA) {
|
||||||
|
return DA->getKind() == DAK_TypeEraser;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Represents any sort of access control modifier.
|
/// Represents any sort of access control modifier.
|
||||||
class AbstractAccessControlAttr : public DeclAttribute {
|
class AbstractAccessControlAttr : public DeclAttribute {
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -1488,6 +1488,11 @@ ERROR(attr_dynamic_replacement_expected_for,none,
|
|||||||
ERROR(attr_dynamic_replacement_expected_colon,none,
|
ERROR(attr_dynamic_replacement_expected_colon,none,
|
||||||
"expected ':' after @_dynamicReplacement(for", ())
|
"expected ':' after @_dynamicReplacement(for", ())
|
||||||
|
|
||||||
|
ERROR(attr_type_eraser_expected_type_name,none,
|
||||||
|
"expected a type name in @_typeEraser()", ())
|
||||||
|
ERROR(attr_type_eraser_expected_rparen,none,
|
||||||
|
"expected ')' after type name for @_typeEraser", ())
|
||||||
|
|
||||||
ERROR(attr_private_import_expected_rparen,none,
|
ERROR(attr_private_import_expected_rparen,none,
|
||||||
"expected ')' after function name for @_private", ())
|
"expected ')' after function name for @_private", ())
|
||||||
ERROR(attr_private_import_expected_sourcefile, none,
|
ERROR(attr_private_import_expected_sourcefile, none,
|
||||||
|
|||||||
@@ -1094,6 +1094,8 @@ StringRef DeclAttribute::getAttrName() const {
|
|||||||
return "objc";
|
return "objc";
|
||||||
case DAK_DynamicReplacement:
|
case DAK_DynamicReplacement:
|
||||||
return "_dynamicReplacement";
|
return "_dynamicReplacement";
|
||||||
|
case DAK_TypeEraser:
|
||||||
|
return "_typeEraser";
|
||||||
case DAK_PrivateImport:
|
case DAK_PrivateImport:
|
||||||
return "_private";
|
return "_private";
|
||||||
case DAK_RestatedObjCConformance:
|
case DAK_RestatedObjCConformance:
|
||||||
|
|||||||
@@ -2175,6 +2175,37 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DAK_TypeEraser: {
|
||||||
|
// Parse leading '('
|
||||||
|
if (Tok.isNot(tok::l_paren)) {
|
||||||
|
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||||
|
DeclAttribute::isDeclModifier(DK));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceLoc LParenLoc = consumeToken(tok::l_paren);
|
||||||
|
ParserResult<TypeRepr> ErasedType;
|
||||||
|
bool invalid = false;
|
||||||
|
{
|
||||||
|
// Parse type-eraser type
|
||||||
|
SyntaxParsingContext ContentContext(SyntaxContext, SyntaxKind::Type);
|
||||||
|
ErasedType = parseType(diag::attr_type_eraser_expected_type_name);
|
||||||
|
invalid = ErasedType.hasCodeCompletion() || ErasedType.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse matching ')'
|
||||||
|
SourceLoc RParenLoc;
|
||||||
|
invalid |= parseMatchingToken(tok::r_paren, RParenLoc,
|
||||||
|
diag::attr_type_eraser_expected_rparen,
|
||||||
|
LParenLoc);
|
||||||
|
if (invalid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Attributes.add(new (Context)
|
||||||
|
TypeEraserAttr(AtLoc, {Loc, RParenLoc}, ErasedType.get()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case DAK_Specialize: {
|
case DAK_Specialize: {
|
||||||
if (Tok.isNot(tok::l_paren)) {
|
if (Tok.isNot(tok::l_paren)) {
|
||||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ public:
|
|||||||
IGNORED_ATTR(StaticInitializeObjCMetadata)
|
IGNORED_ATTR(StaticInitializeObjCMetadata)
|
||||||
IGNORED_ATTR(SynthesizedProtocol)
|
IGNORED_ATTR(SynthesizedProtocol)
|
||||||
IGNORED_ATTR(Testable)
|
IGNORED_ATTR(Testable)
|
||||||
|
IGNORED_ATTR(TypeEraser)
|
||||||
IGNORED_ATTR(WeakLinked)
|
IGNORED_ATTR(WeakLinked)
|
||||||
IGNORED_ATTR(PrivateImport)
|
IGNORED_ATTR(PrivateImport)
|
||||||
IGNORED_ATTR(DisfavoredOverload)
|
IGNORED_ATTR(DisfavoredOverload)
|
||||||
|
|||||||
@@ -1434,6 +1434,7 @@ namespace {
|
|||||||
UNINTERESTING_ATTR(Convenience)
|
UNINTERESTING_ATTR(Convenience)
|
||||||
UNINTERESTING_ATTR(Semantics)
|
UNINTERESTING_ATTR(Semantics)
|
||||||
UNINTERESTING_ATTR(SetterAccess)
|
UNINTERESTING_ATTR(SetterAccess)
|
||||||
|
UNINTERESTING_ATTR(TypeEraser)
|
||||||
UNINTERESTING_ATTR(HasStorage)
|
UNINTERESTING_ATTR(HasStorage)
|
||||||
UNINTERESTING_ATTR(UIApplicationMain)
|
UNINTERESTING_ATTR(UIApplicationMain)
|
||||||
UNINTERESTING_ATTR(UsableFromInline)
|
UNINTERESTING_ATTR(UsableFromInline)
|
||||||
|
|||||||
@@ -1823,6 +1823,12 @@ namespace decls_block {
|
|||||||
BCArray<IdentifierIDField>
|
BCArray<IdentifierIDField>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
using TypeEraserDeclAttrLayout = BCRecordLayout<
|
||||||
|
TypeEraser_DECL_ATTR,
|
||||||
|
BCFixed<1>, // implicit flag
|
||||||
|
TypeIDField // type eraser type
|
||||||
|
>;
|
||||||
|
|
||||||
using CustomDeclAttrLayout = BCRecordLayout<
|
using CustomDeclAttrLayout = BCRecordLayout<
|
||||||
Custom_DECL_ATTR,
|
Custom_DECL_ATTR,
|
||||||
BCFixed<1>, // implicit flag
|
BCFixed<1>, // implicit flag
|
||||||
|
|||||||
@@ -2108,6 +2108,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
|
|||||||
case DAK_RestatedObjCConformance:
|
case DAK_RestatedObjCConformance:
|
||||||
case DAK_ClangImporterSynthesizedType:
|
case DAK_ClangImporterSynthesizedType:
|
||||||
case DAK_PrivateImport:
|
case DAK_PrivateImport:
|
||||||
|
case DAK_TypeEraser:
|
||||||
llvm_unreachable("cannot serialize attribute");
|
llvm_unreachable("cannot serialize attribute");
|
||||||
|
|
||||||
case DAK_Count:
|
case DAK_Count:
|
||||||
|
|||||||
19
test/attr/typeEraser.swift
Normal file
19
test/attr/typeEraser.swift
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// RUN: %target-swift-frontend -typecheck %s -verify
|
||||||
|
|
||||||
|
class AnyP: P1 {}
|
||||||
|
|
||||||
|
@_typeEraser(AnyP) // okay
|
||||||
|
protocol P1 {}
|
||||||
|
|
||||||
|
@_typeEraser // expected-error {{expected '(' in '_typeEraser' attribute}}
|
||||||
|
protocol P2 {}
|
||||||
|
|
||||||
|
@_typeEraser() // expected-error {{expected a type name in @_typeEraser()}}
|
||||||
|
protocol P3 {}
|
||||||
|
|
||||||
|
@_typeEraser(AnyP // expected-note {{to match this opening '('}}
|
||||||
|
protocol P4 {} // expected-error {{expected ')' after type name for @_typeEraser}}
|
||||||
|
|
||||||
|
@_typeEraser(AnyP) // expected-error {{@_typeEraser may only be used on 'protocol' declarations}}
|
||||||
|
func notAProtocol() {}
|
||||||
|
|
||||||
Reference in New Issue
Block a user