diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 2e3d66f82fda3..11e80605567ea 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -364,6 +364,41 @@ class DeclAttribute : public AttributeBase { /// The opposite of ABIBreakingToRemove ABIStableToRemove = 1ull << 15, + + /// Attribute should not be used in an \c \@abi attribute. Use for + /// attributes which cannot affect mangled names, even indirectly, and + /// which either don't affect ABI or where ABI-only declarations get their + /// behavior from their API counterpart. + ForbiddenInABIAttr = 1ull << 16, + + /// Attribute can be used without restrictions in an \c \@abi attribute. + /// Use for attributes which affect mangled names but otherwise don't alter + /// the ABI, or ones where the \c ABIDeclChecker manually implements + /// special checking logic (e.g. because several different attributes + /// contribute to the same aspect of ABI in some complicated way). + UnconstrainedInABIAttr = 1ull << 17, + + /// Attribute can be used in an \c \@abi attribute, but must match + /// equivalent on API decl. Use for attributes which affect both mangled + /// names and other parts of the ABI such that the declaration can only be + /// valid if they match. + EquivalentInABIAttr = 1ull << 18, + + /// Attribute can be used in an \c \@abi attribute, but must match + /// equivalent on API decl; if omitted, API decl's attribute will be + /// cloned. Use where you would want to use \c EquivalentInABIAttr but + /// repeating the attribute is judged too burdensome. + InferredInABIAttr = 1ull << 19, + + /// Use for attributes which are \em only valid on declarations that cannot + /// have an \c @abi attribute, such as \c ImportDecl . + UnreachableInABIAttr = 1ull << 20, + }; + + enum : uint64_t { + InABIAttrMask = ForbiddenInABIAttr | UnconstrainedInABIAttr + | EquivalentInABIAttr | InferredInABIAttr + | UnreachableInABIAttr }; LLVM_READNONE @@ -549,6 +584,11 @@ class DeclAttribute : public AttributeBase { /// Determine whether we can clone this attribute. bool canClone() const; + + /// Determine if this attribute and \p other are "the same", as in, they + /// would have the same effect on \p attachedTo were they attached to it. A + /// clone should always be equivalent to the original. + bool isEquivalent(const DeclAttribute *other, Decl *attachedTo) const; }; #define UNIMPLEMENTED_CLONE(AttrType) \ @@ -582,6 +622,11 @@ class SimpleDeclAttr : public DeclAttribute { return new (ctx) SimpleDeclAttr( AtLoc, Range.Start, isImplicit()); } + + bool isEquivalent(const SimpleDeclAttr *other, Decl *attachedTo) const { + // True by definition, since there's nothing to this other than its kind. + return true; + } }; // Declare typedefs for all of the simple declaration attributes. @@ -614,6 +659,10 @@ class SILGenNameAttr : public DeclAttribute { SILGenNameAttr *clone(ASTContext &ctx) const { return new (ctx) SILGenNameAttr(Name, Raw, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const SILGenNameAttr *other, Decl *attachedTo) const { + return Name == other->Name && Raw == other->Raw; + } }; /// Defines the @_section attribute. @@ -636,6 +685,10 @@ class SectionAttr : public DeclAttribute { SectionAttr *clone(ASTContext &ctx) const { return new (ctx) SectionAttr(Name, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const SectionAttr *other, Decl *attachedTo) const { + return Name == other->Name; + } }; /// Defines the @_cdecl attribute. @@ -658,6 +711,10 @@ class CDeclAttr : public DeclAttribute { CDeclAttr *clone(ASTContext &ctx) const { return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const CDeclAttr *other, Decl *attachedTo) const { + return Name == other->Name; + } }; /// Defines the @_semantics attribute. @@ -681,6 +738,10 @@ class SemanticsAttr : public DeclAttribute { SemanticsAttr *clone(ASTContext &ctx) const { return new (ctx) SemanticsAttr(Value, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const SemanticsAttr *other, Decl *attachedTo) const { + return Value == other->Value; + } }; /// Defines the @_alignment attribute. @@ -701,6 +762,10 @@ class AlignmentAttr : public DeclAttribute { AlignmentAttr *clone(ASTContext &ctx) const { return new (ctx) AlignmentAttr(getValue(), AtLoc, Range, isImplicit()); } + + bool isEquivalent(const AlignmentAttr *other, Decl *attachedTo) const { + return getValue() == other->getValue(); + } }; /// Defines the @_swift_native_objc_runtime_base attribute. @@ -732,6 +797,11 @@ class SwiftNativeObjCRuntimeBaseAttr : public DeclAttribute { return new (ctx) SwiftNativeObjCRuntimeBaseAttr( BaseClassName, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const SwiftNativeObjCRuntimeBaseAttr *other, + Decl *attachedTo) const { + return BaseClassName == other->BaseClassName; + } }; /// Defines the @available attribute. @@ -914,6 +984,8 @@ class AvailableAttr : public DeclAttribute { return clone(C, isImplicit()); } + bool isEquivalent(const AvailableAttr *other, Decl *attachedTo) const; + static bool classof(const DeclAttribute *DA) { return DA->getKind() == DeclAttrKind::Available; } @@ -1081,6 +1153,16 @@ class ObjCAttr final : public DeclAttribute, /// original without source location information. ObjCAttr *clone(ASTContext &context) const; + bool isEquivalent(const ObjCAttr *other, Decl *attachedTo) const { + std::optional thisName, otherName; + if (hasName() && !isNameImplicit()) + thisName = getName(); + if (other->hasName() && !other->isNameImplicit()) + otherName = other->getName(); + + return thisName == otherName; + } + static bool classof(const DeclAttribute *DA) { return DA->getKind() == DeclAttrKind::ObjC; } @@ -1111,6 +1193,10 @@ class PrivateImportAttr final return new (ctx) PrivateImportAttr( AtLoc, Range, SourceFile, SourceRange(), isImplicit()); } + + bool isEquivalent(const PrivateImportAttr *other, Decl *attachedTo) const { + return getSourceFile() == other->getSourceFile(); + } }; /// The @_dynamicReplacement(for:) attribute. @@ -1190,6 +1276,10 @@ class DynamicReplacementAttr final } UNIMPLEMENTED_CLONE(DynamicReplacementAttr) + + bool isEquivalent(const DynamicReplacementAttr *other, Decl *attachedTo) const { + return getReplacedFunctionName() == other->getReplacedFunctionName(); + } }; /// The \c @_typeEraser(TypeEraserType) attribute. @@ -1247,6 +1337,8 @@ class TypeEraserAttr final : public DeclAttribute { } UNIMPLEMENTED_CLONE(TypeEraserAttr) + + bool isEquivalent(const TypeEraserAttr *other, Decl *attachedTo) const; }; /// Represents any sort of access control modifier. @@ -1286,6 +1378,10 @@ class AccessControlAttr : public AbstractAccessControlAttr { AccessControlAttr *clone(ASTContext &ctx) const { return new (ctx) AccessControlAttr(AtLoc, Range, getAccess(), isImplicit()); } + + bool isEquivalent(const AccessControlAttr *other, Decl *attachedTo) const { + return getAccess() == other->getAccess(); + } }; /// Represents a 'private', 'internal', or 'public' marker for a setter on a @@ -1305,6 +1401,10 @@ class SetterAccessAttr : public AbstractAccessControlAttr { SetterAccessAttr *clone(ASTContext &ctx) const { return new (ctx) SetterAccessAttr(AtLoc, Range, getAccess(), isImplicit()); } + + bool isEquivalent(const SetterAccessAttr *other, Decl *attachedTo) const { + return getAccess() == other->getAccess(); + } }; /// SPI attribute applied to both decls and imports. @@ -1341,6 +1441,8 @@ class SPIAccessControlAttr final : public DeclAttribute, static bool classof(const DeclAttribute *DA) { return DA->getKind() == DeclAttrKind::SPIAccessControl; } + + bool isEquivalent(const SPIAccessControlAttr *other, Decl *attachedTo) const; }; /// Represents an inline attribute. @@ -1363,6 +1465,10 @@ class InlineAttr : public DeclAttribute { InlineAttr *clone(ASTContext &ctx) const { return new (ctx) InlineAttr(AtLoc, Range, getKind(), isImplicit()); } + + bool isEquivalent(const InlineAttr *other, Decl *attachedTo) const { + return getKind() == other->getKind(); + } }; /// Represents the optimize attribute. @@ -1387,6 +1493,10 @@ class OptimizeAttr : public DeclAttribute { OptimizeAttr *clone(ASTContext &ctx) const { return new (ctx) OptimizeAttr(AtLoc, Range, getMode(), isImplicit()); } + + bool isEquivalent(const OptimizeAttr *other, Decl *attachedTo) const { + return getMode() == other->getMode(); + } }; /// Represents the exclusivity attribute. @@ -1418,6 +1528,10 @@ class ExclusivityAttr : public DeclAttribute { ExclusivityAttr *clone(ASTContext &ctx) const { return new (ctx) ExclusivityAttr(AtLoc, Range, getMode(), isImplicit()); } + + bool isEquivalent(const ExclusivityAttr *other, Decl *attachedTo) const { + return getMode() == other->getMode(); + } }; /// Represents the side effects attribute. @@ -1464,6 +1578,14 @@ class EffectsAttr : public DeclAttribute { } return new (ctx) EffectsAttr(getKind()); } + + bool isEquivalent(const EffectsAttr *other, Decl *attachedTo) const { + if (getKind() != other->getKind()) + return false; + if (getKind() == EffectsKind::Custom) + return getCustomString() == other->getCustomString(); + return true; + } }; @@ -1492,6 +1614,11 @@ class ReferenceOwnershipAttr : public DeclAttribute { static bool classof(const DeclAttribute *DA) { return DA->getKind() == DeclAttrKind::ReferenceOwnership; } + + bool isEquivalent(const ReferenceOwnershipAttr *other, + Decl *attachedTo) const { + return get() == other->get(); + } }; /// Defines the attribute that we use to model documentation comments. @@ -1515,6 +1642,10 @@ class RawDocCommentAttr : public DeclAttribute { RawDocCommentAttr *clone(ASTContext &ctx) const { return new (ctx) RawDocCommentAttr(CommentRange, isImplicit()); } + + bool isEquivalent(const RawDocCommentAttr *other, Decl *attachedTo) const { + return getCommentRange() == other->getCommentRange(); + } }; /// An attribute applied to a CoreFoundation class that is toll-free bridged to @@ -1542,6 +1673,10 @@ class ObjCBridgedAttr : public DeclAttribute { ObjCBridgedAttr *clone(ASTContext &ctx) const { return new (ctx) ObjCBridgedAttr(ObjCClass); } + + bool isEquivalent(const ObjCBridgedAttr *other, Decl *attachedTo) const { + return getObjCClass() == other->getObjCClass(); + } }; /// An attribute that specifies a synthesized conformance of a known @@ -1586,6 +1721,13 @@ class SynthesizedProtocolAttr : public DeclAttribute { return new (ctx) SynthesizedProtocolAttr( protocol, getLazyLoader(), isUnchecked()); } + + bool isEquivalent(const SynthesizedProtocolAttr *other, + Decl *attachedTo) const { + return isUnchecked() == other->isUnchecked() + && getProtocol() == other->getProtocol() + && getLazyLoader() == other->getLazyLoader(); + } }; /// The @_specialize attribute, which forces specialization on the specified @@ -1719,6 +1861,8 @@ class SpecializeAttr final } UNIMPLEMENTED_CLONE(SpecializeAttr) + + bool isEquivalent(const SpecializeAttr *other, Decl *attachedTo) const; }; class StorageRestrictionsAttr final @@ -1763,19 +1907,24 @@ class StorageRestrictionsAttr final } UNIMPLEMENTED_CLONE(StorageRestrictionsAttr) + + bool isEquivalent(const StorageRestrictionsAttr *other, + Decl *attachedTo) const; }; /// The @_implements attribute, which treats a decl as the implementation for /// some named protocol requirement (but otherwise not-visible by that name). class ImplementsAttr : public DeclAttribute { - TypeRepr *TyR; + /// If constructed by the \c create() variant with a TypeRepr, the TypeRepr; + /// if constructed by the \c create() variant with a DeclContext and + /// ProtocolDecl, the DeclContext. + llvm::PointerUnion TyROrDC; DeclName MemberName; DeclNameLoc MemberNameLoc; ImplementsAttr(SourceLoc atLoc, SourceRange Range, - TypeRepr *TyR, - DeclName MemberName, - DeclNameLoc MemberNameLoc); + llvm::PointerUnion TyROrDC, + DeclName MemberName, DeclNameLoc MemberNameLoc); public: static ImplementsAttr *create(ASTContext &Ctx, SourceLoc atLoc, @@ -1795,7 +1944,9 @@ class ImplementsAttr : public DeclAttribute { /// otherwise `nullopt`. This should only be used for dumping. std::optional getCachedProtocol(DeclContext *dc) const; - TypeRepr *getProtocolTypeRepr() const { return TyR; } + TypeRepr *getProtocolTypeRepr() const { + return TyROrDC.dyn_cast(); + } DeclName getMemberName() const { return MemberName; } DeclNameLoc getMemberNameLoc() const { return MemberNameLoc; } @@ -1806,9 +1957,15 @@ class ImplementsAttr : public DeclAttribute { /// Create a copy of this attribute. ImplementsAttr *clone(ASTContext &ctx) const { - return new (ctx) ImplementsAttr( - AtLoc, Range, TyR, getMemberName(), getMemberNameLoc()); + if (auto tyR = getProtocolTypeRepr()) { + return create(ctx, AtLoc, Range, tyR, getMemberName(), + getMemberNameLoc()); + } + auto dc = TyROrDC.dyn_cast(); + return create(dc, getProtocol(dc), getMemberName()); } + + bool isEquivalent(const ImplementsAttr *other, Decl *attachedTo) const; }; /// A limited variant of \c \@objc that's used for classes with generic ancestry. @@ -1837,6 +1994,10 @@ class ObjCRuntimeNameAttr : public DeclAttribute { ObjCRuntimeNameAttr *clone(ASTContext &ctx) const { return new (ctx) ObjCRuntimeNameAttr(Name, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const ObjCRuntimeNameAttr *other, Decl *attachedTo) const { + return Name == other->Name; + } }; /// Attribute that specifies a protocol conformance that has been restated @@ -1860,6 +2021,11 @@ class RestatedObjCConformanceAttr : public DeclAttribute { RestatedObjCConformanceAttr *clone(ASTContext &ctx) const { return new (ctx) RestatedObjCConformanceAttr(Proto); } + + bool isEquivalent(const RestatedObjCConformanceAttr *other, + Decl *attachedTo) const { + return Proto == other->Proto; + } }; /// Attached to type declarations synthesized by the Clang importer. @@ -1927,6 +2093,12 @@ class ClangImporterSynthesizedTypeAttr : public DeclAttribute { return new (ctx) ClangImporterSynthesizedTypeAttr( originalTypeName, getKind()); } + + bool isEquivalent(const ClangImporterSynthesizedTypeAttr *other, + Decl *attachedTo) const { + return getKind() == other->getKind() + && originalTypeName == other->originalTypeName; + } }; /// Defines a custom attribute. @@ -1998,6 +2170,8 @@ class CustomAttr final : public DeclAttribute { bool canClone() const { return argList == nullptr; } + bool isEquivalent(const CustomAttr *other, Decl *attachedTo) const; + private: friend class CustomAttrNominalRequest; void resetTypeInformation(TypeExpr *repr); @@ -2036,6 +2210,11 @@ class ProjectedValuePropertyAttr : public DeclAttribute { return new (ctx) ProjectedValuePropertyAttr( ProjectionPropertyName, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const ProjectedValuePropertyAttr *other, + Decl *attachedTo) const { + return ProjectionPropertyName == other->ProjectionPropertyName; + } }; /// Describes a symbol that was originally defined in another module. For @@ -2101,6 +2280,14 @@ class OriginallyDefinedInAttr: public DeclAttribute { AtLoc, Range, ManglingModuleName, LinkerModuleName, Platform, MovedVersion, isImplicit()); } + + bool isEquivalent(const OriginallyDefinedInAttr *other, + Decl *attachedTo) const { + return ManglingModuleName == other->ManglingModuleName + && LinkerModuleName == other->LinkerModuleName + && Platform == other->Platform + && MovedVersion == other->MovedVersion; + } }; /// Attribute that marks a function as differentiable. @@ -2250,6 +2437,11 @@ class DifferentiableAttr final } UNIMPLEMENTED_CLONE(DifferentiableAttr) + + bool isEquivalent(const DifferentiableAttr *other, Decl *attachedTo) const { + // Not properly implemented (very complex and not currently needed) + return false; + } }; /// A declaration name with location. @@ -2391,6 +2583,11 @@ class DerivativeAttr final } UNIMPLEMENTED_CLONE(DerivativeAttr) + + bool isEquivalent(const DerivativeAttr *other, Decl *attachedTo) const { + // Not properly implemented (very complex and not currently needed) + return false; + } }; /// The `@transpose(of:)` attribute registers a function as a transpose of @@ -2477,6 +2674,11 @@ class TransposeAttr final } UNIMPLEMENTED_CLONE(TransposeAttr) + + bool isEquivalent(const TransposeAttr *other, Decl *attachedTo) const { + // Not properly implemented (very complex and not currently needed) + return false; + } }; enum class NonSendableKind : uint8_t { @@ -2512,6 +2714,10 @@ class NonSendableAttr : public DeclAttribute { NonSendableAttr *clone(ASTContext &ctx) const { return new (ctx) NonSendableAttr(AtLoc, Range, Specificity, isImplicit()); } + + bool isEquivalent(const NonSendableAttr *other, Decl *attachedTo) const { + return Specificity == other->Specificity; + } }; /// The @_unavailableFromAsync attribute, used to make function declarations @@ -2539,6 +2745,11 @@ class UnavailableFromAsyncAttr : public DeclAttribute { return new (ctx) UnavailableFromAsyncAttr( Message, AtLoc, Range, isImplicit()); } + + bool isEquivalent(const UnavailableFromAsyncAttr *other, + Decl *attachedTo) const { + return Message == other->Message; + } }; /// The `@backDeployed(...)` attribute, used to make function declarations @@ -2569,6 +2780,10 @@ class BackDeployedAttr : public DeclAttribute { return new (ctx) BackDeployedAttr( AtLoc, Range, Platform, Version, isImplicit()); } + + bool isEquivalent(const BackDeployedAttr *other, Decl *attachedTo) const { + return Platform == other->Platform && Version == Version; + } }; /// Defines the `@_expose` attribute, used to expose declarations in the @@ -2602,6 +2817,10 @@ class ExposeAttr : public DeclAttribute { return new (ctx) ExposeAttr( Name, AtLoc, Range, getExposureKind(), isImplicit()); } + + bool isEquivalent(const ExposeAttr *other, Decl *attachedTo) const { + return Name == other->Name && getExposureKind() == other->getExposureKind(); + } }; /// Define the `@_extern` attribute, used to import external declarations in @@ -2657,6 +2876,11 @@ class ExternAttr : public DeclAttribute { ModuleName, Name, AtLoc, getLParenLoc(), getRParenLoc(), Range, getExternKind(), isImplicit()); } + + bool isEquivalent(const ExternAttr *other, Decl *attachedTo) const { + return getExternKind() == other->getExternKind() + && ModuleName == other->ModuleName && Name == other->Name; + } }; /// The `@_documentation(...)` attribute, used to override a symbol's visibility @@ -2685,6 +2909,10 @@ class DocumentationAttr: public DeclAttribute { return new (ctx) DocumentationAttr( AtLoc, Range, Metadata, Visibility, isImplicit()); } + + bool isEquivalent(const DocumentationAttr *other, Decl *attachedTo) const { + return Metadata == other->Metadata && Visibility == other->Visibility; + } }; class ObjCImplementationAttr final : public DeclAttribute { @@ -2739,6 +2967,12 @@ class ObjCImplementationAttr final : public DeclAttribute { CategoryName, AtLoc, Range, isEarlyAdopter(), isImplicit(), isCategoryNameInvalid()); } + + bool isEquivalent(const ObjCImplementationAttr *other, + Decl *attachedTo) const { + // Ignoring `CategoryName` as it gets copied to @objc + return isEarlyAdopter() == other->isEarlyAdopter(); + } }; /// Represents nonisolated modifier. @@ -2764,6 +2998,10 @@ class NonisolatedAttr final : public DeclAttribute { NonisolatedAttr *clone(ASTContext &ctx) const { return new (ctx) NonisolatedAttr(AtLoc, Range, isUnsafe(), isImplicit()); } + + bool isEquivalent(const NonisolatedAttr *other, Decl *attachedTo) const { + return isUnsafe() == other->isUnsafe(); + } }; /// A macro role attribute, spelled with either @attached or @freestanding, @@ -2817,6 +3055,11 @@ class MacroRoleAttr final } UNIMPLEMENTED_CLONE(MacroRoleAttr) + + bool isEquivalent(const MacroRoleAttr *other, Decl *attachedTo) const { + // Unimplemented: complex and not immediately needed. + return true; + } }; /// Specifies the raw storage used by a type. @@ -2920,6 +3163,8 @@ class RawLayoutAttr final : public DeclAttribute { } UNIMPLEMENTED_CLONE(RawLayoutAttr) + + bool isEquivalent(const RawLayoutAttr *other, Decl *attachedTo) const; }; class LifetimeAttr final : public DeclAttribute { @@ -2945,6 +3190,8 @@ class LifetimeAttr final : public DeclAttribute { LifetimeAttr *clone(ASTContext &ctx) const { return new (ctx) LifetimeAttr(AtLoc, Range, isImplicit(), entry); } + + bool isEquivalent(const LifetimeAttr *other, Decl *attachedTo) const; }; /// Predicate used to filter MatchingAttributeRange. @@ -2993,6 +3240,9 @@ class AllowFeatureSuppressionAttr final } UNIMPLEMENTED_CLONE(AllowFeatureSuppressionAttr) + + bool isEquivalent(const AllowFeatureSuppressionAttr *other, + Decl *attachedTo) const; }; /// Defines the @abi attribute. @@ -3018,6 +3268,11 @@ class ABIAttr : public DeclAttribute { } UNIMPLEMENTED_CLONE(ABIAttr) + + bool isEquivalent(const ABIAttr *other, Decl *attachedTo) const { + // Unsupported: tricky to implement and unneeded. + return true; + } }; class ExecutionAttr : public DeclAttribute { @@ -3042,6 +3297,10 @@ class ExecutionAttr : public DeclAttribute { } UNIMPLEMENTED_CLONE(ExecutionAttr) + + bool isEquivalent(const ExecutionAttr *other, Decl *attachedTo) const { + return getBehavior() == other->getBehavior(); + } }; /// Attributes that may be applied to declarations. diff --git a/include/swift/AST/AttrKind.h b/include/swift/AST/AttrKind.h index 1f4a784c70510..d56edbc4b6e31 100644 --- a/include/swift/AST/AttrKind.h +++ b/include/swift/AST/AttrKind.h @@ -145,6 +145,8 @@ enum class DeclAttrKind : unsigned { #include "swift/AST/DeclAttr.def" }; +StringRef getDeclAttrKindID(DeclAttrKind kind); + enum : unsigned { NumDeclAttrKinds = static_cast(DeclAttrKind::Last_DeclAttr) + 1, NumDeclAttrKindBits = countBitsUsed(NumDeclAttrKinds - 1), diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index ab3d8fde31c39..0544e49bed8b6 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -1041,6 +1041,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated, public Swi /// from source code. void attachParsedAttrs(DeclAttributes attrs); + /// Retrieve the custom name in the \c @objc attribute, if present. + std::optional + getExplicitObjCName(bool allowInvalid = false) const; + /// True if this declaration provides an implementation for an imported /// Objective-C declaration. This implies various restrictions and special /// behaviors for it and, if it's an extension, its members. @@ -5919,6 +5923,13 @@ class AbstractStorageDecl : public ValueDecl { /// Return the interface type of the stored value. Type getValueInterfaceType() const; + /// Retrieve the source range of the variable type, or an invalid range if the + /// variable's type is not explicitly written in the source. + /// + /// Only for use in diagnostics. It is not always possible to always + /// precisely point to the variable type because of type aliases. + SourceRange getTypeSourceRangeForDiagnostics() const; + /// Determine how this storage is implemented. StorageImplInfo getImplInfo() const; @@ -6353,13 +6364,6 @@ class VarDecl : public AbstractStorageDecl { /// and not just getInterfaceType(). Type getTypeInContext() const; - /// Retrieve the source range of the variable type, or an invalid range if the - /// variable's type is not explicitly written in the source. - /// - /// Only for use in diagnostics. It is not always possible to always - /// precisely point to the variable type because of type aliases. - SourceRange getTypeSourceRangeForDiagnostics() const; - /// Determine the mutability of this variable declaration when /// accessed from a given declaration context. StorageMutability mutability( diff --git a/include/swift/AST/DeclAttr.def b/include/swift/AST/DeclAttr.def index a7cb4d7d4eb59..654d9cf221688 100644 --- a/include/swift/AST/DeclAttr.def +++ b/include/swift/AST/DeclAttr.def @@ -63,142 +63,142 @@ // leave an "Unused 'NNN'" comment so the unused code is obvious. DECL_ATTR(_silgen_name, SILGenName, OnAbstractFunction | OnVar, - LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 0) DECL_ATTR(available, Available, OnAbstractFunction | OnAssociatedType | OnGenericType | OnVar | OnSubscript | OnEnumElement | OnMacro | OnExtension, - AllowMultipleAttributes | LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 1) CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final, OnClass | OnFunc | OnAccessor | OnVar | OnSubscript, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 2) DECL_ATTR(objc, ObjC, OnAbstractFunction | OnClass | OnProtocol | OnExtension | OnVar | OnSubscript | OnEnum | OnEnumElement, - ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 3) CONTEXTUAL_SIMPLE_DECL_ATTR(required, Required, OnConstructor, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | EquivalentInABIAttr, 4) CONTEXTUAL_SIMPLE_DECL_ATTR(optional, Optional, OnConstructor | OnFunc | OnAccessor | OnVar | OnSubscript, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 5) SIMPLE_DECL_ATTR(dynamicCallable, DynamicCallable, OnNominalType, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 6) SIMPLE_DECL_ATTR(main, MainType, OnClass | OnStruct | OnEnum | OnExtension, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 7) SIMPLE_DECL_ATTR(_exported, Exported, OnImport, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 8) SIMPLE_DECL_ATTR(dynamicMemberLookup, DynamicMemberLookup, OnNominalType, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 9) SIMPLE_DECL_ATTR(NSCopying, NSCopying, OnVar, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 10) SIMPLE_DECL_ATTR(IBAction, IBAction, OnFunc, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 11) SIMPLE_DECL_ATTR(IBDesignable, IBDesignable, OnClass | OnExtension, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 12) SIMPLE_DECL_ATTR(IBInspectable, IBInspectable, OnVar, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 13) SIMPLE_DECL_ATTR(IBOutlet, IBOutlet, OnVar, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 14) SIMPLE_DECL_ATTR(NSManaged, NSManaged, OnVar | OnFunc | OnAccessor, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 15) CONTEXTUAL_SIMPLE_DECL_ATTR(lazy, Lazy, OnVar, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 16) SIMPLE_DECL_ATTR(LLDBDebuggerFunction, LLDBDebuggerFunction, OnFunc, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 17) SIMPLE_DECL_ATTR(UIApplicationMain, UIApplicationMain, OnClass, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 18) SIMPLE_DECL_ATTR(unsafe_no_objc_tagged_pointer, UnsafeNoObjCTaggedPointer, OnProtocol, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 19) DECL_ATTR(inline, Inline, OnVar | OnSubscript | OnAbstractFunction, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 20) DECL_ATTR(_semantics, Semantics, OnAbstractFunction | OnSubscript | OnNominalType | OnVar, - AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 21) CONTEXTUAL_SIMPLE_DECL_ATTR(dynamic, Dynamic, OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 22) CONTEXTUAL_SIMPLE_DECL_ATTR(infix, Infix, OnFunc | OnOperator, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 23) CONTEXTUAL_SIMPLE_DECL_ATTR(prefix, Prefix, OnFunc | OnOperator, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 24) CONTEXTUAL_SIMPLE_DECL_ATTR(postfix, Postfix, OnFunc | OnOperator, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 25) SIMPLE_DECL_ATTR(_transparent, Transparent, OnFunc | OnAccessor | OnConstructor | OnVar | OnDestructor, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 26) SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits, OnClass, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 27) // Unused '28' @@ -206,37 +206,37 @@ SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits, SIMPLE_DECL_ATTR(nonobjc, NonObjC, OnExtension | OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 30) SIMPLE_DECL_ATTR(_fixed_layout, FixedLayout, OnVar | OnClass | OnStruct | OnProtocol, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 31) SIMPLE_DECL_ATTR(inlinable, Inlinable, OnVar | OnSubscript | OnAbstractFunction, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 32) DECL_ATTR(_specialize, Specialize, OnConstructor | OnFunc | OnAccessor, - AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 33) SIMPLE_DECL_ATTR(objcMembers, ObjCMembers, OnClass, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 34) CONTEXTUAL_SIMPLE_DECL_ATTR(_compilerInitialized, CompilerInitialized, OnVar, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 35) SIMPLE_DECL_ATTR(_lexicalLifetimes, LexicalLifetimes, OnFunc, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 36) // Unused '37' @@ -245,37 +245,37 @@ SIMPLE_DECL_ATTR(_lexicalLifetimes, LexicalLifetimes, CONTEXTUAL_SIMPLE_DECL_ATTR(__consuming, LegacyConsuming, OnFunc | OnAccessor, - DeclModifier | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 40) CONTEXTUAL_SIMPLE_DECL_ATTR(mutating, Mutating, OnFunc | OnAccessor, - DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 41) CONTEXTUAL_SIMPLE_DECL_ATTR(nonmutating, NonMutating, OnFunc | OnAccessor, - DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 42) CONTEXTUAL_SIMPLE_DECL_ATTR(convenience, Convenience, OnConstructor, - DeclModifier | NotSerialized | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | EquivalentInABIAttr, 43) CONTEXTUAL_SIMPLE_DECL_ATTR(override, Override, OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor | OnAssociatedType, - DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 44) SIMPLE_DECL_ATTR(_hasStorage, HasStorage, OnVar, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 45) DECL_ATTR(private, AccessControl, OnFunc | OnAccessor | OnExtension | OnGenericType | OnVar | OnSubscript | OnConstructor | OnMacro | OnImport, - DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 46) DECL_ATTR_ALIAS(fileprivate, AccessControl) DECL_ATTR_ALIAS(internal, AccessControl) @@ -285,540 +285,541 @@ CONTEXTUAL_DECL_ATTR_ALIAS(open, AccessControl) DECL_ATTR(__setter_access, SetterAccess, OnVar | OnSubscript, - DeclModifier | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 47) DECL_ATTR(__raw_doc_comment, RawDocComment, OnAnyDecl, - UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 48) CONTEXTUAL_DECL_ATTR(weak, ReferenceOwnership, OnVar, - DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 49) CONTEXTUAL_DECL_ATTR_ALIAS(unowned, ReferenceOwnership) DECL_ATTR(_effects, Effects, OnAbstractFunction, - AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 50) DECL_ATTR(__objc_bridged, ObjCBridged, OnClass, - UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 51) SIMPLE_DECL_ATTR(NSApplicationMain, NSApplicationMain, OnClass, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 52) SIMPLE_DECL_ATTR(_objc_non_lazy_realization, ObjCNonLazyRealization, OnClass, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 53) DECL_ATTR(__synthesized_protocol, SynthesizedProtocol, OnConcreteNominalType, - UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 54) SIMPLE_DECL_ATTR(testable, Testable, OnImport, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 55) DECL_ATTR(_alignment, Alignment, OnStruct | OnEnum, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 56) SIMPLE_DECL_ATTR(rethrows, Rethrows, OnFunc | OnConstructor, - DeclModifier | RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 57) SIMPLE_DECL_ATTR(rethrows, AtRethrows, OnProtocol, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 58) DECL_ATTR(_swift_native_objc_runtime_base, SwiftNativeObjCRuntimeBase, OnClass, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 59) CONTEXTUAL_SIMPLE_DECL_ATTR(indirect, Indirect, OnEnum | OnEnumElement, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 60) SIMPLE_DECL_ATTR(warn_unqualified_access, WarnUnqualifiedAccess, OnFunc | OnAccessor, - LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 61) SIMPLE_DECL_ATTR(_show_in_interface, ShowInInterface, OnProtocol, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 62) DECL_ATTR(_cdecl, CDecl, OnFunc | OnAccessor, - LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 63) SIMPLE_DECL_ATTR(usableFromInline, UsableFromInline, OnAbstractFunction | OnVar | OnSubscript | OnNominalType | OnTypeAlias, - LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 64) SIMPLE_DECL_ATTR(discardableResult, DiscardableResult, OnFunc | OnAccessor | OnConstructor | OnMacro, - LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 65) SIMPLE_DECL_ATTR(GKInspectable, GKInspectable, OnVar, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 66) DECL_ATTR(_implements, Implements, OnFunc | OnAccessor | OnVar | OnSubscript | OnTypeAlias, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 67) DECL_ATTR(_objcRuntimeName, ObjCRuntimeName, OnClass, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 68) SIMPLE_DECL_ATTR(_staticInitializeObjCMetadata, StaticInitializeObjCMetadata, OnClass, - UserInaccessible | LongAttribute | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | LongAttribute | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 69) DECL_ATTR(_restatedObjCConformance, RestatedObjCConformance, OnProtocol, - UserInaccessible | LongAttribute | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | LongAttribute | RejectByParser | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 70) // Unused '71' DECL_ATTR(implementation, ObjCImplementation, OnExtension | OnAbstractFunction, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 72) DECL_ATTR_ALIAS(_objcImplementation, ObjCImplementation) DECL_ATTR(_optimize, Optimize, OnAbstractFunction | OnSubscript | OnVar, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 73) DECL_ATTR(_clangImporterSynthesizedType, ClangImporterSynthesizedType, OnGenericType, - LongAttribute | RejectByParser | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | RejectByParser | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 74) SIMPLE_DECL_ATTR(_weakLinked, WeakLinked, OnNominalType | OnAssociatedType | OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor | OnEnumElement | OnExtension | OnImport, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 75) SIMPLE_DECL_ATTR(frozen, Frozen, OnEnum | OnStruct, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToRemove | APIStableToAdd, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToRemove | APIStableToAdd | UnreachableInABIAttr, 76) - DECL_ATTR_ALIAS(_frozen, Frozen) + SIMPLE_DECL_ATTR(_forbidSerializingReference, ForbidSerializingReference, OnAnyDecl, - LongAttribute | RejectByParser | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + LongAttribute | RejectByParser | UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 77) SIMPLE_DECL_ATTR(_hasInitialValue, HasInitialValue, OnVar, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 78) SIMPLE_DECL_ATTR(_nonoverride, NonOverride, OnFunc | OnAccessor | OnVar | OnSubscript | OnConstructor | OnAssociatedType, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 79) DECL_ATTR(_dynamicReplacement, DynamicReplacement, OnAbstractFunction | OnVar | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 80) SIMPLE_DECL_ATTR(_borrowed, Borrowed, OnVar | OnSubscript, - UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 81) DECL_ATTR(_private, PrivateImport, OnImport, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 82) SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient, OnVar | OnSubscript | OnAbstractFunction, - UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, 83) SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly, OnImport | OnFunc | OnConstructor | OnVar | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 84) DECL_ATTR(_custom, Custom, OnAnyDecl, - RejectByParser | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + RejectByParser | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 85) SIMPLE_DECL_ATTR(propertyWrapper, PropertyWrapper, OnStruct | OnClass | OnEnum, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 86) SIMPLE_DECL_ATTR(_disfavoredOverload, DisfavoredOverload, OnAbstractFunction | OnVar | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 87) SIMPLE_DECL_ATTR(resultBuilder, ResultBuilder, OnNominalType, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 88) DECL_ATTR(_projectedValueProperty, ProjectedValueProperty, OnVar, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 89) SIMPLE_DECL_ATTR(_nonEphemeral, NonEphemeral, OnParam, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr, 90) DECL_ATTR(differentiable, Differentiable, OnAccessor | OnConstructor | OnFunc | OnVar | OnSubscript, - LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 91) SIMPLE_DECL_ATTR(_hasMissingDesignatedInitializers, HasMissingDesignatedInitializers, OnClass, - UserInaccessible | NotSerialized | APIBreakingToAdd | ABIBreakingToAdd | APIStableToRemove | ABIStableToRemove, + UserInaccessible | NotSerialized | APIBreakingToAdd | ABIBreakingToAdd | APIStableToRemove | ABIStableToRemove | UnreachableInABIAttr, 92) SIMPLE_DECL_ATTR(_inheritsConvenienceInitializers, InheritsConvenienceInitializers, OnClass, - UserInaccessible | NotSerialized | APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove, + UserInaccessible | NotSerialized | APIStableToAdd | ABIStableToAdd | APIBreakingToRemove | ABIBreakingToRemove | UnreachableInABIAttr, 93) DECL_ATTR(_typeEraser, TypeEraser, OnProtocol, - UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | AllowMultipleAttributes, + UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | AllowMultipleAttributes | UnreachableInABIAttr, 94) SIMPLE_DECL_ATTR(IBSegueAction, IBSegueAction, OnFunc, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 95) DECL_ATTR(_originallyDefinedIn, OriginallyDefinedIn, OnNominalType | OnFunc | OnVar | OnExtension, - UserInaccessible | AllowMultipleAttributes | LongAttribute | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | AllowMultipleAttributes | LongAttribute | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 96) DECL_ATTR(derivative, Derivative, OnFunc, - LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 97) DECL_ATTR(_spi, SPIAccessControl, OnAbstractFunction | OnExtension | OnGenericType | OnVar | OnSubscript | OnImport | OnAccessor | OnEnumElement | OnMacro, - AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + AllowMultipleAttributes | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr, 98) DECL_ATTR(transpose, Transpose, OnFunc, - LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + LongAttribute | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 99) SIMPLE_DECL_ATTR(noDerivative, NoDerivative, OnAbstractFunction | OnVar | OnSubscript, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 100) // Unused '101' CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor, OnClass, - DeclModifier | ConcurrencyOnly | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | ConcurrencyOnly | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 102) CONTEXTUAL_SIMPLE_DECL_ATTR(isolated, Isolated, OnDestructor, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 103) SIMPLE_DECL_ATTR(globalActor, GlobalActor, OnClass | OnStruct | OnEnum, - ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | UnreachableInABIAttr, 104) SIMPLE_DECL_ATTR(_specializeExtension, SpecializeExtension, OnExtension, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 105) CONTEXTUAL_SIMPLE_DECL_ATTR(async, Async, OnVar | OnFunc, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 106) SIMPLE_DECL_ATTR(Sendable, Sendable, OnFunc | OnConstructor | OnAccessor | OnAnyClangDecl, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 107) + SIMPLE_DECL_ATTR(_marker, Marker, OnProtocol, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 108) SIMPLE_DECL_ATTR(reasync, Reasync, OnFunc | OnConstructor, - RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + RejectByParser | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 109) SIMPLE_DECL_ATTR(reasync, AtReasync, OnProtocol, - ConcurrencyOnly | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ConcurrencyOnly | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 110) // Unused '111' CONTEXTUAL_DECL_ATTR(nonisolated, Nonisolated, OnFunc | OnConstructor | OnDestructor | OnVar | OnSubscript | OnProtocol | OnExtension | OnClass | OnStruct | OnEnum, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | UnconstrainedInABIAttr, 112) // Unused '113' SIMPLE_DECL_ATTR(_unsafeInheritExecutor, UnsafeInheritExecutor, OnFunc, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 114) SIMPLE_DECL_ATTR(_implicitSelfCapture, ImplicitSelfCapture, OnParam, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 115) SIMPLE_DECL_ATTR(_inheritActorContext, InheritActorContext, OnParam, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 116) SIMPLE_DECL_ATTR(_eagerMove, EagerMove, OnFunc | OnParam | OnVar | OnNominalType, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 117) CONTEXTUAL_SIMPLE_DECL_ATTR(distributed, DistributedActor, OnClass | OnFunc | OnAccessor | OnVar, - DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, 118) SIMPLE_DECL_ATTR(_noEagerMove, NoEagerMove, OnFunc | OnParam | OnVar | OnNominalType, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 119) SIMPLE_DECL_ATTR(_assemblyVision, EmitAssemblyVisionRemarks, OnFunc | OnNominalType, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 120) DECL_ATTR(_nonSendable, NonSendable, OnNominalType, - UserInaccessible | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + UserInaccessible | AllowMultipleAttributes | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 121) SIMPLE_DECL_ATTR(_noImplicitCopy, NoImplicitCopy, OnFunc | OnParam | OnVar, - UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove, + UserInaccessible | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 122) SIMPLE_DECL_ATTR(_noLocks, NoLocks, OnAbstractFunction | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 123) SIMPLE_DECL_ATTR(_noAllocation, NoAllocation, OnAbstractFunction | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 124) SIMPLE_DECL_ATTR(preconcurrency, Preconcurrency, OnFunc | OnConstructor | OnProtocol | OnGenericType | OnVar | OnSubscript | OnEnumElement | OnImport, - ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 125) CONTEXTUAL_SIMPLE_DECL_ATTR(_const, CompileTimeLiteral, OnParam | OnVar, - DeclModifier | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + DeclModifier | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | UnconstrainedInABIAttr, 126) DECL_ATTR(_unavailableFromAsync, UnavailableFromAsync, OnFunc | OnConstructor | OnMacro, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | ForbiddenInABIAttr, 127) DECL_ATTR(exclusivity, Exclusivity, OnVar, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 128) DECL_ATTR(backDeployed, BackDeployed, OnAbstractFunction | OnAccessor | OnSubscript | OnVar, - AllowMultipleAttributes | LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove, + AllowMultipleAttributes | LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 129) DECL_ATTR_ALIAS(_backDeploy, BackDeployed) CONTEXTUAL_SIMPLE_DECL_ATTR(_local, KnownToBeLocal, OnFunc | OnParam | OnVar, - DeclModifier | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + DeclModifier | UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 130) SIMPLE_DECL_ATTR(_moveOnly, MoveOnly, OnNominalType, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 131) SIMPLE_DECL_ATTR(_alwaysEmitConformanceMetadata, AlwaysEmitConformanceMetadata, OnProtocol, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 132) DECL_ATTR(_expose, Expose, OnFunc | OnNominalType | OnVar | OnConstructor, - AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 133) // Unused '134' SIMPLE_DECL_ATTR(_spiOnly, SPIOnly, OnImport, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 135) DECL_ATTR(_documentation, Documentation, OnAnyDecl, - UserInaccessible | APIBreakingToAdd | APIStableToRemove | ABIStableToAdd | ABIStableToRemove, + UserInaccessible | APIBreakingToAdd | APIStableToRemove | ABIStableToAdd | ABIStableToRemove | ForbiddenInABIAttr, 136) // Unused '137' SIMPLE_DECL_ATTR(_noMetadata, NoMetadata, OnGenericTypeParam, - UserInaccessible | NotSerialized | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 138) // Unused '139' CONTEXTUAL_SIMPLE_DECL_ATTR(consuming, Consuming, OnFunc | OnAccessor, - DeclModifier | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 140) CONTEXTUAL_SIMPLE_DECL_ATTR(borrowing, Borrowing, OnFunc | OnAccessor, - DeclModifier | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + DeclModifier | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 141) DECL_ATTR(attached, MacroRole, OnMacro, - AllowMultipleAttributes | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove, + AllowMultipleAttributes | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove | UnreachableInABIAttr, 142) DECL_ATTR_ALIAS(freestanding, MacroRole) SIMPLE_DECL_ATTR(_used, Used, OnAbstractFunction | OnVar, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 143) DECL_ATTR(_section, Section, OnAbstractFunction | OnVar, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | ForbiddenInABIAttr, 144) DECL_ATTR(storageRestrictions, StorageRestrictions, OnAccessor, - ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove | UnreachableInABIAttr, 145) DECL_ATTR(_rawLayout, RawLayout, OnStruct, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 146) DECL_ATTR(_extern, Extern, OnFunc, - AllowMultipleAttributes | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + AllowMultipleAttributes | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 147) SIMPLE_DECL_ATTR(_nonescapable, NonEscapable, OnNominalType, - UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | UnreachableInABIAttr, 148) SIMPLE_DECL_ATTR(_unsafeNonescapableResult, UnsafeNonEscapableResult, OnAbstractFunction | OnSubscript | OnAccessor, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, 149) // Unused '150' SIMPLE_DECL_ATTR(_staticExclusiveOnly, StaticExclusiveOnly, OnStruct, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | UnreachableInABIAttr, 151) SIMPLE_DECL_ATTR(extractConstantsFromMembers, ExtractConstantsFromMembers, OnClass | OnEnum | OnProtocol | OnStruct, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr, 152) SIMPLE_DECL_ATTR(_noRuntime, NoRuntime, OnAbstractFunction | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 153) SIMPLE_DECL_ATTR(_noExistentials, NoExistentials, OnAbstractFunction | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 154) SIMPLE_DECL_ATTR(_noObjCBridging, NoObjCBridging, OnAbstractFunction | OnSubscript, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 155) // Unused '156': Used to be `_distributedThunkTarget` but completed implementation in Swift 6.0 does not need it after all DECL_ATTR(_allowFeatureSuppression, AllowFeatureSuppression, OnAnyDecl, - UserInaccessible | NotSerialized | ABIStableToAdd | APIStableToAdd | ABIStableToRemove | APIStableToRemove, + UserInaccessible | NotSerialized | ABIStableToAdd | APIStableToAdd | ABIStableToRemove | APIStableToRemove | ForbiddenInABIAttr, 157) DECL_ATTR_ALIAS(_disallowFeatureSuppression, AllowFeatureSuppression) SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics, OnAbstractFunction | OnSubscript | OnVar | OnExtension, - UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 158) // Declares that a struct contains "sensitive" data. It enforces that the contents of such a struct value @@ -827,54 +828,54 @@ SIMPLE_DECL_ATTR(_preInverseGenerics, PreInverseGenerics, // TODO: enable @sensitive also for other nominal types than structs, e.g. for enums SIMPLE_DECL_ATTR(sensitive, Sensitive, OnStruct, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | UnreachableInABIAttr, 159) SIMPLE_DECL_ATTR(unsafe, Unsafe, OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType | OnExtension | OnTypeAlias | OnEnumElement, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 160) DECL_ATTR(lifetime, Lifetime, OnAccessor | OnConstructor | OnFunc | OnSubscript, - LongAttribute | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | AllowMultipleAttributes, + LongAttribute | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove | AllowMultipleAttributes | EquivalentInABIAttr, 161) SIMPLE_DECL_ATTR(_addressableSelf, AddressableSelf, OnAccessor | OnConstructor | OnFunc | OnSubscript, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UserInaccessible, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UserInaccessible | UnconstrainedInABIAttr, 162) SIMPLE_DECL_ATTR(_addressableForDependencies, AddressableForDependencies, OnNominalType, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UserInaccessible, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UserInaccessible | UnreachableInABIAttr, 163) SIMPLE_DECL_ATTR(safe, Safe, OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType | OnExtension | OnEnumElement, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 164) DECL_ATTR(abi, ABI, - OnAbstractFunction | OnVar, - LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove, + OnConstructor | OnFunc | OnSubscript | OnVar, + LongAttribute | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 165) DECL_ATTR_FEATURE_REQUIREMENT(ABI, ABIAttribute) DECL_ATTR(execution, Execution, OnFunc | OnConstructor | OnSubscript | OnVar, - ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | UnconstrainedInABIAttr, 166) DECL_ATTR_FEATURE_REQUIREMENT(Execution, ExecutionAttribute) SIMPLE_DECL_ATTR(const, ConstVal, OnParam | OnVar | OnFunc, - ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, 167) DECL_ATTR_FEATURE_REQUIREMENT(ConstVal, CompileTimeValues) SIMPLE_DECL_ATTR(constInitialized, ConstInitialized, OnVar, - ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove, + ABIStableToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove | EquivalentInABIAttr, 168) DECL_ATTR_FEATURE_REQUIREMENT(ConstInitialized, CompileTimeValues) diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h index 6a4d7c2cb4262..147f8a5c1f751 100644 --- a/include/swift/AST/DiagnosticEngine.h +++ b/include/swift/AST/DiagnosticEngine.h @@ -702,6 +702,10 @@ namespace swift { /// Flush the active diagnostic to the diagnostic output engine. void flush(); + /// Returns the \c SourceManager associated with \c SourceLoc s for this + /// diagnostic. + SourceManager &getSourceManager(); + /// Prevent the diagnostic from behaving more severely than \p limit. For /// instance, if \c DiagnosticBehavior::Warning is passed, an error will be /// emitted as a warning, but a note will still be emitted as a note. @@ -1561,6 +1565,10 @@ namespace swift { } }; + inline SourceManager &InFlightDiagnostic::getSourceManager() { + return Engine->SourceMgr; + } + /// Remember details about the state of a diagnostic engine and restore them /// when the object is destroyed. /// diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 47cb892f60e7d..619d8d4ce78c4 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -8351,16 +8351,16 @@ ERROR(attr_abi_mismatched_kind,none, ERROR(attr_abi_mismatched_arity,none, "cannot give %kind0 the ABI of a %kindonly0 with a different number of " - "low-level parameters", - (ValueDecl *)) + "%select{|generic }1parameters", + (Decl *, /*genericParams=*/bool)) ERROR(attr_abi_mismatched_throws,none, "cannot give %0 the ABI of a %kindonly0 which %select{cannot|can}1 throw", - (ValueDecl *, /*abiCanThrow=*/bool)) + (Decl *, /*abiCanThrow=*/bool)) ERROR(attr_abi_mismatched_async,none, "cannot give %0 the ABI of %select{a non-async|an async}1 %kindonly0", - (ValueDecl *, /*abiIsAsync=*/bool)) + (Decl *, /*abiIsAsync=*/bool)) ERROR(attr_abi_mismatched_pbd_size,none, "cannot give pattern binding the ABI of a binding with " @@ -8369,13 +8369,89 @@ ERROR(attr_abi_mismatched_pbd_size,none, ERROR(attr_abi_mismatched_var,none, "no match for %select{%kind0 in the ABI|ABI %kind0}1", - (ValueDecl *, /*isABI=*/bool)) + (Decl *, /*isABI=*/bool)) ERROR(attr_abi_incompatible_with_silgen_name,none, "cannot use '@_silgen_name' and '@abi' on the same %0 because they serve " "the same purpose", (DescriptiveDeclKind)) +ERROR(attr_abi_missing_attr,none, + "missing '%0' %select{attribute|modifier}1 in '@abi'", + (StringRef, bool)) +ERROR(attr_abi_extra_attr,none, + "extra %select{|implicit }2'%0' %select{attribute|modifier}1 in '@abi'", + (StringRef, bool, /*isImplicit=*/bool)) +ERROR(attr_abi_forbidden_attr,none, + "unused '%0' %select{attribute|modifier}1 in '@abi'", + (StringRef, bool)) +REMARK(abi_attr_inferred_attribute,none, + "inferred '%0' in '@abi' to match %select{attribute|modifier}1 on API", + (StringRef, bool)) + +ERROR(attr_abi_mismatched_attr,none, + "'%0' %select{attribute|modifier}1 in '@abi' should match '%2'", + (StringRef, bool, StringRef)) +NOTE(attr_abi_matching_attr_here,none, + "%select{should match|matches}0 %select{attribute|modifier}1 " + "%select{|implicitly added }2here", + (/*matches=*/bool, /*isModifier=*/bool, /*isImplicit=*/bool)) + +#define TYPE_ORIGIN(KIND_IDX, DECL_IDX) "%select{|%kind" #DECL_IDX " |" \ + "self parameter |result |thrown |%error}" #KIND_IDX +ERROR(attr_abi_mismatched_type,none, + TYPE_ORIGIN(0, 1) "type %2 in '@abi' should match %3", + (unsigned, Decl *, Type, Type)) +NOTE(attr_abi_should_match_type_here,none, + "should match type here", ()) + +ERROR(attr_abi_mismatched_generic_signature,none, + "generic signature '%0' in '@abi' is not compatible with '%1'", + (StringRef, StringRef)) +ERROR(attr_abi_missing_generic_signature,none, + "declaration in '@abi' should have generic signature compatible with " + "'%0'", + (StringRef)) +ERROR(attr_abi_extra_generic_signature,none, + "declaration in '@abi' should not have generic signature because %0 " + "is not generic", + (Decl *)) + +ERROR(attr_abi_mismatched_param_modifier,none, + "%select{default |}0%select{attribute|modifier}2 %select{|'%0' }0" + "on " TYPE_ORIGIN(3, 4) "in '@abi' is not compatible with " + "%select{default|'%1'}1", + (StringRef, StringRef, /*isModifier=*/bool, unsigned, Decl *)) +ERROR(attr_abi_no_default_arguments,none, + "%kind0 in '@abi' should not have a default argument; it does not " + "affect the parameter's ABI", + (Decl *)) + +// These macros insert 'final', 'non-final', or nothing depending on both the +// current decl and its counterpart, such that 'non-final' is used if the +// counterpart would be described as 'final' or 'static'. They must be kept in +// sync with `StaticnessAndFinality`. +#define NONFINAL_OR_NOTHING(COUNTERPART) \ + "%select{||non-final |non-final |non-final |%error}" #COUNTERPART +#define FINAL_OR_NONFINAL_OR_NOTHING(CURRENT, COUNTERPART, FINAL_OK) \ + "%select{|%select{" NONFINAL_OR_NOTHING(COUNTERPART) \ + "|" NONFINAL_OR_NOTHING(COUNTERPART) \ + "|final |final ||%error}" #CURRENT "}" #FINAL_OK + +ERROR(attr_abi_static_final_mismatch,none, + FINAL_OR_NONFINAL_OR_NOTHING(0, 2, 4) "%kind1 in '@abi' should be " + FINAL_OR_NONFINAL_OR_NOTHING(2, 0, 4) "%kindonly3 to ensure ABI " + "compatibility", + (uint8_t, Decl *, uint8_t, Decl *, /*isClass=*/bool)) + +#undef NONFINAL_OR_NOTHING +#undef FINAL_OR_NONFINAL_OR_NOTHING + +ERROR(attr_abi_failable_mismatch,none, + "cannot give %select{non-failable|failable}1 %kind0 the ABI of a " + "%select{non-failable|failable}2 %kindonly0", + (Decl *, bool, bool)) + //===----------------------------------------------------------------------===// // MARK: Isolated conformances //===----------------------------------------------------------------------===// diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 300107268c571..73dbd7a9fdd9b 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -2378,6 +2378,10 @@ enum class ParamSpecifier : uint8_t { StringRef getNameForParamSpecifier(ParamSpecifier name); +/// What does \c ParamSpecifier::Default mean for a parameter that's directly +/// attached to \p VD ? Pass \c nullptr for the value for a closure. +ParamSpecifier getDefaultParamSpecifier(const ValueDecl *VD); + /// Provide parameter type relevant flags, i.e. variadic, autoclosure, and /// escaping. class ParameterTypeFlags { diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 5d9cac773637b..8a73b09290079 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -269,6 +269,9 @@ namespace swift { /// Emit a remark on early exit in explicit interface build bool EnableSkipExplicitInterfaceModuleBuildRemarks = false; + /// Emit a remark when \c \@abi infers an attribute or modifier. + bool EnableABIInferenceRemarks = false; + /// /// Support for alternate usage modes /// diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 5b85213f00ed6..73f76baea1f3f 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -468,6 +468,10 @@ def remark_module_serialization : Flag<["-"], "Rmodule-serialization">, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, HelpText<"Emit remarks about module serialization">; +def remark_abi_inference : Flag<["-"], "Rabi-inference">, + Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, + HelpText<"Emit a remark when an '@abi' attribute adds an attribute or modifier to the ABI declaration based on its presence in the API">; + def emit_tbd : Flag<["-"], "emit-tbd">, HelpText<"Emit a TBD file">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>; diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index de62f634dd4f3..7af62c05439c4 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -1193,11 +1193,9 @@ getOverriddenSwiftProtocolObjCName(const ValueDecl *decl, return std::nullopt; // If there is an 'objc' attribute with a name, use that name. - if (auto objc = proto->getAttrs().getAttribute()) { - if (auto name = objc->getName()) { - llvm::SmallString<4> buffer; - return std::string(name->getString(buffer)); - } + if (auto objcName = proto->getExplicitObjCName()) { + llvm::SmallString<4> buffer; + return std::string(objcName->getString(buffer)); } return std::nullopt; @@ -3379,8 +3377,7 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn, } } -static ParamSpecifier -getDefaultOwnership(const ValueDecl *forDecl) { +ParamSpecifier swift::getDefaultParamSpecifier(const ValueDecl *forDecl) { // `consuming` is the default ownership for initializers and setters. // Everything else defaults to borrowing. if (!forDecl) { @@ -3451,7 +3448,7 @@ getParameterFlagsForMangling(ParameterTypeFlags flags, void ASTMangler::appendFunctionInputType( AnyFunctionType *fnType, ArrayRef params, GenericSignature sig, const ValueDecl *forDecl, bool isRecursedInto) { - auto defaultSpecifier = getDefaultOwnership(forDecl); + auto defaultSpecifier = getDefaultParamSpecifier(forDecl); switch (params.size()) { case 0: diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index a96e0783c5381..7beec725f5709 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -1284,6 +1284,15 @@ void PrintAST::printAttributes(const Decl *D) { // for each decl They cannot be shared across different decls. assert(Options.ExcludeCustomAttrList.empty()); + // If there is an `@abi` attr, we need to print it first so that it isn't + // affected by subsequent mutation of `Options.ExcludeAttrList`. + if (auto abiAttr = attrs.getAttribute()) { + if (Options.PrintImplicitAttrs && !Options.excludeAttr(abiAttr)) { + abiAttr->print(Printer, Options, D); + Options.ExcludeAttrList.push_back(DeclAttrKind::ABI); + } + } + if (Options.PrintSyntheticSILGenName && !D->getAttrs().hasAttribute()) { if (canPrintSyntheticSILGenName(D)) { @@ -1334,7 +1343,8 @@ void PrintAST::printAttributes(const Decl *D) { // Add SPIs to both private and package interfaces if (!Options.printPublicInterface() && DeclAttribute::canAttributeAppearOnDeclKind( - DeclAttrKind::SPIAccessControl, D->getKind())) { + DeclAttrKind::SPIAccessControl, D->getKind()) && + !Options.excludeAttrKind(DeclAttrKind::SPIAccessControl)) { interleave(D->getSPIGroups(), [&](Identifier spiName) { Printer.printAttrName("_spi", true); @@ -1358,7 +1368,7 @@ void PrintAST::printAttributes(const Decl *D) { // If the declaration is implicitly @objc, print the attribute now. if (auto VD = dyn_cast(D)) { if (VD->isObjC() && !isa(VD) && - !attrs.hasAttribute()) { + !attrs.hasAttribute() && ABIRoleInfo(D).providesAPI()) { Printer.printAttrName("@objc"); Printer << " "; } diff --git a/lib/AST/AccessRequests.cpp b/lib/AST/AccessRequests.cpp index c85aa726de7dc..996677cb07d01 100644 --- a/lib/AST/AccessRequests.cpp +++ b/lib/AST/AccessRequests.cpp @@ -43,6 +43,11 @@ AccessLevel AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const { assert(!D->hasAccess()); + // ABI decls share the access level of their API decl. + auto abiRole = ABIRoleInfo(D); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getFormalAccess(); + // Check if the decl has an explicit access control attribute. if (auto *AA = D->getAttrs().getAttribute()) return AA->getAccess(); @@ -201,6 +206,12 @@ AccessLevel SetterAccessLevelRequest::evaluate(Evaluator &evaluator, AbstractStorageDecl *ASD) const { assert(!ASD->Accessors.getInt().hasValue()); + + // ABI decls share the access level of their API decl. + auto abiRole = ABIRoleInfo(ASD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getSetterFormalAccess(); + if (auto *SAA = ASD->getAttrs().getAttribute()) return SAA->getAccess(); diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index c1713a6b6278d..61b992437d66c 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -34,6 +34,7 @@ #include "swift/Basic/Defer.h" #include "swift/Basic/QuotedString.h" #include "swift/Strings.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" @@ -58,13 +59,24 @@ static_assert(IsTriviallyDestructible::value, #Name " needs to specify either APIBreakingToAdd or APIStableToAdd"); \ static_assert(DeclAttribute::hasOneBehaviorFor##Id( \ DeclAttribute::APIBreakingToRemove | DeclAttribute::APIStableToRemove), \ - #Name " needs to specify either APIBreakingToRemove or APIStableToRemove"); + #Name " needs to specify either APIBreakingToRemove or APIStableToRemove"); \ + static_assert(DeclAttribute::hasOneBehaviorFor##Id(DeclAttribute::InABIAttrMask), \ + #Name " needs to specify exactly one of ForbiddenInABIAttr, UnconstrainedInABIAttr, EquivalentInABIAttr, InferredInABIAttr, or UnreachableInABIAttr"); #include "swift/AST/DeclAttr.def" #define TYPE_ATTR(_, Id) \ static_assert(TypeAttrKind::Id <= TypeAttrKind::Last_TypeAttr); #include "swift/AST/TypeAttr.def" +LLVM_ATTRIBUTE_USED StringRef swift::getDeclAttrKindID(DeclAttrKind kind) { + switch (kind) { +#define DECL_ATTR(_, CLASS, ...) \ + case DeclAttrKind::CLASS: \ + return #CLASS; +#include "swift/AST/DeclAttr.def" + } +} + StringRef swift::getAccessLevelSpelling(AccessLevel value) { switch (value) { case AccessLevel::Private: return "private"; @@ -392,6 +404,27 @@ bool DeclAttribute::canClone() const { } } +// Ensure that every DeclAttribute subclass implements its own isEquivalent(). +static void checkDeclAttributeIsEquivalents() { +#define DECL_ATTR(_,CLASS,...) \ + bool(CLASS##Attr::*ptr##CLASS)(const CLASS##Attr *, Decl *) const = &CLASS##Attr::isEquivalent; \ + (void)ptr##CLASS; +#include "swift/AST/DeclAttr.def" +} + +bool DeclAttribute::isEquivalent(const DeclAttribute *other, Decl *attachedTo) const { + (void)checkDeclAttributeIsEquivalents; + if (getKind() != other->getKind()) + return false; + switch (getKind()) { +#define DECL_ATTR(_,CLASS, ...) \ + case DeclAttrKind::CLASS:\ + return static_cast(this)->isEquivalent(\ + static_cast(other), attachedTo); +#include "swift/AST/DeclAttr.def" + } +} + const BackDeployedAttr * DeclAttributes::getBackDeployed(const ASTContext &ctx, bool forTargetVariant) const { @@ -1664,8 +1697,26 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, abiDecl = cast(abiDecl) ->getVarAtSimilarStructuralPosition( const_cast(cast(D))); - if (abiDecl) - abiDecl->print(Printer, Options); + if (abiDecl) { + auto optionsCopy = Options; + + // Don't print any attributes marked with `ForbiddenInABIAttr`. + // (Reminder: There is manual logic in `PrintAST::printAttributes()` + // to handle non-ABI attributes when `PrintImplicitAttrs` is set.) + for (auto rawAttrKind : range(0, unsigned(DeclAttrKind::Last_DeclAttr))) { + DeclAttrKind attrKind{rawAttrKind}; + if (!(DeclAttribute::getBehaviors(attrKind) + & DeclAttribute::ForbiddenInABIAttr)) + continue; + + if (attrKind == DeclAttrKind::AccessControl) + optionsCopy.PrintAccess = false; + else + optionsCopy.ExcludeAttrList.push_back(attrKind); + } + + abiDecl->print(Printer, optionsCopy); + } Printer << ")"; break; @@ -1730,7 +1781,7 @@ uint64_t DeclAttribute::getBehaviors(DeclAttrKind DK) { return BEHAVIORS; #include "swift/AST/DeclAttr.def" } - llvm_unreachable("bad DeclAttrKind"); + return 0; } std::optional DeclAttribute::getRequiredFeature(DeclAttrKind DK) { @@ -2121,6 +2172,26 @@ Type TypeEraserAttr::getResolvedType(const ProtocolDecl *PD) const { ErrorType::get(ctx)); } +static bool eqTypes(Type first, Type second) { + if (first.isNull() || second.isNull()) + return false; + return first->getCanonicalType() == second->getCanonicalType(); +} + +bool TypeEraserAttr::isEquivalent(const TypeEraserAttr *other, + Decl *attachedTo) const { + // Only makes sense when attached to a protocol. + auto proto = dyn_cast(attachedTo); + if (!proto) + return true; + + Type thisType = getResolvedType(proto), + otherType = other->getResolvedType(proto); + if (thisType.isNull() || otherType.isNull()) + return false; + return thisType->getCanonicalType() == otherType->getCanonicalType(); +} + Type RawLayoutAttr::getResolvedLikeType(StructDecl *sd) const { auto &ctx = sd->getASTContext(); return evaluateOrDefault(ctx.evaluator, @@ -2139,6 +2210,34 @@ Type RawLayoutAttr::getResolvedCountType(StructDecl *sd) const { ErrorType::get(ctx)); } +bool RawLayoutAttr::isEquivalent(const RawLayoutAttr *other, + Decl *attachedTo) const { + if (shouldMoveAsLikeType() != other->shouldMoveAsLikeType()) + return false; + + if (auto thisSizeAndAlignment = getSizeAndAlignment()) + return thisSizeAndAlignment == other->getSizeAndAlignment(); + + auto SD = dyn_cast(attachedTo); + if (!SD) + return true; + + if (auto thisScalarLikeType = getResolvedScalarLikeType(SD)) { + auto otherScalarLikeType = other->getResolvedScalarLikeType(SD); + return otherScalarLikeType && eqTypes(*thisScalarLikeType, + *otherScalarLikeType); + } + + if (auto thisArrayLikeTypes = getResolvedArrayLikeTypeAndCount(SD)) { + auto otherArrayLikeTypes = other->getResolvedArrayLikeTypeAndCount(SD); + return otherArrayLikeTypes + && eqTypes(thisArrayLikeTypes->first, otherArrayLikeTypes->first) + && eqTypes(thisArrayLikeTypes->second, otherArrayLikeTypes->second); + } + + llvm_unreachable("unknown variant of RawLayoutAttr"); +} + AvailableAttr::AvailableAttr( SourceLoc AtLoc, SourceRange Range, AvailabilityDomainOrIdentifier DomainOrIdentifier, SourceLoc DomainLoc, @@ -2246,6 +2345,19 @@ AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const { implicit ? SourceRange() : ObsoletedRange, implicit, isSPI()); } +bool AvailableAttr::isEquivalent(const AvailableAttr *other, + Decl *attachedTo) const { + return getRawIntroduced() == other->getRawIntroduced() + && getRawDeprecated() == other->getRawDeprecated() + && getRawObsoleted() == other->getRawObsoleted() + && getMessage() == other->getMessage() + && getRename() == other->getRename() + && isSPI() == other->isSPI() + && getKind() == other->getKind() + && attachedTo->getSemanticAvailableAttr(this)->getDomain() + == attachedTo->getSemanticAvailableAttr(other)->getDomain(); +} + static StringRef getManglingModuleName(StringRef OriginalModuleName) { auto index = OriginalModuleName.find(";"); return index == StringRef::npos @@ -2448,6 +2560,69 @@ GenericSignature SpecializeAttr::getSpecializedSignature( nullptr); } +/// Checks whether \p first and \p second have the same elements according to +/// \p eq , ignoring the order those elements are in but considering the number +/// of repetitions. +template +bool sameElements(ArrayRef first, ArrayRef second, Eq eq) { + if (first.size() != second.size()) + return false; + + llvm::SmallSet claimedSecondIndices; + + for (auto firstElem : first) { + bool found = false; + for (auto i : indices(second)) { + if (!eq(firstElem, second[i]) || claimedSecondIndices.count(i)) + continue; + + found = true; + claimedSecondIndices.insert(i); + break; + } + + if (!found) + return false; + } + + return true; +} + +/// Checks whether \p first and \p second have the same elements, ignoring the +/// order those elements are in but considering the number of repetitions. +template +bool sameElements(ArrayRef first, ArrayRef second) { + return sameElements(first, second, std::equal_to()); +} + +bool SpecializeAttr::isEquivalent(const SpecializeAttr *other, + Decl *attachedTo) const { + if (isExported() != other->isExported() || + getSpecializationKind() != other->getSpecializationKind() || + getTargetFunctionName() != other->getTargetFunctionName() || + specializedSignature.getCanonicalSignature() != + other->specializedSignature.getCanonicalSignature()) + return false; + + if (!sameElements(getSPIGroups(), other->getSPIGroups())) + return false; + + SmallVector thisTypeErasedParams, otherTypeErasedParams; + for (auto ty : getTypeErasedParams()) + thisTypeErasedParams.push_back(ty->getCanonicalType()); + for (auto ty : other->getTypeErasedParams()) + otherTypeErasedParams.push_back(ty->getCanonicalType()); + + if (!sameElements(ArrayRef(thisTypeErasedParams), + ArrayRef(otherTypeErasedParams))) + return false; + + return sameElements(getAvailableAttrs(), other->getAvailableAttrs(), + [=](AvailableAttr *thisAttr, AvailableAttr *otherAttr) { + return thisAttr->isEquivalent(otherAttr, attachedTo); + }); +} + SPIAccessControlAttr::SPIAccessControlAttr(SourceLoc atLoc, SourceRange range, ArrayRef spiGroups) : DeclAttribute(DeclAttrKind::SPIAccessControl, atLoc, range, @@ -2476,6 +2651,11 @@ SPIAccessControlAttr *SPIAccessControlAttr::clone(ASTContext &C, return attr; } +bool SPIAccessControlAttr::isEquivalent(const SPIAccessControlAttr *other, + Decl *attachedTo) const { + return sameElements(getSPIGroups(), other->getSPIGroups()); +} + DifferentiableAttr::DifferentiableAttr(bool implicit, SourceLoc atLoc, SourceRange baseRange, enum DifferentiabilityKind diffKind, @@ -2712,11 +2892,18 @@ StorageRestrictionsAttr::create( /*implicit=*/false); } -ImplementsAttr::ImplementsAttr(SourceLoc atLoc, SourceRange range, - TypeRepr *TyR, DeclName MemberName, - DeclNameLoc MemberNameLoc) +bool StorageRestrictionsAttr:: +isEquivalent(const StorageRestrictionsAttr *other, Decl *attachedTo) const { + return sameElements(getAccessesNames(), other->getAccessesNames()) + && sameElements(getInitializesNames(), other->getInitializesNames()); +} + +ImplementsAttr:: +ImplementsAttr(SourceLoc atLoc, SourceRange range, + llvm::PointerUnion TyROrDC, + DeclName MemberName, DeclNameLoc MemberNameLoc) : DeclAttribute(DeclAttrKind::Implements, atLoc, range, /*Implicit=*/false), - TyR(TyR), MemberName(MemberName), MemberNameLoc(MemberNameLoc) {} + TyROrDC(TyROrDC), MemberName(MemberName), MemberNameLoc(MemberNameLoc) {} ImplementsAttr *ImplementsAttr::create(ASTContext &Ctx, SourceLoc atLoc, SourceRange range, @@ -2733,9 +2920,8 @@ ImplementsAttr *ImplementsAttr::create(DeclContext *DC, DeclName MemberName) { auto &ctx = DC->getASTContext(); void *mem = ctx.Allocate(sizeof(ImplementsAttr), alignof(ImplementsAttr)); - auto *attr = new (mem) ImplementsAttr( - SourceLoc(), SourceRange(), nullptr, - MemberName, DeclNameLoc()); + auto *attr = new (mem) ImplementsAttr(SourceLoc(), SourceRange(), DC, + MemberName, DeclNameLoc()); ctx.evaluator.cacheOutput(ImplementsAttrProtocolRequest{attr, DC}, std::move(Proto)); return attr; @@ -2754,6 +2940,13 @@ ImplementsAttr::getCachedProtocol(DeclContext *dc) const { return std::nullopt; } +bool ImplementsAttr::isEquivalent(const ImplementsAttr *other, + Decl *attachedTo) const { + auto DC = attachedTo->getDeclContext(); + return getMemberName() == other->getMemberName() + && getProtocol(DC) == other->getProtocol(DC); +} + CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type, CustomAttributeInitializer *initContext, ArgumentList *argList, bool implicit) @@ -2822,6 +3015,14 @@ bool CustomAttr::isArgUnsafe() const { return isArgUnsafeBit; } +bool CustomAttr::isEquivalent(const CustomAttr *other, Decl *attachedTo) const { + // For the sake of both @abi checking and implementability, we're going to + // ignore expressions in the arguments and initializer. + + return isArgUnsafe() == other->isArgUnsafe() && eqTypes(getType(), + other->getType()); +} + MacroRoleAttr::MacroRoleAttr(SourceLoc atLoc, SourceRange range, MacroSyntax syntax, SourceLoc lParenLoc, MacroRole role, @@ -2949,12 +3150,27 @@ AllowFeatureSuppressionAttr *AllowFeatureSuppressionAttr::create( AllowFeatureSuppressionAttr(atLoc, range, implicit, inverted, features); } +bool AllowFeatureSuppressionAttr:: +isEquivalent(const AllowFeatureSuppressionAttr *other, Decl *attachedTo) const { + if (getInverted() != other->getInverted()) + return false; + + return sameElements(getSuppressedFeatures(), other->getSuppressedFeatures()); +} + LifetimeAttr *LifetimeAttr::create(ASTContext &context, SourceLoc atLoc, SourceRange baseRange, bool implicit, LifetimeEntry *entry) { return new (context) LifetimeAttr(atLoc, baseRange, implicit, entry); } +bool LifetimeAttr::isEquivalent(const LifetimeAttr *other, + Decl *attachedTo) const { + // FIXME: This is kind of cheesy. + return getLifetimeEntry()->getString() + == other->getLifetimeEntry()->getString(); +} + void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) { if (attr) attr->print(out); diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 5aa08cc6f99b3..af8113a89050d 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -411,6 +411,11 @@ bool Decl::isAvailableAsSPI() const { SemanticAvailableAttributes Decl::getSemanticAvailableAttrs(bool includeInactive) const { + // A decl in an @abi gets its availability from the decl it's attached to. + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getSemanticAvailableAttrs(includeInactive); + return SemanticAvailableAttributes(getAttrs(), this, includeInactive); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 7953bba24d572..61dc314cbeace 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -4156,6 +4156,10 @@ void ValueDecl::setIsObjC(bool value) { } Identifier ExtensionDecl::getObjCCategoryName() const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCCategoryName(); + // If there's an @objc attribute, it's authoritative. (ClangImporter // attaches one automatically.) if (auto objcAttr = getAttrs().getAttribute(/*AllowInvalid*/true)) { @@ -4409,6 +4413,10 @@ StringRef ValueDecl::getCDeclName() const { return clangDecl->getName(); } + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getCDeclName(); + // Handle explicit cdecl attributes. if (auto cdeclAttr = getAttrs().getAttribute()) { return cdeclAttr->Name; @@ -4445,6 +4453,18 @@ ValueDecl::getObjCRuntimeName(bool skipIsObjCResolution) const { return std::nullopt; } +std::optional +Decl::getExplicitObjCName(bool allowInvalid) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getExplicitObjCName(); + + auto objcAttr = getAttrs().getAttribute(allowInvalid); + if (objcAttr && !objcAttr->isNameImplicit()) + return objcAttr->getName(); + return std::nullopt; +} + bool ValueDecl::canInferObjCFromRequirement(ValueDecl *requirement) { // Only makes sense for a requirement of an @objc protocol. auto proto = cast(requirement->getDeclContext()); @@ -4457,9 +4477,8 @@ bool ValueDecl::canInferObjCFromRequirement(ValueDecl *requirement) { // If there is already an @objc attribute with an explicit name, we // can't infer a name (it's already there). - if (auto objcAttr = getAttrs().getAttribute()) { - if (objcAttr->hasName() && !objcAttr->isNameImplicit()) - return false; + if (getExplicitObjCName().has_value()) { + return false; } // If the nominal type doesn't conform to the protocol at all, we @@ -4700,6 +4719,11 @@ SourceLoc Decl::getAttributeInsertionLoc(bool forModifier) const { bool ValueDecl::isUsableFromInline() const { assert(getFormalAccess() < AccessLevel::Public); + // ABI decls share the access level of their API decl. + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->isUsableFromInline(); + if (getAttrs().hasAttribute() || getAttrs().hasAttribute() || getAttrs().hasAttribute()) @@ -5134,6 +5158,10 @@ static bool checkAccessUsingAccessScopes(const DeclContext *useDC, static bool isObjCMemberImplementation(const ValueDecl *VD, llvm::function_ref getAccessLevel) { + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return isObjCMemberImplementation(abiRole.getCounterpart(), getAccessLevel); + if (auto ED = dyn_cast(VD->getDeclContext())) if (ED->isObjCImplementation() && !isa(VD)) { auto attrDecl = isa(VD) @@ -6613,6 +6641,10 @@ static StringRef mangleObjCRuntimeName(const NominalTypeDecl *nominal, StringRef ClassDecl::getObjCRuntimeName( llvm::SmallVectorImpl &buffer) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCRuntimeName(buffer); + // If there is a Clang declaration, use it's runtime name. if (auto objcClass = dyn_cast_or_null(getClangDecl())) @@ -7121,6 +7153,10 @@ ProtocolDecl::getPrimaryAssociatedTypes() const { StringRef ProtocolDecl::getObjCRuntimeName( llvm::SmallVectorImpl &buffer) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCRuntimeName(buffer); + // If there is an 'objc' attribute with a name, use that name. if (auto objc = getAttrs().getAttribute()) { if (auto name = objc->getName()) @@ -7593,6 +7629,10 @@ getNameFromObjcAttribute(const ObjCAttr *attr, DeclName preferredName) { ObjCSelector AbstractStorageDecl::getObjCGetterSelector(Identifier preferredName) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCGetterSelector(preferredName); + // If the getter has an @objc attribute with a name, use that. if (auto getter = getAccessor(AccessorKind::Get)) { if (auto name = getNameFromObjcAttribute(getter->getAttrs(). @@ -7623,6 +7663,10 @@ AbstractStorageDecl::getObjCGetterSelector(Identifier preferredName) const { ObjCSelector AbstractStorageDecl::getObjCSetterSelector(Identifier preferredName) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCSetterSelector(preferredName); + // If the setter has an @objc attribute with a name, use that. auto setter = getAccessor(AccessorKind::Set); auto objcAttr = setter ? setter->getAttrs().getAttribute() @@ -7874,14 +7918,19 @@ SourceRange VarDecl::getSourceRange() const { return getNameLoc(); } -SourceRange VarDecl::getTypeSourceRangeForDiagnostics() const { +SourceRange AbstractStorageDecl::getTypeSourceRangeForDiagnostics() const { + // Subscripts always have an explicitly-written type. + if (auto *SD = dyn_cast(this)) + return SD->getElementTypeSourceRange(); + // For a parameter, map back to its parameter to get the TypeLoc. if (auto *PD = dyn_cast(this)) { if (auto typeRepr = PD->getTypeRepr()) return typeRepr->getSourceRange(); } - - Pattern *Pat = getParentPattern(); + + auto *VD = cast(this); + Pattern *Pat = VD->getParentPattern(); if (!Pat || Pat->isImplicit()) return SourceRange(); @@ -8605,6 +8654,10 @@ Type VarDecl::getPropertyWrapperInitValueInterfaceType() const { } Identifier VarDecl::getObjCPropertyName() const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCPropertyName(); + if (auto attr = getAttrs().getAttribute()) { if (auto name = attr->getName()) return name->getSelectorPieces()[0]; @@ -10209,6 +10262,11 @@ AbstractFunctionDecl::getBodyFingerprintIncludingLocalTypeMembers() const { ObjCSelector AbstractFunctionDecl::getObjCSelector(DeclName preferredName, bool skipIsObjCResolution) const { + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getObjCSelector(preferredName, + skipIsObjCResolution); + // FIXME: Forces computation of the Objective-C selector. if (!skipIsObjCResolution) (void)isObjC(); @@ -11640,7 +11698,12 @@ bool ClassDecl::isNonDefaultExplicitDistributedActor(ModuleDecl *M, bool ClassDecl::isNativeNSObjectSubclass() const { // @objc actors implicitly inherit from NSObject. if (isActor()) { - if (getAttrs().hasAttribute()) { + DeclAttributes attrs = getAttrs(); + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + attrs = abiRole.getCounterpart()->getAttrs(); + + if (attrs.hasAttribute()) { return true; } ClassDecl *superclass = getSuperclassDecl(); diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index eba98b6bbaa5c..f8ed0c23c6850 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -3165,6 +3165,11 @@ SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const { assert (isa(decl) || isa(decl)); + // ABI decls share the SPI groups of their API decl. + auto abiRole = ABIRoleInfo(decl); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getSPIGroups(); + // First, look for local attributes. llvm::SetVector spiGroups; for (auto attr : decl->getAttrs().getAttributes()) diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index d806ce0499ec2..77c1e16fe3fce 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -1546,7 +1546,7 @@ void MemberLookupTable::addMember(Decl *member) { A->getMemberName().addToLookupTable(Lookup, vd); auto abiRole = ABIRoleInfo(vd); - if (!abiRole.providesABI()) + if (!abiRole.providesABI() && abiRole.getCounterpart()) addMember(abiRole.getCounterpart()); } diff --git a/lib/AST/SwiftNameTranslation.cpp b/lib/AST/SwiftNameTranslation.cpp index 934c4db467dee..f675c536dcac7 100644 --- a/lib/AST/SwiftNameTranslation.cpp +++ b/lib/AST/SwiftNameTranslation.cpp @@ -37,6 +37,10 @@ getNameForObjC(const ValueDecl *VD, CustomNamesOnly_t customNamesOnly) { assert(isa(VD) || isa(VD) || isa(VD) || isa(VD) || isa(VD) || isa(VD)); + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return getNameForObjC(abiRole.getCounterpart(), customNamesOnly); + if (auto objc = VD->getAttrs().getAttribute()) { if (auto name = objc->getName()) { assert(name->getNumSelectorPieces() == 1); @@ -63,6 +67,10 @@ getErrorDomainStringForObjC(const EnumDecl *ED) { // Should have already been diagnosed as diag::objc_enum_generic. assert(!ED->isGenericContext() && "Trying to bridge generic enum error to Obj-C"); + auto abiRole = ABIRoleInfo(ED); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return getErrorDomainStringForObjC(abiRole.getCounterpart()); + SmallVector outerTypes; for (const NominalTypeDecl * D = ED; D != nullptr; @@ -86,6 +94,11 @@ getErrorDomainStringForObjC(const EnumDecl *ED) { bool swift::objc_translation:: printSwiftEnumElemNameInObjC(const EnumElementDecl *EL, llvm::raw_ostream &OS, Identifier PreferredName) { + auto abiRole = ABIRoleInfo(EL); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return printSwiftEnumElemNameInObjC(abiRole.getCounterpart(), OS, + PreferredName); + StringRef ElemName = getNameForObjC(EL, CustomNamesOnly); if (!ElemName.empty()) { OS << ElemName; @@ -104,6 +117,10 @@ printSwiftEnumElemNameInObjC(const EnumElementDecl *EL, llvm::raw_ostream &OS, std::pair swift::objc_translation:: getObjCNameForSwiftDecl(const ValueDecl *VD, DeclName PreferredName){ + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return getObjCNameForSwiftDecl(abiRole.getCounterpart(), PreferredName); + ASTContext &Ctx = VD->getASTContext(); Identifier BaseName; if (PreferredName) { @@ -157,6 +174,10 @@ isVisibleToObjC(const ValueDecl *VD, AccessLevel minRequiredAccess, StringRef swift::cxx_translation::getNameForCxx(const ValueDecl *VD, CustomNamesOnly_t customNamesOnly) { + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return getNameForCxx(abiRole.getCounterpart(), customNamesOnly); + ASTContext& ctx = VD->getASTContext(); for (auto *EA : VD->getAttrs().getAttributes()) { @@ -214,6 +235,10 @@ swift::cxx_translation::DeclRepresentation swift::cxx_translation::getDeclRepresentation( const ValueDecl *VD, std::optional> isZeroSized) { + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return getDeclRepresentation(abiRole.getCounterpart(), isZeroSized); + if (getActorIsolation(const_cast(VD)).isActorIsolated()) return {Unsupported, UnrepresentableIsolatedInActor}; if (isa(VD)) diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index 124329d967f81..d20c0b72d453f 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -356,7 +356,8 @@ void IsDynamicRequest::cacheResult(bool value) const { decl->setIsDynamic(value); // Add an attribute for printing - if (value && !decl->getAttrs().hasAttribute()) + if (value && !decl->getAttrs().hasAttribute() && + ABIRoleInfo(decl).providesAPI()) decl->getAttrs().add(new (decl->getASTContext()) DynamicAttr(/*Implicit=*/true)); } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index e694108488f63..8eadf227e0591 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -6594,6 +6594,9 @@ findFunctionInterfaceAndImplementation(AbstractFunctionDecl *func) { ObjCInterfaceAndImplementation ObjCInterfaceAndImplementationRequest:: evaluate(Evaluator &evaluator, Decl *decl) const { + ASSERT(ABIRoleInfo(decl).providesAPI() + && "@interface request for ABI-only decl?"); + // Types and extensions have direct links to their counterparts through the // `@_objcImplementation` attribute. Let's resolve that. // (Also directing nulls here, where they'll early-return.) @@ -6633,6 +6636,21 @@ llvm::TinyPtrVector Decl::getAllImplementedObjCDecls() const { // This *is* the interface, if there is one. return {}; + // ABI-only attributes don't have an `@implementation`, so query the API + // counterpart and map the results back to ABI decls. + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) { + auto interfaceDecls = + abiRole.getCounterpart()->getAllImplementedObjCDecls(); + + // Map the APIs back to their ABI counterparts (often a no-op) + for (auto &interfaceDecl : interfaceDecls) { + interfaceDecl = ABIRoleInfo(interfaceDecl).getCounterpart(); + } + + return interfaceDecls; + } + ObjCInterfaceAndImplementationRequest req{const_cast(this)}; auto result = evaluateOrDefault(getASTContext().evaluator, req, {}); return result.interfaceDecls; @@ -6650,6 +6668,14 @@ Decl *Decl::getObjCImplementationDecl() const { // This *is* the implementation, if it has one. return nullptr; + // ABI-only attributes don't have an `@implementation`, so query the API + // counterpart and map the results back to ABI decls. + auto abiRole = ABIRoleInfo(this); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) { + auto implDecl = abiRole.getCounterpart()->getObjCImplementationDecl(); + return ABIRoleInfo(implDecl).getCounterpart(); + } + ObjCInterfaceAndImplementationRequest req{const_cast(this)}; auto result = evaluateOrDefault(getASTContext().evaluator, req, {}); return result.implementationDecl; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9f3ebf072677f..a334b66bd25df 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1422,6 +1422,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.EnableSkipExplicitInterfaceModuleBuildRemarks = Args.hasArg(OPT_remark_skip_explicit_interface_build); + Opts.EnableABIInferenceRemarks = Args.hasArg(OPT_remark_abi_inference); + if (Args.hasArg(OPT_experimental_skip_non_exportable_decls)) { // Only allow -experimental-skip-non-exportable-decls if either library // evolution is enabled (in which case the module's ABI is independent of diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 7b770e0717c5a..2a85b94c3779c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -2189,7 +2189,7 @@ Parser::parseAllowFeatureSuppressionAttribute(bool inverted, SourceLoc atLoc, auto range = SourceRange(loc, parensRange.End); return makeParserResult(AllowFeatureSuppressionAttr::create( - Context, loc, range, /*implicit*/ false, /*inverted*/ inverted, + Context, atLoc, range, /*implicit*/ false, /*inverted*/ inverted, features)); } @@ -9776,10 +9776,23 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc, Decls.push_back(Subscript); + bool Invalid = false; + // Reject 'subscript' functions outside of type decls + if (!(Flags & PD_HasContainerType)) { + diagnose(SubscriptLoc, diag::subscript_decl_wrong_scope); + Invalid = true; + } + // '{' // Parse getter and setter. ParsedAccessors accessors; if (Tok.isNot(tok::l_brace)) { + // Subscript stubs should never have accessors, and this one doesn't, so + // we're done. + if (Flags.contains(PD_StubOnly)) { + return makeParserResult(Status, Subscript); + } + // Subscript declarations must always have at least a getter, so they need // to be followed by a {. if (!Status.isErrorOrHasCompletion()) { @@ -9796,13 +9809,6 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc, Subscript); } - bool Invalid = false; - // Reject 'subscript' functions outside of type decls - if (!(Flags & PD_HasContainerType)) { - diagnose(SubscriptLoc, diag::subscript_decl_wrong_scope); - Invalid = true; - } - accessors.record(*this, Subscript, (Invalid || !Status.isSuccess() || Status.hasCodeCompletion())); diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 56fa11d92b8f7..c8c714fef2149 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -451,6 +451,7 @@ static LinkageLimit getLinkageLimit(SILDeclRef constant) { using Kind = SILDeclRef::Kind; auto *d = constant.getDecl(); + ASSERT(ABIRoleInfo(d).providesAPI() && "getLinkageLimit() for ABI decl?"); // Back deployment thunks and fallbacks are emitted into the client. if (constant.backDeploymentKind != SILDeclRef::BackDeploymentKind::None) @@ -1267,6 +1268,9 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const { if (auto *ACE = getAbstractClosureExpr()) return mangler.mangleClosureEntity(ACE, SKind); + ASSERT(ABIRoleInfo(getDecl()).providesAPI() + && "SILDeclRef mangling ABI decl directly?"); + // As a special case, functions can have manually mangled names. // Use the SILGen name only for the original non-thunked, non-curried entry // point. diff --git a/lib/SIL/IR/SILFunctionBuilder.cpp b/lib/SIL/IR/SILFunctionBuilder.cpp index 74647128c2872..b15f75b4645c8 100644 --- a/lib/SIL/IR/SILFunctionBuilder.cpp +++ b/lib/SIL/IR/SILFunctionBuilder.cpp @@ -377,6 +377,9 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction( if (auto *accessor = dyn_cast(decl)) { auto *storage = accessor->getStorage(); // Add attributes for e.g. computed properties. + ASSERT(ABIRoleInfo(storage).providesAPI() + && "addFunctionAttributes() on ABI-only accessor?"); + addFunctionAttributes(F, storage->getAttrs(), mod, getOrCreateDeclaration); @@ -395,6 +398,8 @@ SILFunction *SILFunctionBuilder::getOrCreateFunction( F->setInlineStrategy(NoInline); } } + ASSERT(ABIRoleInfo(decl).providesAPI() + && "addFunctionAttributes() on ABI-only decl?"); addFunctionAttributes(F, decl->getAttrs(), mod, getOrCreateDeclaration, constant); } diff --git a/lib/SIL/IR/SILSymbolVisitor.cpp b/lib/SIL/IR/SILSymbolVisitor.cpp index f58c424180c53..b45b48d7202ad 100644 --- a/lib/SIL/IR/SILSymbolVisitor.cpp +++ b/lib/SIL/IR/SILSymbolVisitor.cpp @@ -491,6 +491,9 @@ class SILSymbolVisitorImpl : public ASTVisitor { addFunction(SILDeclRef(AFD)); + ASSERT(ABIRoleInfo(AFD).providesAPI() + && "SILSymbolVisitorImpl visiting ABI-only decl?"); + if (auto dynKind = getDynamicKind(AFD)) { // Add the global function pointer for a dynamically replaceable function. Visitor.addDynamicFunction(AFD, *dynKind); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 0bd0a03e244ef..1a85e274fa077 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -1439,6 +1439,9 @@ void SILGenModule::emitAbstractFuncDecl(AbstractFunctionDecl *AFD) { // Emit default arguments and property wrapper initializers. emitArgumentGenerators(AFD, AFD->getParameters()); + ASSERT(ABIRoleInfo(AFD).providesAPI() + && "emitAbstractFuncDecl() on ABI-only decl?"); + // If the declaration is exported as a C function, emit its native-to-foreign // thunk too, if it wasn't already forced. if (AFD->getAttrs().hasAttribute()) { diff --git a/lib/Sema/AssociatedTypeInference.cpp b/lib/Sema/AssociatedTypeInference.cpp index 31a5c3285c1f6..720343abcca7e 100644 --- a/lib/Sema/AssociatedTypeInference.cpp +++ b/lib/Sema/AssociatedTypeInference.cpp @@ -3724,15 +3724,12 @@ bool AssociatedTypeInference::diagnoseNoSolutions( failed.Result.getKind() != CheckTypeWitnessResult::Superclass) { Type resultType; SourceRange typeRange; - if (auto *var = dyn_cast(failed.Witness)) { - resultType = var->getValueInterfaceType(); - typeRange = var->getTypeSourceRangeForDiagnostics(); + if (auto *storage = dyn_cast(failed.Witness)) { + resultType = storage->getValueInterfaceType(); + typeRange = storage->getTypeSourceRangeForDiagnostics(); } else if (auto *func = dyn_cast(failed.Witness)) { resultType = func->getResultInterfaceType(); typeRange = func->getResultTypeSourceRange(); - } else if (auto *subscript = dyn_cast(failed.Witness)) { - resultType = subscript->getElementInterfaceType(); - typeRange = subscript->getElementTypeSourceRange(); } // If the type witness was inferred from an existential diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 57df045386821..103435fa20d90 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -50,6 +50,7 @@ add_swift_host_library(swiftSema STATIC TypeOfReference.cpp TypeCheckAccess.cpp TypeCheckAttr.cpp + TypeCheckAttrABI.cpp TypeCheckAvailability.cpp TypeCheckBitwise.cpp TypeCheckCaptures.cpp diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index e3fc30db24619..1a6151c727c08 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -195,68 +195,10 @@ class AttributeChecker : public AttributeVisitor { IGNORED_ATTR(Unsafe) #undef IGNORED_ATTR -private: - static unsigned getABIArity(AbstractFunctionDecl *afd) { - unsigned arity = afd->getParameters()->size(); - arity += afd->getGenericSignature().getGenericParams().size(); - if (afd->hasImplicitSelfDecl()) - arity += 1; - return arity; - } - - void checkABIAttrPBD(PatternBindingDecl *APBD, VarDecl *VD) { - auto PBD = VD->getParentPatternBinding(); - - // To make sure we only diagnose this stuff once, check that VD is the first - // anchoring variable in the PBD. - bool isFirstAnchor = false; - for (auto i : range(PBD->getNumPatternEntries())) { - auto anchorVD = PBD->getAnchoringVarDecl(i); - if (anchorVD) { - isFirstAnchor = (anchorVD == VD); - break; - } - } - - if (!isFirstAnchor) - return; - - // Check that the PBDs have the same number of patterns. - if (PBD->getNumPatternEntries() < APBD->getNumPatternEntries()) { - diagnose(APBD->getPattern(PBD->getNumPatternEntries())->getLoc(), - diag::attr_abi_mismatched_pbd_size, /*abiHasExtra=*/false); - return; - } - if (PBD->getNumPatternEntries() > APBD->getNumPatternEntries()) { - diagnose(PBD->getPattern(APBD->getNumPatternEntries())->getLoc(), - diag::attr_abi_mismatched_pbd_size, /*abiHasExtra=*/true); - return; - } - - // Check that each pattern has the same number of variables. - for (auto i : range(PBD->getNumPatternEntries())) { - SmallVector VDs; - SmallVector AVDs; - - PBD->getPattern(i)->collectVariables(VDs); - APBD->getPattern(i)->collectVariables(AVDs); - - if (VDs.size() < AVDs.size()) { - for (auto AVD : drop_begin(AVDs, VDs.size())) { - AVD->diagnose(diag::attr_abi_mismatched_var, - AVD, /*isABI=*/true); - } - } - else if (VDs.size() > AVDs.size()) { - for (auto VD : drop_begin(VDs, AVDs.size())) { - VD->diagnose(diag::attr_abi_mismatched_var, - VD, /*isABI=*/false); - } - } - } + void visitABIAttr(ABIAttr *attr) { + TypeChecker::checkDeclABIAttribute(D, attr); } -public: void visitExecutionAttr(ExecutionAttr *attr) { auto *const decl = cast(D); @@ -300,81 +242,6 @@ class AttributeChecker : public AttributeVisitor { } } - void visitABIAttr(ABIAttr *attr) { - Decl *AD = attr->abiDecl; - if (isa(D) && isa(AD)) { - auto VD = cast(D); - auto APBD = cast(AD); - - // Diagnose dissimilar PBD structures. - checkABIAttrPBD(APBD, VD); - - // Do the rest of this checking on the corresponding VarDecl, not the - // PBD that's actually in the attribute. Note that `AD` will become null - // if they're too dissimilar to match up. - AD = APBD->getVarAtSimilarStructuralPosition(VD); - } - // TODO: EnumElementDecl? - - if (!AD) - return; - - // Check the ABI decl and bail if there was a problem with it. - TypeChecker::typeCheckDecl(AD); - if (AD->isInvalid()) - return; - - // Do the declarations have the same kind, broadly speaking? Many kinds have - // special mangling behavior (e.g. inits vs normal funcs) that make it - // unrealistic to treat one kind as though it were another. - if (D->getKind() != AD->getKind()) { - // FIXME: DescriptiveDeclKind is overly specific; we really just want to - // say that e.g. a `func` can't have the ABI of a `var`. - diagnoseAndRemoveAttr(attr, diag::attr_abi_mismatched_kind, - D, AD->getDescriptiveKind()); - return; - } - - if (isa(D)) { - auto AFD = cast(D); - auto AAFD = cast(AD); - - // FIXME: How much should we diagnose in IRGen for more precise ABI info? - - // Do the declarations have roughly the same number of parameters? We'll - // allow some fuzziness for what these parameters *are*, since there isn't - // always an ABI difference between e.g. a free function with N parameters - // and an instance method with N-1 parameters (plus an implicit `self`). - if (getABIArity(AFD) != getABIArity(AAFD)) { - diagnoseAndRemoveAttr(attr, diag::attr_abi_mismatched_arity, - AFD); - } - - // Do the declarations match in throwing behavior? We don't care about - // `throws` vs. `rethrows` here, just whether callers will account for an - // error return. - // FIXME: Typed throws? - if (AFD->hasThrows() != AAFD->hasThrows()) { - diagnoseAndRemoveAttr(attr, diag::attr_abi_mismatched_throws, - AFD, /*abiCanThrow=*/AAFD->hasThrows()); - } - - // Do the declarations match in async-ness? - if (AFD->hasAsync() != AAFD->hasAsync()) { - diagnoseAndRemoveAttr(attr, diag::attr_abi_mismatched_async, - AFD, /*abiHasAsync=*/AAFD->hasAsync()); - } - } - - // TODO: Diagnose if Protocol::isMarkerProtocol() - contradiction in terms - // (and mangler can't handle invertible protocols with @abi) - - // TODO: Validate more - // FIXME: The list of properties that have to match is practically endless - // and will grow as new features are added to the compiler. We might want to - // write an AttributeVisitor just to help us catch omissions over time. - } - void visitAlignmentAttr(AlignmentAttr *attr) { // Alignment must be a power of two. auto value = attr->getValue(); @@ -1795,6 +1662,10 @@ static SourceRange getArgListRange(ASTContext &Ctx, DeclAttribute *attr) { void AttributeChecker:: visitObjCImplementationAttr(ObjCImplementationAttr *attr) { + // If `D` is ABI-only, let ABIDeclChecker diagnose the bad attribute. + if (!ABIRoleInfo(D).providesAPI()) + return; + DeclAttribute * langAttr = D->getAttrs().getAttribute(/*AllowInvalid=*/true); if (!langAttr) @@ -5267,7 +5138,8 @@ void AttributeChecker::checkBackDeployedAttrs( } if (auto *AFD = dyn_cast(D)) { - if (!AFD->hasBody()) { + // Ignore this for ABI-only decls; ABIDeclChecker will diagnose it better. + if (!AFD->hasBody() && ABIRoleInfo(AFD).providesAPI()) { diagnoseAndRemoveAttr(Attr, diag::back_deployed_requires_body, Attr, VD); continue; @@ -6800,6 +6672,12 @@ static bool typeCheckDerivativeAttr(DerivativeAttr *attr) { // Note: Implementation must be idempotent because it may be called multiple // times for the same attribute. Decl *D = attr->getOriginalDeclaration(); + + // ABI-only decls can't have @derivative; bail out and let ABIDeclChecker + // diagnose this. + if (!ABIRoleInfo(D).providesAPI()) + return false; + auto &Ctx = D->getASTContext(); auto &diags = Ctx.Diags; // `@derivative` attribute requires experimental differentiable programming diff --git a/lib/Sema/TypeCheckAttrABI.cpp b/lib/Sema/TypeCheckAttrABI.cpp new file mode 100644 index 0000000000000..d81c018ed7faa --- /dev/null +++ b/lib/Sema/TypeCheckAttrABI.cpp @@ -0,0 +1,1205 @@ +//===--- TypeCheckAttrABI.cpp - Type Checking for @abi Attribute ----------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 - 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements diagnostics for the @abi attribute. +/// +//===----------------------------------------------------------------------===// + +#include "TypeChecker.h" +#include "swift/AST/Decl.h" +#include "swift/AST/Effects.h" +#include "swift/AST/DiagnosticsSema.h" +#include "swift/AST/ParameterList.h" +#include "swift/AST/ASTPrinter.h" +#include "swift/AST/Types.h" +#include "swift/Basic/Assertions.h" +#include "swift/Parse/Lexer.h" +#include + +using namespace swift; + +namespace { + +/// Like ASTVisitor, but the visit methods are passed a pair of nodes to compare. +/// Either node might be \c nil , indicating that a matching node was not found. +template +class ASTComparisonVisitor { +public: + bool visit(Decl *D1, Decl *D2) { + DeclKind kind = D1 ? D1->getKind() : D2->getKind(); + switch (kind) { +#define DECL(CLASS, PARENT) \ + case DeclKind::CLASS: \ + return static_cast(this) \ + ->visit##CLASS##Decl(static_cast(D1), \ + static_cast(D2)); +#include "swift/AST/DeclNodes.def" + } + llvm_unreachable("Not reachable, all cases handled"); + } + +#define DECL(CLASS, PARENT) \ + bool visitParentOf##CLASS##Decl(CLASS##Decl *D1, CLASS##Decl *D2) {\ + return static_cast(this)->visit##PARENT(D1, D2); \ + } +#define ABSTRACT_DECL(CLASS, PARENT) DECL(CLASS, PARENT) +#include "swift/AST/DeclNodes.def" +}; + +/// Describes the effects that have been applied to a declaration, packaging up +/// various bits of info used for \c \@abi diagnostics. +struct DeclEffects { + PossibleEffects effects; + PossibleEffects polymorphicEffects; + + SourceLoc asyncLoc; + SourceLoc throwsLoc; + + std::optional effectiveThrownType; + TypeRepr *thrownTypeRepr; + + DeclEffects(AbstractFunctionDecl *afd) + : effects(), polymorphicEffects(), + asyncLoc(afd->getAsyncLoc()), throwsLoc(afd->getThrowsLoc()), + effectiveThrownType(afd->getEffectiveThrownErrorType()), + thrownTypeRepr(afd->getThrownTypeRepr()) + { + if (afd->hasEffect(EffectKind::Async)) + effects |= EffectKind::Async; + if (afd->hasPolymorphicEffect(EffectKind::Async)) + polymorphicEffects |= EffectKind::Async; + + if (afd->hasEffect(EffectKind::Throws)) + effects |= EffectKind::Throws; + if (afd->hasPolymorphicEffect(EffectKind::Throws)) + polymorphicEffects |= EffectKind::Throws; + } + + bool anyContains(EffectKind effect) const { + return effects.contains(effect) || polymorphicEffects.contains(effect); + } +}; + +/// Describes the relationship between a given type and the declaration it +/// belongs to--e.g. is this its result type? a parameter type? etc. Used with +/// a couple of \c \@abi diagnostics. +class TypeOrigin { +public: + // Cases must be kept in sync with DiagnosticsSema TYPE_ORIGIN + enum class Kind : uint8_t { + Unspecified = 0, + Parameter = 1, + SelfParameter = 2, + Result = 3, + ThrowsEffect = 4, + }; + +private: + llvm::PointerIntPair declAndKind; + + TypeOrigin(Decl *decl, Kind kind) + : declAndKind(decl, kind) {} + +public: + static TypeOrigin forUnspecified() { + return TypeOrigin(nullptr, Kind::Unspecified); + } + + static TypeOrigin forParameter(ParamDecl *paramDecl) { + return TypeOrigin(paramDecl, + paramDecl->isSelfParameter() ? Kind::SelfParameter + : Kind::Parameter); + } + + static TypeOrigin forResult() { + return TypeOrigin(nullptr, Kind::Result); + } + + static TypeOrigin forThrowsEffect() { + return TypeOrigin(nullptr, Kind::ThrowsEffect); + } + + Kind getKind() const { + return declAndKind.getInt(); + } + + Decl *getDecl() const { + return declAndKind.getPointer(); + } +}; + +/// Emit a fix-it replacing \p charRange with \p newText , inserting or +/// removing whitespace after \c charRange in a way suitable for editing a +/// sequence of whitespce-separated keywords. +void fixItReplaceKeywords(InFlightDiagnostic &diag, + CharSourceRange charRange, + StringRef newText) { + auto &SM = diag.getSourceManager(); + auto charRangeIsFollowedByWhitespace = [&]() -> bool { + auto str = SM.extractText({ charRange.getEnd(), 1 }); + return str.empty() ? false : isspace(str.front()); + }; + + SmallString<32> scratch; + scratch += newText; + + if (newText.empty()) { + // Eat trailing whitespace. + while (charRangeIsFollowedByWhitespace()) { + charRange = { charRange.getStart(), charRange.getByteLength() + 1 }; + } + } else { + if (!charRangeIsFollowedByWhitespace()) { + scratch.push_back(' '); + } + } + + diag.fixItReplaceChars(charRange.getStart(), charRange.getEnd(), scratch); +} + +/// Emit a fix-it replacing \p range with \p newText , inserting or +/// removing whitespace after \c range in a way suitable for editing a +/// sequence of whitespce-separated keywords. +void fixItReplaceKeywords(InFlightDiagnostic &diag, + SourceRange range, + StringRef newText) { + auto &SM = diag.getSourceManager(); + auto charRange = Lexer::getCharSourceRangeFromSourceRange(SM, range); + return fixItReplaceKeywords(diag, charRange, newText); +} + +/// Returns a string representation of \p attr suitable to either replace an +/// existing attribute or be inserted as a new attribute, depending on the +/// value of \p toInsert . +StringRef printAttr(DeclAttribute *attr, + Decl *decl, + SmallVectorImpl &scratch, + bool toInsert = false) { + auto &ctx = decl->getASTContext(); + auto opts = PrintOptions::printForDiagnostics(AccessLevel::Private, + ctx.TypeCheckerOpts.PrintFullConvention); + opts.PrintLongAttrsOnSeparateLines = false; + + llvm::raw_svector_ostream os{scratch}; + StreamPrinter printer{os}; + attr->print(printer, opts, decl); + + auto str = StringRef(scratch.begin(), scratch.size()); + if (!toInsert) + str = str.trim(' '); + return str; +} + +/// Emit \c diag::attr_abi_matching_attr_here in the best available location. +void noteAttrHere(DeclAttribute *attr, Decl *decl, bool isMatch = false) { + auto &ctx = decl->getASTContext(); + SourceLoc loc = attr->getLocation(); + if (loc.isValid()) + ctx.Diags.diagnose(loc, diag::attr_abi_matching_attr_here, + isMatch, attr->isDeclModifier(), attr->isImplicit()); + else + ctx.Diags.diagnose(decl, diag::attr_abi_matching_attr_here, + isMatch, attr->isDeclModifier(), attr->isImplicit()); +} + +/// Get the best available \c SourceLoc representing the type in \p storage . +SourceLoc getTypeLoc(AbstractStorageDecl *storage, Decl *owner = nullptr) { + auto loc = storage->getTypeSourceRangeForDiagnostics().Start; + if (loc.isInvalid()) + loc = storage->getLoc(); + if (loc.isInvalid() && owner) + loc = owner->getLoc(); + return loc; +} + +/// Get a decl's generic signature, if it has one. +GenericSignature getGenericSignature(Decl *decl) { + if (auto genericCtx = decl->getAsGenericContext()) + return genericCtx->getGenericSignature(); + return GenericSignature(); +} + +class ABIDeclChecker : public ASTComparisonVisitor { + ASTContext &ctx; + Decl *diagnoseOnDecl; + ABIAttr *abiAttr; + + /// Used to de-duplicate short-form \c \@available attrs. See \c checkAttr() . + SmallSetVector diagnosedAvailableAttrSourceLocs; + + /// This emits a diagnostic with a fixit to remove the attribute. + template + InFlightDiagnostic diagnoseAndRemoveAttr(DeclAttribute *attr, + ArgTypes &&...Args) { + return swift::diagnoseAndRemoveAttr(diagnoseOnDecl, attr, + std::forward(Args)...); + } + +public: + ABIDeclChecker(ASTContext &ctx, Decl *diagnoseOnDecl, ABIAttr *abiAttr) + : ctx(ctx), diagnoseOnDecl(diagnoseOnDecl), abiAttr(abiAttr) {} + + // MARK: @abi checking - decls + + void check(Decl *api, Decl *abi) { + // Do the declarations have the same kind, broadly speaking? Many kinds have + // special mangling behavior (e.g. inits vs normal funcs) that make it + // unrealistic to treat one kind as though it were another. + // (And if they don't, we can't really compare them properly. + if (api->getKind() != abi->getKind()) { + // FIXME: DescriptiveDeclKind is overly specific; we really just want to + // say that e.g. a `func` can't have the ABI of a `var`. + diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_kind, + api, abi->getDescriptiveKind()); + return; + } + + visit(api, abi); + } + + bool checkParameterFlags(ParameterTypeFlags api, ParameterTypeFlags abi, + ParameterTypeFlags apiOrig, + ParameterTypeFlags abiOrig, + Type apiType, Type abiType, + SourceLoc apiTypeLoc, SourceLoc abiTypeLoc, + TypeOrigin origin) { + // Some keywords are spelled differently for a `self` parameter. + bool isSelfParam = origin.getKind() == TypeOrigin::Kind::SelfParameter; + + bool didDiagnose = false; + + auto noteShouldMatch = [&](bool isModifier) { + if (isSelfParam) + ctx.Diags.diagnose(apiTypeLoc, diag::attr_abi_matching_attr_here, + /*matches=*/false, isModifier, /*isImplicit=*/false); + else + ctx.Diags.diagnose(apiTypeLoc, diag::attr_abi_should_match_type_here); + }; + + // These assertions represent values that should have been normalized. + ASSERT(!api.isVariadic() && !abi.isVariadic()); + ASSERT(!api.isAutoClosure() && !abi.isAutoClosure()); + ASSERT(!api.isNonEphemeral() && !abi.isNonEphemeral()); + ASSERT(!api.isIsolated() && !abi.isIsolated()); + ASSERT(!api.isSending() && !abi.isSending()); + ASSERT(!api.isCompileTimeLiteral() && !abi.isCompileTimeLiteral()); + + if (api.getOwnershipSpecifier() != abi.getOwnershipSpecifier()) { + auto getSpelling = [=](ParamSpecifier spec) -> StringRef { + // Customize a couple of names to match what the developer would + // actually write. + if (spec == ParamSpecifier::Default) + return ""; + if (spec == ParamSpecifier::InOut && isSelfParam) + return "mutating"; + if (spec == ParamSpecifier::LegacyOwned && isSelfParam) + return "__consuming"; + if (spec == ParamSpecifier::ImplicitlyCopyableConsuming) + return "sending"; + return getNameForParamSpecifier(spec); + }; + + ctx.Diags.diagnose(abiTypeLoc, diag::attr_abi_mismatched_param_modifier, + getSpelling(abiOrig.getOwnershipSpecifier()), + getSpelling(apiOrig.getOwnershipSpecifier()), + /*isModifier=*/true, unsigned(origin.getKind()), + origin.getDecl()); + noteShouldMatch(/*isModifier=*/true); + didDiagnose = true; + } + + if (api.isNoDerivative() != abi.isNoDerivative()) { + ctx.Diags.diagnose(abiTypeLoc, diag::attr_abi_mismatched_param_modifier, + abiOrig.isNoDerivative() ? "noDerivative" : "", + apiOrig.isNoDerivative() ? "noDerivative" : "", + /*isModifier=*/false, unsigned(origin.getKind()), + origin.getDecl()); + noteShouldMatch(/*isModifier=*/false); + didDiagnose = true; + } + + if (api.isAddressable() != abi.isAddressable()) { + StringRef spelling = isSelfParam ? "_addressableSelf" : "_addressable"; + ctx.Diags.diagnose(abiTypeLoc, diag::attr_abi_mismatched_param_modifier, + abiOrig.isAddressable() ? spelling : "", + apiOrig.isAddressable() ? spelling : "", + /*isModifier=*/false, unsigned(origin.getKind()), + origin.getDecl()); + noteShouldMatch(/*isModifier=*/false); + didDiagnose = true; + } + + if (!didDiagnose && api != abi) { + // Flag difference not otherwise diagnosed. This is a fallback diagnostic. + ctx.Diags.diagnose(abiTypeLoc, diag::attr_abi_mismatched_type, + unsigned(origin.getKind()), origin.getDecl(), + abiType, apiType); + ctx.Diags.diagnose(apiTypeLoc, diag::attr_abi_should_match_type_here); + didDiagnose = true; + } + + return didDiagnose; + } + + bool checkParameter(ParamDecl *api, ParamDecl *abi, + ValueDecl *apiDecl, ValueDecl *abiDecl) { + ASSERT(api && abi); + + bool didDiagnose = false; + if (auto defaultExpr = abi->getStructuralDefaultExpr()) { + // Forbidden. + ctx.Diags.diagnose(defaultExpr->getLoc(), + diag::attr_abi_no_default_arguments, abi); + // TODO: Fix removing default arg (requires SourceLoc for equal sign) + + // Don't return immediately because we can independently check the type. + didDiagnose = true; + } + + auto apiOrig = api->toFunctionParam(); + auto abiOrig = abi->toFunctionParam(); + // FIXME: Do `self` params have the same default param specifier behavior? + auto apiNorm = normalizeParam(apiOrig, apiDecl); + auto abiNorm = normalizeParam(abiOrig, abiDecl); + + // FIXME: Refine to point to specific modifiers where possible. + SourceLoc apiTypeLoc = getTypeLoc(api, apiDecl); + SourceLoc abiTypeLoc = getTypeLoc(abi, abiDecl); + + didDiagnose |= checkType(apiNorm.getPlainType(), abiNorm.getPlainType(), + apiTypeLoc, abiTypeLoc, + getGenericSignature(apiDecl), + getGenericSignature(abiDecl), + TypeOrigin::forParameter(abi)); + + didDiagnose |= checkParameterFlags(apiNorm.getParameterFlags(), + abiNorm.getParameterFlags(), + apiOrig.getParameterFlags(), + abiOrig.getParameterFlags(), + apiNorm.getPlainType(), + abiNorm.getPlainType(), + apiTypeLoc, abiTypeLoc, + TypeOrigin::forParameter(abi)); + + didDiagnose |= checkAttrs(api->getAttrs(), abi->getAttrs(), api, abi); + + return didDiagnose; + } + + bool checkParameterList(ParameterList *api, ParameterList *abi, + ValueDecl *apiDecl, ValueDecl *abiDecl) { + // Do the declarations have the same number of parameters? + if (api->size() != abi->size()) { + diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_arity, apiDecl, + /*genericParams=*/false); + return true; + } + + bool didDiagnose = false; + + for (auto pair : llvm::zip(*api, *abi)) { + didDiagnose |= checkParameter(std::get<0>(pair), std::get<1>(pair), + apiDecl, abiDecl); + } + + return didDiagnose; + } + + bool checkImplicitSelfParam(ParamDecl *api, ParamDecl *abi, + ValueDecl *apiDecl, ValueDecl *abiDecl) { + if (!api && !abi) + // Nothing to check + return false; + + if ((api && !abi) || (!api && abi)) { + diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_arity, + apiDecl, /*genericParams=*/false); + return true; + } + + return checkParameter(api, abi, apiDecl, abiDecl); + } + + bool checkGenericSignature(GenericSignature api, GenericSignature abi, + Decl *apiDecl, Decl *abiDecl) { + if (api.isNull() && abi.isNull()) + return false; + + if (api.isNull()) { + abiDecl->diagnose(diag::attr_abi_extra_generic_signature, apiDecl); + return true; + } + + if (abi.isNull()) { + abiDecl->diagnose(diag::attr_abi_missing_generic_signature, + api.getAsString()); + return true; + } + + auto apiNorm = normalizeGenericSignature(api); + auto abiNorm = normalizeGenericSignature(abi); + + if (!apiNorm->isEqual(abiNorm)) { + abiDecl->diagnose(diag::attr_abi_mismatched_generic_signature, + abi.getAsString(), api.getAsString()); + apiDecl->diagnose(diag::attr_abi_should_match_type_here); + return true; + } + + return false; + } + + bool checkEffects(DeclEffects api, DeclEffects abi, Decl *apiDecl, + Decl *abiDecl) { + bool didDiagnose = false; + + // Do the declarations match in throwing behavior? We don't care about + // `throws` vs. `rethrows` here, just whether callers will account for an + // error return. + bool apiThrows = api.anyContains(EffectKind::Throws); + bool abiThrows = abi.anyContains(EffectKind::Throws); + + if (apiThrows != abiThrows) { + diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_throws, + apiDecl, /*abiCanThrow=*/abiThrows); + didDiagnose = true; + } else if (apiThrows && abiThrows) { + // If both throw, make sure the throw types are compatible. + auto apiThrowType = api.effectiveThrownType.value_or(ctx.getNeverType()); + auto abiThrowType = abi.effectiveThrownType.value_or(ctx.getNeverType()); + + didDiagnose |= checkType(apiThrowType, abiThrowType, + api.throwsLoc, abi.throwsLoc, + getGenericSignature(apiDecl), + getGenericSignature(abiDecl), + TypeOrigin::forThrowsEffect()); + } + + // Do the declarations match in async-ness? + if (api.anyContains(EffectKind::Async) != abi.anyContains(EffectKind::Async)) { + diagnoseAndRemoveAttr(abiAttr, diag::attr_abi_mismatched_async, + apiDecl, /*abiHasAsync=*/abi.anyContains(EffectKind::Async)); + didDiagnose = true; + } + + return didDiagnose; + } + + bool checkFailable(ConstructorDecl *api, ConstructorDecl *abi) { + if (api->isFailable() == abi->isFailable()) { + return false; + } + + auto diag = ctx.Diags.diagnose(abiAttr->getLocation(), + diag::attr_abi_failable_mismatch, api, + api->isFailable(), abi->isFailable()); + + if (api->isFailable()) + diag.fixItInsertAfter(abi->getLoc(), + api->isImplicitlyUnwrappedOptional() ? "!" : "?"); + else + diag.fixItRemove(abi->getFailabilityLoc()); + + return true; + } + + bool checkStaticAndFinal(ValueDecl *api, ValueDecl *abi) { + // The `static`, `class`, and `final` keywords all need to be evaluated + // together because of their intertwined semantics. This pile of code + // diagnoses errors in either or both. + + /// Returns the type and location of the declaration's `static` or `class` keyword, if any. + auto getStaticSpelling = [](Decl *decl) -> Located { + if (auto var = dyn_cast(decl)) + decl = var->getParentPatternBinding(); + + if (auto pbd = dyn_cast(decl)) + return { pbd->getStaticSpelling(), pbd->getStaticLoc() }; + + if (auto subscript = dyn_cast(decl)) + return { subscript->getStaticSpelling(), subscript->getStaticLoc() }; + + if (auto func = dyn_cast(decl)) + return { func->getStaticSpelling(), func->getStaticLoc() }; + + return { StaticSpellingKind::None, SourceLoc() }; + }; + + /// Represents the combination of `class`, `static`, and `final` keywords + /// for a given declaration. + enum class StaticnessAndFinality : uint8_t { + InstanceAndOverridable, + ClassAndOverridable, + InstanceAndFinal, + ClassAndFinal, + Static, + }; + + /// Returns a `StaticnessAndFinality` corresponding to the given values. + auto getStaticnessAndFinality = [](StaticSpellingKind staticSpelling, + bool isFinal) { + switch (staticSpelling) { + case StaticSpellingKind::None: + return isFinal ? StaticnessAndFinality::InstanceAndFinal + : StaticnessAndFinality::InstanceAndOverridable; + + case StaticSpellingKind::KeywordStatic: + return StaticnessAndFinality::Static; + + case StaticSpellingKind::KeywordClass: + return isFinal ? StaticnessAndFinality::ClassAndFinal + : StaticnessAndFinality::ClassAndOverridable; + } + + llvm_unreachable("unknown StaticSpellingKind"); + }; + + auto apiSAF = getStaticnessAndFinality(getStaticSpelling(api).Item, + api->isFinal()); + + auto abiStaticSpelling = getStaticSpelling(abi); + auto abiSAF = getStaticnessAndFinality(abiStaticSpelling.Item, + abi->isFinal()); + + /// Collapses down the difference between `Static` and `ClassAndFinal`. + auto getSemantics = [](StaticnessAndFinality syntax) { + if (syntax == StaticnessAndFinality::ClassAndFinal) + return StaticnessAndFinality::Static; + return syntax; + }; + + if (getSemantics(apiSAF) != getSemantics(abiSAF)) { + auto diag = abi->diagnose(diag::attr_abi_static_final_mismatch, + uint8_t(abiSAF), abi, uint8_t(apiSAF), api, + api->getDeclContext()->getSelfClassDecl()); + + SourceLoc insertLoc = abi->getAttributeInsertionLoc(/*forModifier=*/true); + SourceLoc replaceLoc = abiStaticSpelling.Loc; + SourceLoc deleteLoc; + + // If there's a (non-implicit) `final`, we may want to fix it. + auto finalAttr = abi->getAttrs().getAttribute(); + if (finalAttr && !finalAttr->isImplicit()) + deleteLoc = finalAttr->getLocation(); + + // If only one is valid, that should be `replaceLoc`; if both are valid, + // `replaceLoc` should come before `deleteLoc`. + if (deleteLoc.isValid() && (replaceLoc.isInvalid() || + ctx.SourceMgr.isBefore(deleteLoc, replaceLoc))) + std::swap(deleteLoc, replaceLoc); + + // Delete the keyword at `deleteLoc`, if there is one. + if (deleteLoc.isValid()) + fixItReplaceKeywords(diag, deleteLoc, ""); + + StringRef spellings[] = { "", "class", "final", "final class", "static" }; + auto newKeywords = spellings[uint8_t(apiSAF)]; + + // Either replace the first keyword, or insert new keywords. + if (replaceLoc.isValid()) + fixItReplaceKeywords(diag, replaceLoc, newKeywords); + else + fixItReplaceKeywords(diag, CharSourceRange(insertLoc, 0), newKeywords); + + return true; + } + + return false; + } + + /// This declaration should not be in an `@abi` attribute. +#define UNSUPPORTED_DECL(NAME) \ + bool visit##NAME##Decl(NAME##Decl *api, NAME##Decl *abi) { \ + return visitParentOf##NAME##Decl(api, abi); \ + } + + /// This declaration has no additional validation logic. +#define PASSTHROUGH_DECL(NAME) \ + bool visit##NAME##Decl(NAME##Decl *api, NAME##Decl *abi) { \ + return visitParentOf##NAME##Decl(api, abi); \ + } + + bool visitDecl(Decl *api, Decl *abi) { + bool didDiagnose = checkAttrs(api->getAttrs(), abi->getAttrs(), api, abi); + + if (api->getAsGenericContext()) { + didDiagnose |= checkGenericSignature(getGenericSignature(api), + getGenericSignature(abi), + api, abi); + } + + return didDiagnose; + } + + bool visitValueDecl(ValueDecl *api, ValueDecl *abi) { + if (visitParentOfValueDecl(api, abi)) + return true; + + return checkStaticAndFinal(api, abi); + } + + PASSTHROUGH_DECL(Type) + PASSTHROUGH_DECL(GenericType) + PASSTHROUGH_DECL(NominalType) + PASSTHROUGH_DECL(Operator) + + UNSUPPORTED_DECL(Enum) + UNSUPPORTED_DECL(Struct) + UNSUPPORTED_DECL(Class) + + // TODO: When supported, diagnose if Protocol::isMarkerProtocol() + // (mangler can't handle invertible protocols with @abi) + UNSUPPORTED_DECL(Protocol) + + UNSUPPORTED_DECL(BuiltinTuple) + UNSUPPORTED_DECL(OpaqueType) + UNSUPPORTED_DECL(TypeAlias) + UNSUPPORTED_DECL(GenericTypeParam) + UNSUPPORTED_DECL(AssociatedType) + UNSUPPORTED_DECL(Module) + UNSUPPORTED_DECL(Param) + UNSUPPORTED_DECL(Destructor) + UNSUPPORTED_DECL(Macro) + UNSUPPORTED_DECL(EnumElement) + UNSUPPORTED_DECL(Extension) + UNSUPPORTED_DECL(TopLevelCode) + UNSUPPORTED_DECL(Import) + UNSUPPORTED_DECL(PrecedenceGroup) + UNSUPPORTED_DECL(Missing) + UNSUPPORTED_DECL(MissingMember) + UNSUPPORTED_DECL(PatternBinding) + UNSUPPORTED_DECL(EnumCase) + UNSUPPORTED_DECL(Accessor) + UNSUPPORTED_DECL(InfixOperator) + UNSUPPORTED_DECL(PrefixOperator) + UNSUPPORTED_DECL(PostfixOperator) + UNSUPPORTED_DECL(MacroExpansion) + + bool visitAbstractFunctionDecl(AbstractFunctionDecl *api, + AbstractFunctionDecl *abi) { + if (visitParentOfAbstractFunctionDecl(api, abi)) + return true; + + // FIXME: How much should we diagnose in IRGen for more precise ABI info? + + if (checkImplicitSelfParam(api->getImplicitSelfDecl(), + abi->getImplicitSelfDecl(), + api, abi)) + return true; + + if (checkParameterList(api->getParameters(), abi->getParameters(), + api, abi)) + return true; + + return checkEffects(DeclEffects(api), DeclEffects(abi), api, abi); + // NOTE: Does not check result type--that's the subclass's responsibility! + } + + bool visitFuncDecl(FuncDecl *api, FuncDecl *abi) { + if (visitParentOfFuncDecl(api, abi)) + return true; + + // Intentionally ignoring `hasSendingResult()` because it doesn't affect + // calling convention. + + return checkType(api->getResultInterfaceType(), + abi->getResultInterfaceType(), + api->getResultTypeSourceRange().Start, + abi->getResultTypeSourceRange().Start, + getGenericSignature(api), getGenericSignature(abi), + TypeOrigin::forResult()); + } + + bool visitConstructorDecl(ConstructorDecl *api, ConstructorDecl *abi) { + if (visitParentOfConstructorDecl(api, abi)) + return true; + + return checkFailable(api, abi); + } + + bool visitAbstractStorageDecl(AbstractStorageDecl *api, + AbstractStorageDecl *abi) { + if (visitParentOfAbstractStorageDecl(api, abi)) + return true; + + if (checkType(api->getValueInterfaceType(), abi->getValueInterfaceType(), + getTypeLoc(api), getTypeLoc(abi), + getGenericSignature(api), getGenericSignature(abi), + TypeOrigin::forUnspecified())) + return true; + + return false; + } + + bool visitVarDecl(VarDecl *api, VarDecl *abi) { + if (visitParentOfVarDecl(api, abi)) + return true; + return false; + } + + bool visitSubscriptDecl(SubscriptDecl *api, SubscriptDecl *abi) { + if (visitParentOfSubscriptDecl(api, abi)) + return true; + + if (checkParameterList(api->getIndices(), abi->getIndices(), api, abi)) + return true; + + return false; + } + +#undef UNSUPPORTED_DECL +#undef PASSTHROUGH_DECL + + // MARK: @abi checking - attributes + + /// Are these attributes similar enough that they should be checked against + /// one another? At minimum this means they're of the same kind, but for some + /// attrs there are additional criteria. + bool canCompareAttrs(DeclAttribute *api, DeclAttribute *abi, + Decl *apiDecl, Decl *abiDecl) { + if (api->getKind() != abi->getKind()) + return false; + + auto getAvailableDomain = [](Decl *D, DeclAttribute *A) { + return D->getSemanticAvailableAttr(cast(A))->getDomain(); + }; + + // Extra logic for specific attributes. + switch (api->getKind()) { + case DeclAttrKind::Expose: + return cast(api)->getExposureKind() + == cast(abi)->getExposureKind(); + + case DeclAttrKind::Extern: + return cast(api)->getExternKind() + == cast(abi)->getExternKind(); + + case DeclAttrKind::Available: + return getAvailableDomain(apiDecl, api) + == getAvailableDomain(abiDecl, abi); + return true; + + default: + break; + } + + return true; + } + + /// Check two attribute lists against one another. + /// + /// This pairs up attributes which are sufficiently similar (as determined by + /// \c canCompareAttrs() ) and then checks them. Attributes which + /// have no counterpart are checked individually. + bool checkAttrs(DeclAttributes api, DeclAttributes abi, + Decl *apiDecl, Decl *abiDecl) { + bool didDiagnose = false; + + // Collect all ABI attrs. + SmallVector remainingABIDeclAttrs; + for (auto *abiDeclAttr : abi) { + remainingABIDeclAttrs.push_back(abiDeclAttr); + } + + // Visit each API attr, pairing it with an ABI attr if possible. + // Note that this will visit even invalid attributes. + for (auto *apiDeclAttr : api) { + auto abiAttrIter = llvm::find_if(remainingABIDeclAttrs, + [&](DeclAttribute *abiDeclAttr) { + return abiDeclAttr && canCompareAttrs(apiDeclAttr, abiDeclAttr, + apiDecl, abiDecl); + }); + DeclAttribute *abiDeclAttr = nullptr; + if (abiAttrIter != remainingABIDeclAttrs.end()) { + // Found a matching ABI attr. Claim and use it. + std::swap(abiDeclAttr, *abiAttrIter); + } + didDiagnose |= checkAttr(apiDeclAttr, abiDeclAttr, apiDecl, abiDecl); + } + + // Visit leftover ABI attrs. + for (auto *abiDeclAttr : remainingABIDeclAttrs) { + if (abiDeclAttr) + didDiagnose |= checkAttr(nullptr, abiDeclAttr, apiDecl, abiDecl); + } + return didDiagnose; + } + + /// Check a single attribute against its counterpart. If an attribute has no + /// counterpart, the counterpart may be \c nullptr ; either \p abi or \p abi + /// may be \c nullptr , but never both. + bool checkAttr(DeclAttribute *api, DeclAttribute *abi, + Decl *apiDecl, Decl *abiDecl) { + ASSERT(api || abi && "checkAttr() should have at least one attribute"); + + // If either attribute has already been diagnosed, don't check here. + if ((api && api->isInvalid()) || (abi && abi->isInvalid())) + return true; + + auto kind = api ? api->getKind() : abi->getKind(); + auto behaviors = DeclAttribute::getBehaviors(kind); + + switch (behaviors & DeclAttribute::InABIAttrMask) { + case DeclAttribute::UnreachableInABIAttr: + ASSERT(abiAttr->canAppearOnDecl(apiDecl) + && "checking @abi on decl that can't have it???"); + ASSERT(!abiAttr->canAppearOnDecl(apiDecl) + && "unreachable-in-@abi attr on reachable decl???"); + + // If the asserts are disabled, fall through to no checking. + LLVM_FALLTHROUGH; + + case DeclAttribute::UnconstrainedInABIAttr: + // No checking required. + return false; + + case DeclAttribute::ForbiddenInABIAttr: + // Diagnose if ABI has attribute. + if (abi) { + // A shorthand `@available(foo 1, bar 2, *)` attribute gets parsed into + // several separate `AvailableAttr`s, each with the full range of the + // shorthand attribute. If we've already diagnosed one of them, don't + // diagnose the rest; otherwise, record that we've diagnosed this one. + if (isa(abi) && + !diagnosedAvailableAttrSourceLocs.insert(abi->getLocation())) + return true; + + diagnoseAndRemoveAttr(abi, diag::attr_abi_forbidden_attr, + abi->getAttrName(), abi->isDeclModifier()); + return true; + } + + return false; + + case DeclAttribute::InferredInABIAttr: + if (!abi && api->canClone()) { + // Infer an identical attribute. + abi = api->clone(ctx); + abi->setImplicit(true); + abiDecl->getAttrs().add(abi); + + if (ctx.LangOpts.EnableABIInferenceRemarks) { + SmallString<64> scratch; + auto abiAttrAsString = printAttr(abi, abiDecl, scratch); + + abiDecl->diagnose(diag::abi_attr_inferred_attribute, + abiAttrAsString, api->isDeclModifier()); + noteAttrHere(api, apiDecl, /*isMatch=*/true); + } + } + + // Other than the cloning behavior, Inferred behaves like Equivalent. + LLVM_FALLTHROUGH; + + case DeclAttribute::EquivalentInABIAttr: + // Diagnose if API doesn't have attribute. + if (!api) { + diagnoseAndRemoveAttr(abi, diag::attr_abi_extra_attr, + abi->getAttrName(), abi->isDeclModifier(), + abi->isImplicit()); + return true; + } + + // Diagnose if ABI doesn't have attribute. + if (!abi) { + SmallString<64> scratch; + auto apiAttrAsString = printAttr(api, apiDecl, scratch, + /*toInsert=*/true); + + ctx.Diags.diagnose(abiDecl, diag::attr_abi_missing_attr, + api->getAttrName(), api->isDeclModifier()) + .fixItInsert(abiDecl->getAttributeInsertionLoc(api->isDeclModifier()), + apiAttrAsString); + noteAttrHere(api, apiDecl); + return true; + } + + // Diagnose if two attributes are mismatched. + if (!api->isEquivalent(abi, apiDecl)) { + SmallString<64> scratch; + auto apiAttrAsString = printAttr(api, apiDecl, scratch); + + ctx.Diags.diagnose(abi->getLocation(), diag::attr_abi_mismatched_attr, + abi->getAttrName(), abi->isDeclModifier(), + apiAttrAsString) + .fixItReplace(abi->getRangeWithAt(), apiAttrAsString); + noteAttrHere(api, apiDecl); + return true; + } + + return false; + } + + llvm_unreachable("unknown InABIAttrMask behavior"); + } + + // MARK: @abi checking - types + + bool checkType(Type api, Type abi, SourceLoc apiLoc, SourceLoc abiLoc, + GenericSignature apiSig, GenericSignature abiSig, + TypeOrigin origin) { + if (!api.isNull() && !abi.isNull()) { + Type apiNorm = normalizeType(api->getReducedType(apiSig)); + Type abiNorm = normalizeType(abi->getReducedType(abiSig)); + if (apiNorm->isEqual(abiNorm)) { + return false; + } + } + + ctx.Diags.diagnose(abiLoc, diag::attr_abi_mismatched_type, + unsigned(origin.getKind()), origin.getDecl(), abi, api); + ctx.Diags.diagnose(apiLoc, diag::attr_abi_should_match_type_here); + return true; + } + + /// Fold away details of \p original that do not affect the calling + /// conventions used for this type. + static Type normalizeType(Type original) { + return original.transformRec(&tryNormalizeOutermostType); + } + + /// Fold away details of \p original that do not affect the calling + /// conventions used for this parameter. Does \em not fully normalize + /// \c original.getPlainType() , though it may slightly modify it. + /// Pass \c nullptr to \p forDecl for a parameter belonging to a closure. + static AnyFunctionType::Param + normalizeParam(const AnyFunctionType::Param &original, ValueDecl *forDecl) { + Type ty = original.getPlainType(); + auto flags = original.getParameterFlags(); + + // We will smash away (non-parameter pack) variadics; turn the type into + // an array. + if (flags.isVariadic()) { + ty = original.getParameterType(); + } + + // Flatten ownership information down to consume/borrow/inout, which are the + // only distinctions that matter for calling conventions and memory + // management. This removes the distinction between e.g. `__owned` and + // `consuming`, or between the declaration's default parameter ownership + // convention and an explicit equivalent. + auto ownership = normalizeOwnership(flags.getOwnershipSpecifier(), + forDecl); + + // Eliminate flags with no effect on the calling convention. + flags = flags + .withVariadic(false) + .withCompileTimeLiteral(false) + .withAutoClosure(false) + .withNonEphemeral(false) + .withIsolated(false) + .withSending(false) + .withOwnershipSpecifier(ownership); + + return AnyFunctionType::Param(ty, Identifier(), flags, Identifier()); + } + + /// Folds away \p original to one of \c Consuming , \c Borrowing , or + /// \c InOut , which are the only parameter ownership behaviors relevant to ABI. + /// Pass \c nullptr to \p forDecl for a parameter belonging to a closure. + static ParamSpecifier normalizeOwnership(ParamSpecifier original, + ValueDecl *forDecl) { + switch (original) { + case ParamSpecifier::Default: + return getDefaultParamSpecifier(forDecl); + break; + case swift::ParamSpecifier::InOut: + return ParamSpecifier::InOut; + break; + case ParamSpecifier::Borrowing: + case ParamSpecifier::LegacyShared: + return ParamSpecifier::Borrowing; + break; + case swift::ParamSpecifier::Consuming: + case swift::ParamSpecifier::LegacyOwned: + case swift::ParamSpecifier::ImplicitlyCopyableConsuming: + return ParamSpecifier::Consuming; + break; + } + } + + static GenericSignature normalizeGenericSignature(GenericSignature original) { + // FIXME: Are there other ABI-tolerable generic signature differences? + return original.withoutMarkerProtocols(); + } + + static + FunctionTypeIsolation normalizeIsolation(FunctionTypeIsolation original) { + // Isolation doesn't affect the ABI, except that `@isolated(any)` (a.k.a. + // `FunctionTypeIsolation::Kind::Erased`) has a different ABI from all the + // others. See docs/SIL/Types.td for details. + return original.isErased() ? FunctionTypeIsolation::forErased() + : FunctionTypeIsolation::forNonIsolated(); + } + + static std::optional tryNormalizeOutermostType(TypeBase *original) { + // Function types: Eliminate anything that doesn't affect calling convention. + if (auto func = original->getAs()) { + // Ignore `@escaping`, `@Sendable`, `sending` on result, and most + // isolation; they have no ABI effect. + auto normalizedExt = func->getExtInfo().intoBuilder() + .withNoEscape(false) + .withSendable(false) + .withSendingResult(false) + .withIsolation(normalizeIsolation(func->getIsolation())) + .build(); + + // Ignore ignorable parts of parameters. + SmallVector normalizedParams; + for (auto param : func->getParams()) { + auto normalizedParam = normalizeParam(param, /*forDecl=*/nullptr); + normalizedParam = normalizedParam.withType( + normalizeType(normalizedParam.getPlainType())); + normalizedParams.push_back(normalizedParam); + } + + if (isa(func)) + return FunctionType::get(normalizedParams, + normalizeType(func->getResult()), + normalizedExt); + + ASSERT(isa(func)); + + // Ignore ignorable parts of the generic signature. + auto sig = original->getAs()->getGenericSignature(); + return GenericFunctionType::get(normalizeGenericSignature(sig), + normalizedParams, + normalizeType(func->getResult()), + normalizedExt); + } + + // Protocol-related types: Remove marker protocols. + if (auto comp = original->getAs()) { + auto normalized = comp->withoutMarkerProtocols(); + if (!normalized->isEqual(comp)) + return normalized; + } + + if (auto proto = original->getAs()) { + if (proto->getDecl()->isMarkerProtocol()) + return proto->getASTContext().TheAnyType; + } + + if (auto existential = original->getAs()) { + // Pull out the constraint and see how it'll normalize. + auto normConstraint = normalizeType(existential->getConstraintType()); + + // If the constraint is no longer existential, pull it out of the type. + if (!normConstraint->isExistentialType()) + return normConstraint; + } + + // Tuples: Remove labels. + if (auto tuple = original->getAs()) { + bool needsNormalization = false; + SmallVector unlabeledElements; + + for (auto elem : tuple->getElements()) { + needsNormalization |= !elem.getName().empty(); + unlabeledElements.push_back(elem.getWithoutName()); + } + + if (!needsNormalization) + return tuple; + + return TupleType::get(unlabeledElements, tuple->getASTContext()); + } + + // TODO: Allow Optional/non-Optional variance when ABI-compatible? + // TODO: Allow variance in exact class of object? + + return std::nullopt; + } +}; + +void checkABIAttrPBD(PatternBindingDecl *APBD, VarDecl *VD) { + auto &diags = VD->getASTContext().Diags; + auto PBD = VD->getParentPatternBinding(); + + // To make sure we only diagnose this stuff once, check that VD is the first + // anchoring variable in the PBD. + bool isFirstAnchor = false; + for (auto i : range(PBD->getNumPatternEntries())) { + auto anchorVD = PBD->getAnchoringVarDecl(i); + if (anchorVD) { + isFirstAnchor = (anchorVD == VD); + break; + } + } + + if (!isFirstAnchor) + return; + + // Check that the PBDs have the same number of patterns. + if (PBD->getNumPatternEntries() < APBD->getNumPatternEntries()) { + diags.diagnose(APBD->getPattern(PBD->getNumPatternEntries())->getLoc(), + diag::attr_abi_mismatched_pbd_size, /*abiHasExtra=*/false); + return; + } + if (PBD->getNumPatternEntries() > APBD->getNumPatternEntries()) { + diags.diagnose(PBD->getPattern(APBD->getNumPatternEntries())->getLoc(), + diag::attr_abi_mismatched_pbd_size, /*abiHasExtra=*/true); + return; + } + + // Check that each pattern has the same number of variables. + for (auto i : range(PBD->getNumPatternEntries())) { + SmallVector VDs; + SmallVector AVDs; + + PBD->getPattern(i)->collectVariables(VDs); + APBD->getPattern(i)->collectVariables(AVDs); + + if (VDs.size() < AVDs.size()) { + for (auto AVD : drop_begin(AVDs, VDs.size())) { + AVD->diagnose(diag::attr_abi_mismatched_var, + AVD, /*isABI=*/true); + } + } + else if (VDs.size() > AVDs.size()) { + for (auto VD : drop_begin(VDs, AVDs.size())) { + VD->diagnose(diag::attr_abi_mismatched_var, + VD, /*isABI=*/false); + } + } + } +} +} // end anonymous namespace + +void TypeChecker::checkDeclABIAttribute(Decl *D, ABIAttr *attr) { + Decl *AD = attr->abiDecl; + if (isa(D) && isa(AD)) { + auto VD = cast(D); + auto APBD = cast(AD); + + // Diagnose dissimilar PBD structures. + checkABIAttrPBD(APBD, VD); + + // Do the rest of this checking on the corresponding VarDecl, not the + // PBD that's actually in the attribute. Note that `AD` will become null + // if they're too dissimilar to match up. + AD = APBD->getVarAtSimilarStructuralPosition(VD); + } + // TODO: EnumElementDecl? + + if (!AD) + return; + + // Check the ABI decl and bail if there was a problem with it. + TypeChecker::typeCheckDecl(AD); + if (AD->isInvalid()) + return; + + // Apply more precise checks. + ABIDeclChecker(D->getASTContext(), D, attr).check(D, AD); +} diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 32c323d838f86..1dabd633b9a14 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -480,6 +480,12 @@ static const Decl *relatedDeclForAvailabilityFixit(const Decl *D) { D = accessor->getStorage(); } + auto abiRole = ABIRoleInfo(D); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) { + // ABI-only decls can't have @available attributes of their own. + D = abiRole.getCounterpart(); + } + return D->getAbstractSyntaxDeclForAttributes(); } @@ -645,7 +651,7 @@ static void fixAvailabilityForDecl( // syntax to suggest the Fix-It may differ from the declaration to which // we attach availability attributes in the abstract syntax tree during // parsing. - const Decl *ConcDecl = D->getConcreteSyntaxDeclForAttributes(); + const Decl *ConcDecl = relatedDeclForAvailabilityFixit(D); // To avoid exposing the pattern binding declaration to the user, get the // descriptive kind from one of the VarDecls. diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 228c6bc6f0c74..0b6f5c360ba11 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -938,6 +938,11 @@ IsStaticRequest::evaluate(Evaluator &evaluator, FuncDecl *decl) const { bool IsDynamicRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { + // ABI-only decls get this from their API decl. + auto abiRole = ABIRoleInfo(decl); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->isDynamic(); + // If we can't infer dynamic here, don't. if (!DeclAttribute::canAttributeAppearOnDecl(DeclAttrKind::Dynamic, decl)) return false; diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp index 3bf4ff5d53f6b..ec38710102b22 100644 --- a/lib/Sema/TypeCheckDeclObjC.cpp +++ b/lib/Sema/TypeCheckDeclObjC.cpp @@ -650,6 +650,11 @@ bool swift::isRepresentableInObjC( const AbstractFunctionDecl *AFD, ObjCReason Reason, std::optional &asyncConvention, std::optional &errorConvention) { + auto abiRole = ABIRoleInfo(AFD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return isRepresentableInObjC(abiRole.getCounterpart(), Reason, + asyncConvention, errorConvention); + // Clear out the async and error conventions. They will be added later if // needed. asyncConvention = std::nullopt; @@ -1104,6 +1109,10 @@ bool swift::isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason) { if (VD->isInvalid()) return false; + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return isRepresentableInObjC(abiRole.getCounterpart(), Reason); + Type T = VD->getDeclContext()->mapTypeIntoContext(VD->getInterfaceType()); if (auto *RST = T->getAs()) { // In-memory layout of @weak and @unowned does not correspond to anything @@ -1160,6 +1169,10 @@ bool swift::isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason) { bool swift::isRepresentableInObjC(const SubscriptDecl *SD, ObjCReason Reason) { // If you change this function, you must add or modify a test in PrintAsClang. + auto abiRole = ABIRoleInfo(SD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return isRepresentableInObjC(abiRole.getCounterpart(), Reason); + ASTContext &ctx = SD->getASTContext(); DiagnosticStateRAII diagState(ctx.Diags); auto behavior = behaviorLimitForObjCReason(Reason, ctx); @@ -1770,6 +1783,11 @@ static void markAsObjC(ValueDecl *D, ObjCReason reason, bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const { DiagnosticStateRAII diagState(VD->getASTContext().Diags); + // ABI-only decls inherit objc-ness from their API. + auto abiRole = ABIRoleInfo(VD); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->isObjC(); + // Access notes may add attributes that affect this calculus. TypeChecker::applyAccessNote(VD); @@ -4115,6 +4133,9 @@ class ObjCImplementationChecker { evaluator::SideEffect TypeCheckObjCImplementationRequest:: evaluate(Evaluator &evaluator, Decl *D) const { + if (!ABIRoleInfo(D).providesAPI()) + return evaluator::SideEffect(); + PrettyStackTraceDecl trace("checking member implementations of", D); // FIXME: Because we check extension-by-extension, candidates and requirements diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index 4af7efdfcded1..85a113951a1e4 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -2098,7 +2098,8 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) { if (!override->getAttrs().hasAttribute() && overrideRequiresKeyword(base) != OverrideRequiresKeyword::Never && !override->isImplicit() && - override->getDeclContext()->getParentSourceFile()) { + override->getDeclContext()->getParentSourceFile() && + ABIRoleInfo(override).providesAPI()) { auto theDiag = overrideRequiresKeyword(base) == OverrideRequiresKeyword::Always ? diag::missing_override @@ -2513,6 +2514,19 @@ computeOverriddenDecls(ValueDecl *decl, bool ignoreMissingImports) { llvm::TinyPtrVector OverriddenDeclsRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const { + auto abiRole = ABIRoleInfo(decl); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) { + auto apiOverriddenDecls = abiRole.getCounterpart()->getOverriddenDecls(); + + TinyPtrVector abiOverriddenDecls; + for (auto apiOverriddenDecl : apiOverriddenDecls) { + auto abiOverriddenDecl = ABIRoleInfo(apiOverriddenDecl).getCounterpart(); + abiOverriddenDecls.push_back(abiOverriddenDecl); + } + + return abiOverriddenDecls; + } + auto &ctx = decl->getASTContext(); auto overridden = computeOverriddenDecls(decl, false); diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 5664aff3f48f3..033274012edcf 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2173,6 +2173,10 @@ void swift::diagnoseAttrsAddedByAccessNote(SourceFile &SF) { evaluator::SideEffect ApplyAccessNoteRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const { + // Access notes don't apply to ABI-only attributes. + if (!ABIRoleInfo(VD).providesAPI()) + return {}; + AccessNotesFile ¬es = VD->getModuleContext()->getAccessNotes(); if (auto note = notes.lookup(VD)) applyAccessNote(VD, *note.get(), notes); diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 114eea73ddd5e..3df6c0611e531 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -6279,11 +6279,7 @@ static bool hasExplicitObjCName(ClassDecl *classDecl) { if (classDecl->getAttrs().hasAttribute()) return true; - auto objcAttr = classDecl->getAttrs().getAttribute(); - if (!objcAttr) - return false; - - return objcAttr->hasName() && !objcAttr->isNameImplicit(); + return classDecl->getExplicitObjCName().has_value(); } /// Check if the name of a class might be unstable, and if so, emit a diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 4a6af64e8148d..ea7cb6fd2bd87 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -3733,6 +3733,11 @@ static StorageImplInfo classifyWithHasStorageAttr(VarDecl *var) { bool HasStorageRequest::evaluate(Evaluator &evaluator, AbstractStorageDecl *storage) const { + // ABI decl inherits this from API. + auto abiRole = ABIRoleInfo(storage); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->hasStorage(); + // Parameters are always stored. if (isa(storage)) return true; @@ -3818,7 +3823,11 @@ void HasStorageRequest::cacheResult(bool hasStorage) const { return; if (auto varDecl = dyn_cast(decl)) { - if (hasStorage && !varDecl->getAttrs().hasAttribute()) + auto abiRole = ABIRoleInfo(varDecl); + bool abiOnly = !abiRole.providesAPI() && abiRole.getCounterpart(); + + if (hasStorage && !abiOnly && + !varDecl->getAttrs().hasAttribute()) varDecl->getAttrs().add(new (varDecl->getASTContext()) HasStorageAttr(/*isImplicit=*/true)); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index e79d4247f1a9e..cb14ea0bf1b93 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -506,6 +506,7 @@ void typeCheckDecl(Decl *D); void addImplicitDynamicAttribute(Decl *D); void checkDeclAttributes(Decl *D); +void checkDeclABIAttribute(Decl *apiDecl, ABIAttr *abiAttr); void checkClosureAttributes(ClosureExpr *closure); void checkParameterList(ParameterList *params, DeclContext *owner); diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index d464f27eac5f3..11541a24eb2c1 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -4025,7 +4025,8 @@ class DeclDeserializer { AddAttribute(new (ctx) OverrideAttr(SourceLoc())); // Add the @_hasStorage attribute if this var has storage. - if (var->hasStorage()) + // (Unless it's an ABI-only decl--they shouldn't have a HasStorageAttr.) + if (var->hasStorage() && ABIDeclCounterpartID == 0) AddAttribute(new (ctx) HasStorageAttr(/*isImplicit:*/true)); { diff --git a/test/ASTGen/attrs.swift b/test/ASTGen/attrs.swift index d55a408c48d46..307dd7770c3b1 100644 --- a/test/ASTGen/attrs.swift +++ b/test/ASTGen/attrs.swift @@ -94,7 +94,7 @@ struct S4 {} @implementation extension ObjCClass1 {} // expected-error {{cannot find type 'ObjCClass1' in scope}} @implementation(Category) extension ObjCClass1 {} // expected-error {{cannot find type 'ObjCClass1' in scope}} -@abi(func fn_abi()) // expected-error {{cannot give global function 'fn' the ABI of a global function with a different number of low-level parameters}} +@abi(func fn_abi()) // expected-error {{cannot give global function 'fn' the ABI of a global function with a different number of parameters}} func fn(_: Int) {} @_alignment(8) struct AnyAlignment {} diff --git a/test/IRGen/asmname.swift b/test/IRGen/asmname.swift index b86cc485723c1..50d40110adfb7 100644 --- a/test/IRGen/asmname.swift +++ b/test/IRGen/asmname.swift @@ -88,19 +88,24 @@ extension X { // CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s7asmname21abi_ABIAttrPublic_vars5Int64Vvs" // CHECK: define hidden swiftcc i64 @"$s7asmname23abi_ABIAttrInternal_vars5Int64Vvg" // CHECK: define hidden swiftcc void @"$s7asmname23abi_ABIAttrInternal_vars5Int64Vvs" -// CHECK: define internal swiftcc i64 @"$s7asmname22abi_ABIAttrPrivate_vars5Int64Vvg" -// CHECK: define internal swiftcc void @"$s7asmname22abi_ABIAttrPrivate_vars5Int64Vvs" +// CHECK: define internal swiftcc i64 @"$s7asmname22abi_ABIAttrPrivate_var33_{{[0-9A-F]+}}LLs5Int64Vvg" +// CHECK: define internal swiftcc void @"$s7asmname22abi_ABIAttrPrivate_var33_{{[0-9A-F]+}}LLs5Int64Vvs" -@abi(public func abi_ABIAttrGenericNonSendableToSendable(_ value: T) -> T) +@abi(func abi_ABIAttrGenericNonSendableToSendable(_ value: T) -> T) public func api_ABIAttrGenericNonSendableToSendable(_ value: T) -> T { return value } // CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s7asmname031abi_ABIAttrGenericNonSendableToF0yxxlF" // NEGATIVE-NOT: @"$s7asmname031abi_ABIAttrGenericNonSendableToF0yxxs0F0RzlF" // Similar to hack applied to `AsyncStream.init(unfolding:onCancel:)` -@abi(public func abi_ABIAttrPreconcurrencyToNotPreconcurrency(_ c1: () -> Void, _ c2: @Sendable () -> Void)) +@abi(func abi_ABIAttrPreconcurrencyToNotPreconcurrency(_ c1: () -> Void, _ c2: @Sendable () -> Void)) @preconcurrency public func api_ABIAttrPreconcurrencyToNotPreconcurrency(_ c1: () -> Void, _ c2: @Sendable () -> Void) {} // CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc void @"$s7asmname030abi_ABIAttrPreconcurrencyToNotD0yyyyXE_yyYbXEtF" +@abi(var abi_ABIAttrVarEffects: Int) +public var api_ABIAttrVarEffects: Int { get async throws { fatalError() } } +// CHECK: define{{( dllexport)?}}{{( protected)?}} swifttailcc void @"$s7asmname21abi_ABIAttrVarEffectsSivg" +// CHECK: define internal swifttailcc void @"$s7asmname21abi_ABIAttrVarEffectsSivgTY0_" + extension X { // CHECK: define{{( dllexport)?}}{{( protected)?}} swiftcc { i64, i8 } @"$s7asmname1XO8abi_blahACs5Int64V_tcfC" @abi(init(abi_blah: Int64)) diff --git a/test/ModuleInterface/attrs.swift b/test/ModuleInterface/attrs.swift index cbda5e5ca8e01..effaa641cc9b7 100644 --- a/test/ModuleInterface/attrs.swift +++ b/test/ModuleInterface/attrs.swift @@ -1,10 +1,13 @@ // RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name attrs \ +// RUN: -emit-private-module-interface-path %t.private.swiftinterface \ // RUN: -enable-experimental-feature ABIAttribute \ // RUN: -enable-experimental-feature ExecutionAttribute // RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name attrs +// RUN: %target-swift-typecheck-module-from-interface(%t.private.swiftinterface) -module-name attrs -// RUN: %FileCheck %s --input-file %t.swiftinterface +// RUN: %FileCheck %s --check-prefixes CHECK,PUBLIC-CHECK --input-file %t.swiftinterface +// RUN: %FileCheck %s --check-prefixes CHECK,PRIVATE-CHECK --input-file %t.private.swiftinterface // REQUIRES: swift_feature_ABIAttribute // REQUIRES: swift_feature_ExecutionAttribute @@ -35,26 +38,55 @@ internal func __specialize_someGenericFunction(_ t: T) -> Int { fatalError("don't call") } -@abi(public func __abi__abiAttrOnFunction(param: Int)) +@abi(func __abi__abiAttrOnFunction(param: Int)) public func abiAttrOnFunction(param: Int) {} // CHECK: #if {{.*}} $ABIAttribute -// CHECK: @abi(public func __abi__abiAttrOnFunction(param: Swift.Int)) +// CHECK: @abi(func __abi__abiAttrOnFunction(param: Swift.Int)) // CHECK: public func abiAttrOnFunction(param: Swift.Int) // CHECK: #else // CHECK: @_silgen_name("$s5attrs07__abi__B14AttrOnFunction5paramySi_tF") // CHECK: public func abiAttrOnFunction(param: Swift.Int) // CHECK: #endif -@abi(public let __abi__abiAttrOnVar: Int) +@abi(let __abi__abiAttrOnVar: Int) public var abiAttrOnVar: Int = 42 // CHECK: #if {{.*}} $ABIAttribute -// CHECK: @abi(public var __abi__abiAttrOnVar: Swift.Int) +// CHECK: @abi(var __abi__abiAttrOnVar: Swift.Int) // CHECK: public var abiAttrOnVar: Swift.Int // CHECK: #else // CHECK: @available(*, unavailable, message: "this compiler cannot match the ABI specified by the @abi attribute") // CHECK: public var abiAttrOnVar: Swift.Int // CHECK: #endif +public struct MutatingTest { + // CHECK: #if {{.*}} $ABIAttribute + // CHECK: @abi(mutating func abiMutFunc()) + // CHECK: public mutating func abiMutFunc() + // CHECK: #else + // CHECK: @_silgen_name("$s5attrs12MutatingTestV10abiMutFuncyyF") + // CHECK: public mutating func abiMutFunc() + // CHECK: #endif + @abi(mutating func abiMutFunc()) + public mutating func abiMutFunc() {} +} + +// PUBLIC-CHECK-NOT: #if {{.*}} $ABIAttribute +// PUBLIC-CHECK-NOT: @abi(func abiSpiFunc()) +// PUBLIC-CHECK-NOT: public func abiSpiFunc() +// PUBLIC-CHECK-NOT: #else +// PUBLIC-CHECK-NOT: @_silgen_name("$s5attrs10abiSpiFuncyyF") +// PUBLIC-CHECK-NOT: public func abiSpiFunc() +// PUBLIC-CHECK-NOT: #endif +// PRIVATE-CHECK: #if {{.*}} $ABIAttribute +// PRIVATE-CHECK: @abi(func abiSpiFunc()) +// PRIVATE-CHECK: public func abiSpiFunc() +// PRIVATE-CHECK: #else +// PRIVATE-CHECK: @_silgen_name("$s5attrs10abiSpiFuncyyF") +// PRIVATE-CHECK: public func abiSpiFunc() +// PRIVATE-CHECK: #endif +@abi(func abiSpiFunc()) +@_spi(spiGroup) public func abiSpiFunc() {} + @execution(concurrent) public func testExecutionConcurrent() async {} // CHECK: @execution(concurrent) public func testExecutionConcurrent() async diff --git a/test/ModuleInterface/attrs_objc.swift b/test/ModuleInterface/attrs_objc.swift new file mode 100644 index 0000000000000..37cb78318be05 --- /dev/null +++ b/test/ModuleInterface/attrs_objc.swift @@ -0,0 +1,45 @@ +// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s \ +// RUN: -enable-objc-interop -module-name attrs_objc \ +// RUN: -enable-experimental-feature ABIAttribute + +// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name attrs_objc + +// RUN: %FileCheck %s --input-file %t.swiftinterface + +// REQUIRES: objc_interop +// REQUIRES: swift_feature_ABIAttribute + +import Foundation + +@objcMembers +public class ObjCTest: NSObject { + // CHECK: #if {{.*}} $ABIAttribute + // CHECK: @abi(func abiObjCFunc()) + // CHECK: @objc public func abiObjCFunc() + // CHECK: #else + // CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC03abiC5CFuncyyF") + // CHECK: @objc public func abiObjCFunc() + // CHECK: #endif + @abi(func abiObjCFunc()) + @objc public func abiObjCFunc() {} + + // CHECK: #if {{.*}} $ABIAttribute + // CHECK: @abi(func abiImplicitObjCFunc()) + // CHECK: @objc public func abiImplicitObjCFunc() + // CHECK: #else + // CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC011abiImplicitC5CFuncyyF") + // CHECK: @objc public func abiImplicitObjCFunc() + // CHECK: #endif + @abi(func abiImplicitObjCFunc()) + public func abiImplicitObjCFunc() {} + + // CHECK: #if {{.*}} $ABIAttribute + // CHECK: @abi(func abiIBActionFunc(_: Any)) + // CHECK: @objc @IBAction @_Concurrency.MainActor @preconcurrency public func abiIBActionFunc(_: Any) + // CHECK: #else + // CHECK: @_silgen_name("$s10attrs_objc8ObjCTestC15abiIBActionFuncyyypF") + // CHECK: @objc @IBAction @_Concurrency.MainActor @preconcurrency public func abiIBActionFunc(_: Any) + // CHECK: #endif + @abi(func abiIBActionFunc(_: Any)) + @IBAction public func abiIBActionFunc(_: Any) {} +} diff --git a/test/attr/Inputs/attr_abi.h b/test/attr/Inputs/attr_abi.h new file mode 100644 index 0000000000000..580cdfb6b20c2 --- /dev/null +++ b/test/attr/Inputs/attr_abi.h @@ -0,0 +1,3 @@ +void implementation1(void); +void implementation2(void); +void implementation3(void); diff --git a/test/attr/attr_abi.swift b/test/attr/attr_abi.swift index a0f8a8e21ea8b..1409d75bf0fdf 100644 --- a/test/attr/attr_abi.swift +++ b/test/attr/attr_abi.swift @@ -1,7 +1,21 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature Extern -enable-experimental-feature ABIAttribute -parse-as-library +// RUN: %target-typecheck-verify-swift -enable-experimental-feature Extern -enable-experimental-feature ABIAttribute -enable-experimental-feature AddressableParameters -enable-experimental-feature NoImplicitCopy -enable-experimental-feature SymbolLinkageMarkers -enable-experimental-feature StrictMemorySafety -enable-experimental-feature LifetimeDependence -enable-experimental-feature CImplementation -enable-experimental-feature ExecutionAttribute -import-bridging-header %S/Inputs/attr_abi.h -parse-as-library -Rabi-inference -debugger-support // REQUIRES: swift_feature_ABIAttribute +// REQUIRES: swift_feature_AddressableParameters +// REQUIRES: swift_feature_CImplementation +// REQUIRES: swift_feature_ExecutionAttribute // REQUIRES: swift_feature_Extern +// REQUIRES: swift_feature_LifetimeDependence +// REQUIRES: swift_feature_NoImplicitCopy +// REQUIRES: swift_feature_StrictMemorySafety +// REQUIRES: swift_feature_SymbolLinkageMarkers + +import _Differentiation + +import Distributed + +@available(SwiftStdlib 5.7, *) +typealias DefaultDistributedActorSystem = LocalTestingDistributedActorSystem // // Same-kind checking @@ -19,6 +33,23 @@ var funcForVar: Int = 0 @abi(var varForFunc_abi: Int) // expected-error {{cannot give global function 'varForFunc()' the ABI of a pattern binding}} func varForFunc() {} +struct SameKind { + @abi(subscript(sub1 _: Int) -> Int) + subscript(sub1 _: Int) -> Int { 0 } + + @abi(func sub2(_: Int) -> Int) // expected-error {{cannot give subscript 'subscript(sub2:)' the ABI of a instance method}} + subscript(sub2 _: Int) -> Int { 0 } + + @abi(subscript(sub3 _: Int) -> Int) // expected-error {{cannot give instance method 'sub3' the ABI of a subscript}} + func sub3(_: Int) -> Int { 0 } + + @abi(var sub4: Int) // expected-error {{cannot give subscript 'subscript(sub4:)' the ABI of a pattern binding}} + subscript(sub4 _: Int) -> Int { 0 } + + @abi(subscript(sub4 _: Int) -> Int) // expected-error {{cannot give property 'sub4' the ABI of a subscript}} + var sub4: Int { 0 } +} + // // Function arity checking // @@ -26,10 +57,10 @@ func varForFunc() {} @abi(func param00_generic00() -> Int) func param00_generic00() -> Int { fatalError() } -@abi(func param10_generic00(_: Int) -> Int) // expected-error {{cannot give global function 'param10_generic00()' the ABI of a global function with a different number of low-level parameters}} +@abi(func param10_generic00(_: Int) -> Int) // expected-error {{cannot give global function 'param10_generic00()' the ABI of a global function with a different number of parameters}} func param10_generic00() -> Int { fatalError() } -@abi(func param01_generic00() -> Int) // expected-error {{cannot give global function 'param01_generic00' the ABI of a global function with a different number of low-level parameters}} +@abi(func param01_generic00() -> Int) // expected-error {{cannot give global function 'param01_generic00' the ABI of a global function with a different number of parameters}} func param01_generic00(_: Int) -> Int { fatalError() } @abi(func param11_generic00(_: Int) -> Int) @@ -37,30 +68,30 @@ func param11_generic00(_: Int) -> Int { fatalError() } -@abi(func param00_generic10() -> T) // expected-error {{cannot give global function 'param00_generic10()' the ABI of a global function with a different number of low-level parameters}} +@abi(func param00_generic10() -> T) // expected-error {{declaration in '@abi' should not have generic signature}} func param00_generic10() -> Int { fatalError() } -@abi(func param10_generic10(_: Int) -> T) // expected-error {{cannot give global function 'param10_generic10()' the ABI of a global function with a different number of low-level parameters}} +@abi(func param10_generic10(_: Int) -> T) // expected-error {{declaration in '@abi' should not have generic signature}} func param10_generic10() -> Int { fatalError() } -@abi(func param01_generic10() -> T) +@abi(func param01_generic10() -> T) // expected-error {{declaration in '@abi' should not have generic signature because 'param01_generic10' is not generic}} func param01_generic10(_: Int) -> Int { fatalError() } -@abi(func param11_generic10(_: Int) -> T) // expected-error {{cannot give global function 'param11_generic10' the ABI of a global function with a different number of low-level parameters}} +@abi(func param11_generic10(_: Int) -> T) // expected-error {{declaration in '@abi' should not have generic signature because 'param11_generic10' is not generic}} func param11_generic10(_: Int) -> Int { fatalError() } -@abi(func param00_generic01() -> Int) // expected-error {{cannot give global function 'param00_generic01()' the ABI of a global function with a different number of low-level parameters}} +@abi(func param00_generic01() -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} func param00_generic01() -> T { fatalError() } -@abi(func param10_generic01(_: Int) -> Int) +@abi(func param10_generic01(_: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} func param10_generic01() -> T { fatalError() } -@abi(func param01_generic01() -> Int) // expected-error {{cannot give global function 'param01_generic01' the ABI of a global function with a different number of low-level parameters}} +@abi(func param01_generic01() -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} func param01_generic01(_: Int) -> T { fatalError() } -@abi(func param11_generic01(_: Int) -> Int) // expected-error {{cannot give global function 'param11_generic01' the ABI of a global function with a different number of low-level parameters}} +@abi(func param11_generic01(_: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} func param11_generic01(_: Int) -> T { fatalError() } @@ -68,19 +99,73 @@ func param11_generic01(_: Int) -> T { fatalError() } @abi(func param00_generic11() -> T) func param00_generic11() -> T { fatalError() } -@abi(func param10_generic11(_: Int) -> T) // expected-error {{cannot give global function 'param10_generic11()' the ABI of a global function with a different number of low-level parameters}} +@abi(func param10_generic11(_: Int) -> T) // expected-error {{cannot give global function 'param10_generic11()' the ABI of a global function with a different number of parameters}} func param10_generic11() -> T { fatalError() } -@abi(func param01_generic11() -> T) // expected-error {{cannot give global function 'param01_generic11' the ABI of a global function with a different number of low-level parameters}} +@abi(func param01_generic11() -> T) // expected-error {{cannot give global function 'param01_generic11' the ABI of a global function with a different number of parameters}} func param01_generic11(_: Int) -> T { fatalError() } @abi(func param11_generic11(_: Int) -> T) func param11_generic11(_: Int) -> T { fatalError() } + + +struct SubscriptArity { + @abi(subscript(param11_generic00 _: Int) -> Int) + subscript(param11_generic00 _: Int) -> Int { 0 } + + @abi(subscript(param21_generic00 _: Int, _: Int) -> Int) // expected-error {{cannot give subscript 'subscript(param21_generic00:)' the ABI of a subscript with a different number of parameters}} + subscript(param21_generic00 _: Int) -> Int { 0 } + + @abi(subscript(param12_generic00 _: Int) -> Int) // expected-error {{cannot give subscript 'subscript(param12_generic00:_:)' the ABI of a subscript with a different number of parameters}} + subscript(param12_generic00 _: Int, _: Int) -> Int { 0 } + + @abi(subscript(param22_generic00 _: Int, _: Int) -> Int) + subscript(param22_generic00 _: Int, _: Int) -> Int { 0 } + + @abi(subscript(param11_generic10 _: T) -> Int) // expected-error {{declaration in '@abi' should not have generic signature because 'subscript(param11_generic10:)' is not generic}} + subscript(param11_generic10 _: Int) -> Int { 0 } + + @abi(subscript(param21_generic10 _: T, _: Int) -> Int) // expected-error {{declaration in '@abi' should not have generic signature because 'subscript(param21_generic10:)' is not generic}} + subscript(param21_generic10 _: Int) -> Int { 0 } + + @abi(subscript(param12_generic10 _: T) -> Int) // expected-error {{declaration in '@abi' should not have generic signature because 'subscript(param12_generic10:_:)' is not generic}} + subscript(param12_generic10 _: Int, _: Int) -> Int { 0 } + + @abi(subscript(param22_generic10 _: T, _: Int) -> Int) // expected-error {{declaration in '@abi' should not have generic signature because 'subscript(param22_generic10:_:)' is not generic}} + subscript(param22_generic10 _: Int, _: Int) -> Int { 0 } + + @abi(subscript(param11_generic01 _: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} + subscript(param11_generic01 _: T) -> Int { 0 } + + @abi(subscript(param21_generic01 _: Int, _: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} + subscript(param21_generic01 _: T) -> Int { 0 } + + @abi(subscript(param12_generic01 _: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} + subscript(param12_generic01 _: T, _: Int) -> Int { 0 } + + @abi(subscript(param22_generic01 _: Int, _: Int) -> Int) // expected-error {{declaration in '@abi' should have generic signature compatible with ''}} + subscript(param22_generic01 _: T, _: Int) -> Int { 0 } + + @abi(subscript(param11_generic11 _: T) -> Int) + subscript(param11_generic11 _: T) -> Int { 0 } + + @abi(subscript(param21_generic11 _: T, _: Int) -> Int) // expected-error {{cannot give subscript 'subscript(param21_generic11:)' the ABI of a subscript with a different number of parameters}} + subscript(param21_generic11 _: T) -> Int { 0 } + + @abi(subscript(param12_generic11 _: T) -> Int) // expected-error {{cannot give subscript 'subscript(param12_generic11:_:)' the ABI of a subscript with a different number of parameters}} + subscript(param12_generic11 _: T, _: Int) -> Int { 0 } + + @abi(subscript(param22_generic11 _: T, _: Int) -> Int) + subscript(param22_generic11 _: T, _: Int) -> Int { 0 } +} + // // Throws effect checking // +enum MyError: Error {} + @abi(func throws00(_: () throws -> Void)) func throws00(_: () throws -> Void) {} @@ -90,6 +175,9 @@ func throws10(_: () throws -> Void) {} @abi(func throws20(_: () throws -> Void) rethrows) // expected-error {{cannot give 'throws20' the ABI of a global function which can throw}} func throws20(_: () throws -> Void) {} +@abi(func throws30(_: () throws -> Void) throws(MyError)) // expected-error {{cannot give 'throws30' the ABI of a global function which can throw}} +func throws30(_: () throws -> Void) {} + @abi(func throws01(_: () throws -> Void)) // expected-error {{cannot give 'throws01' the ABI of a global function which cannot throw}} func throws01(_: () throws -> Void) throws {} @@ -99,6 +187,9 @@ func throws11(_: () throws -> Void) throws {} @abi(func throws21(_: () throws -> Void) rethrows) func throws21(_: () throws -> Void) throws {} +@abi(func throws31(_: () throws -> Void) throws(MyError)) // expected-error {{thrown type 'MyError' in '@abi' should match 'any Error'}} +func throws31(_: () throws -> Void) throws {} // expected-note@:37 {{should match type here}} + @abi(func throws02(_: () throws -> Void)) // expected-error {{cannot give 'throws02' the ABI of a global function which cannot throw}} func throws02(_: () throws -> Void) rethrows {} @@ -108,6 +199,61 @@ func throws12(_: () throws -> Void) rethrows {} @abi(func throws22(_: () throws -> Void) rethrows) func throws22(_: () throws -> Void) rethrows {} +@abi(func throws32(_: () throws -> Void) throws(MyError)) // expected-error {{thrown type 'MyError' in '@abi' should match 'any Error'}} +func throws32(_: () throws -> Void) rethrows {} // expected-note@:37 {{should match type here}} + +@abi(func throws03(_: () throws -> Void)) // expected-error {{cannot give 'throws03' the ABI of a global function which cannot throw}} +func throws03(_: () throws -> Void) throws(MyError) {} + +@abi(func throws13(_: () throws -> Void) throws) // expected-error {{thrown type 'any Error' in '@abi' should match 'MyError'}} +func throws13(_: () throws -> Void) throws(MyError) {} // expected-note@:37 {{should match type here}} + +@abi(func throws23(_: () throws -> Void) rethrows) // expected-error {{thrown type 'any Error' in '@abi' should match 'MyError'}} +func throws23(_: () throws -> Void) throws(MyError) {} // expected-note@:37 {{should match type here}} + +@abi(func throws33(_: () throws -> Void) throws(MyError)) +func throws33(_: () throws -> Void) throws(MyError) {} + +@abi(var throws00Var: Int) +var throws00Var: Int { get { fatalError() } } + +@abi(var throws11Var: Int) +var throws11Var: Int { get throws { fatalError() } } + +enum ErsatzResult {} + +extension ErsatzResult where Failure == Swift.Error { + // The `where` clause makes `throws(Failure)` equivalent to `throws`. + + // Similar to Swift.Result.init(__untyped_throws_catching:) + @abi( + init( + catching body: () throws -> Success + ) + ) + init( + __untyped_throws_catching body: () throws(Failure) -> Success + ) {} + + @abi(func get() throws -> Success) + func __untyped_throws_get() throws(Failure) -> Success { fatalError() } +} + +extension ErsatzResult { + // Should not be allowed, as `Failure` is still generic + @abi( + init( + unconstrainedCatching body: () throws -> Success // expected-error {{parameter 'body' type '() throws -> Success' in '@abi' should match '() throws(Failure) -> Success'}} + ) + ) + init( + __untyped_throws_catching_bad body: () throws(Failure) -> Success // expected-note {{should match type here}} + ) {} + + @abi(func unconstrainedGet() throws -> Success) // expected-error @:32 {{thrown type 'any Error' in '@abi' should match 'Failure'}} + func __untyped_throws_get_bad() throws(Failure) -> Success { fatalError() } // expected-note {{should match type here}} +} + // // Async effect checking // @@ -124,13 +270,11 @@ func async01() async {} @abi(func async11() async) func async11() async {} -// -// Miscellaneous function checking -// +@abi(var async00Var: Int) +var async00Var: Int { get { fatalError() } } -@_silgen_name("conflictingAttrsSilgenName") -@abi(func conflictingAttrsABI()) -func conflictingAttrsAPI() {} // expected-error@-2 {{cannot use '@_silgen_name' and '@abi' on the same global function because they serve the same purpose}} {{1-44=}} +@abi(var async11Var: Int) +var async11Var: Int { get async { fatalError() } } // // PBD shape checking @@ -149,7 +293,7 @@ var (x3, y3): (Int, Int) = (0, 0), a3: Int = 0 var (x4, y4): (Int, Int) = (0, 0), (a4, b4): (Int, Int) = (0, 0) // expected-error {{no match for var 'b4' in the ABI}} // -// Conflict diagnostics +// Redeclaration diagnostics // @abi(func noConflictWithSelf()) @@ -283,6 +427,1870 @@ func fn() { var var_conflictsWithNonABI: Int = 0 // expected-error {{invalid redeclaration of 'var_conflictsWithNonABI'}} } +// +// Type differences +// + +@abi(func floatForIntParam(_ a: Float) -> Int) // expected-error @:33 {{parameter 'a' type 'Float' in '@abi' should match 'Int'}} +func intForFloatParam(_: Int) -> Int { fatalError() } // expected-note @:26 {{should match type here}} + +@abi(func floatForIntResult(_ a: Int) -> Float) // expected-error @:42 {{result type 'Float' in '@abi' should match 'Int'}} +func intForFloatResult(_: Int) -> Int { fatalError() } // expected-note @:35 {{should match type here}} + +@abi(func labeledForUnlabeledTuple(_: (x: Int, y: Int))) +func labeledForUnlabeledTuple(_: (Int, Int)) {} + +@abi(func unlabeledForLabeledTuple(_: (Int, Int))) +func unlabeledForLabeledTuple(_: (x: Int, y: Int)) {} + +@abi(func labeledForLabeledTuple(_: (x: Int, y: Int))) +func labeledForLabeledTuple(_: (a: Int, b: Int)) {} + +@abi( + func testDefaultArguments( + a: Int, + b: Int = 1, // expected-error {{'b' in '@abi' should not have a default argument; it does not affect the parameter's ABI}} + c: Int, + d: Int = 2 // expected-error {{'d' in '@abi' should not have a default argument; it does not affect the parameter's ABI}} + ) +) +func testDefaultArguments( + a: Int, + b: Int, + c: Int = 1, + d: Int = 2 +) {} + +@abi(func arrayForVariadicParam(a: [Int], b: Set)) // expected-error @:46 {{parameter 'b' type 'Set' in '@abi' should match 'Float...'}} +func arrayForVariadicParam(a: Int..., b: Float...) {} // expected-note @:42 {{should match type here}} + +struct DefaultParamOwnership { + @abi( + func method( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with default}} + _ c: borrowing AnyObject, + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with default}} + _ e: __shared AnyObject, + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with default}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with default}} + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(AnyObject) -> Void'}} + ) + ) + func method( + _: AnyObject, + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, // expected-note {{should match type here}} + _: (AnyObject) -> Void, + _: (AnyObject) -> Void, + _: (AnyObject) -> Void // expected-note {{should match type here}} + ) {} + + @abi( + init( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with default}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with default}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with default}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(AnyObject) -> Void'}} + ) + ) + init( + _: AnyObject, + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, + _: AnyObject, // expected-note {{should match type here}} + _: AnyObject, + _: AnyObject, + _: (AnyObject) -> Void, + _: (AnyObject) -> Void, + _: (AnyObject) -> Void // expected-note {{should match type here}} + ) {} +} + +struct InoutParamOwnership { + @abi( + func method( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with 'inout'}} + _ b: inout AnyObject, + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'inout'}} + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with 'inout'}} + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'inout'}} + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with 'inout'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with 'inout'}} + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + ) + ) + func method( + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void // expected-note {{should match type here}} + ) {} + + @abi( + init( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with 'inout'}} + _ b: inout AnyObject, + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'inout'}} + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with 'inout'}} + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'inout'}} + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with 'inout'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with 'inout'}} + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(inout AnyObject) -> Void'}} + ) + ) + init( + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: inout AnyObject, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void, // expected-note {{should match type here}} + _: (inout AnyObject) -> Void // expected-note {{should match type here}} + ) {} +} + +struct BorrowingParamOwnership { + @abi( + func method( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'borrowing'}} + _ c: borrowing AnyObject, + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with 'borrowing'}} + _ e: __shared AnyObject, + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with 'borrowing'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with 'borrowing'}} + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(borrowing AnyObject) -> Void'}} + ) + ) + func method( + _: borrowing AnyObject, + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, // expected-note {{should match type here}} + _: (borrowing AnyObject) -> Void, + _: (borrowing AnyObject) -> Void, + _: (borrowing AnyObject) -> Void // expected-note {{should match type here}} + ) {} + + @abi( + init( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with 'borrowing'}} + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'borrowing'}} + _ c: borrowing AnyObject, + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with 'borrowing'}} + _ e: __shared AnyObject, + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with 'borrowing'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with 'borrowing'}} + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(borrowing AnyObject) -> Void'}} + ) + ) + init( + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, + _: borrowing AnyObject, // expected-note {{should match type here}} + _: borrowing AnyObject, // expected-note {{should match type here}} + _: (borrowing AnyObject) -> Void, + _: (borrowing AnyObject) -> Void, + _: (borrowing AnyObject) -> Void // expected-note {{should match type here}} + ) {} +} + +struct ConsumingParamOwnership { + @abi( + func method( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with 'consuming'}} + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'consuming'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'consuming'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'consuming'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(consuming AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(consuming AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + func method( + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, + _: consuming AnyObject, + _: (consuming AnyObject) -> Void, // expected-note {{should match type here}} + _: (consuming AnyObject) -> Void, // expected-note {{should match type here}} + _: (consuming AnyObject) -> Void + ) {} + + @abi( + init( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'consuming'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'consuming'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'consuming'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(consuming AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(consuming AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + init( + _: consuming AnyObject, + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, + _: consuming AnyObject, // expected-note {{should match type here}} + _: consuming AnyObject, + _: consuming AnyObject, + _: (consuming AnyObject) -> Void, // expected-note {{should match type here}} + _: (consuming AnyObject) -> Void, // expected-note {{should match type here}} + _: (consuming AnyObject) -> Void + ) {} +} + +struct SharedParamOwnership { + @abi( + func method( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with '__shared'}} + _ c: borrowing AnyObject, + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with '__shared'}} + _ e: __shared AnyObject, + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with '__shared'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with '__shared'}} + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(__shared AnyObject) -> Void'}} + ) + ) + func method( + _: __shared AnyObject, + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, // expected-note {{should match type here}} + _: (__shared AnyObject) -> Void, + _: (__shared AnyObject) -> Void, + _: (__shared AnyObject) -> Void // expected-note {{should match type here}} + ) {} + + @abi( + init( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with '__shared'}} + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with '__shared'}} + _ c: borrowing AnyObject, + _ d: consuming AnyObject, // expected-error {{modifier 'consuming' on parameter 'd' in '@abi' is not compatible with '__shared'}} + _ e: __shared AnyObject, + _ f: __owned AnyObject, // expected-error {{modifier '__owned' on parameter 'f' in '@abi' is not compatible with '__shared'}} + _ g: sending AnyObject, // expected-error {{modifier 'sending' on parameter 'g' in '@abi' is not compatible with '__shared'}} + _ h: (AnyObject) -> Void, + _ i: (borrowing AnyObject) -> Void, + _ j: (consuming AnyObject) -> Void // expected-error {{parameter 'j' type '(consuming AnyObject) -> Void' in '@abi' should match '(__shared AnyObject) -> Void'}} + ) + ) + init( + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, + _: __shared AnyObject, // expected-note {{should match type here}} + _: __shared AnyObject, // expected-note {{should match type here}} + _: (__shared AnyObject) -> Void, + _: (__shared AnyObject) -> Void, + _: (__shared AnyObject) -> Void // expected-note {{should match type here}} + ) {} +} + +struct OwnedParamOwnership { + @abi( + func method( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with '__owned'}} + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with '__owned'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with '__owned'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with '__owned'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(__owned AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(__owned AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + func method( + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, + _: __owned AnyObject, + _: (__owned AnyObject) -> Void, // expected-note {{should match type here}} + _: (__owned AnyObject) -> Void, // expected-note {{should match type here}} + _: (__owned AnyObject) -> Void + ) {} + + @abi( + init( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with '__owned'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with '__owned'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with '__owned'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(__owned AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(__owned AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + init( + _: __owned AnyObject, + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, + _: __owned AnyObject, // expected-note {{should match type here}} + _: __owned AnyObject, + _: __owned AnyObject, + _: (__owned AnyObject) -> Void, // expected-note {{should match type here}} + _: (__owned AnyObject) -> Void, // expected-note {{should match type here}} + _: (__owned AnyObject) -> Void + ) {} +} + +struct SendingParamOwnership { + @abi( + func method( + _ a: AnyObject, // expected-error {{default modifier on parameter 'a' in '@abi' is not compatible with 'sending'}} + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'sending'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'sending'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'sending'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(sending AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(sending AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + func method( + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, + _: sending AnyObject, + _: (sending AnyObject) -> Void, // expected-note {{should match type here}} + _: (sending AnyObject) -> Void, // expected-note {{should match type here}} + _: (sending AnyObject) -> Void + ) {} + + @abi( + init( + _ a: AnyObject, + _ b: inout AnyObject, // expected-error {{modifier 'inout' on parameter 'b' in '@abi' is not compatible with 'sending'}} + _ c: borrowing AnyObject, // expected-error {{modifier 'borrowing' on parameter 'c' in '@abi' is not compatible with 'sending'}} + _ d: consuming AnyObject, + _ e: __shared AnyObject, // expected-error {{modifier '__shared' on parameter 'e' in '@abi' is not compatible with 'sending'}} + _ f: __owned AnyObject, + _ g: sending AnyObject, + _ h: (AnyObject) -> Void, // expected-error {{parameter 'h' type '(AnyObject) -> Void' in '@abi' should match '(sending AnyObject) -> Void'}} + _ i: (borrowing AnyObject) -> Void, // expected-error {{parameter 'i' type '(borrowing AnyObject) -> Void' in '@abi' should match '(sending AnyObject) -> Void'}} + _ j: (consuming AnyObject) -> Void + ) + ) + init( + _: sending AnyObject, + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, + _: sending AnyObject, // expected-note {{should match type here}} + _: sending AnyObject, + _: sending AnyObject, + _: (sending AnyObject) -> Void, // expected-note {{should match type here}} + _: (sending AnyObject) -> Void, // expected-note {{should match type here}} + _: (sending AnyObject) -> Void + ) {} +} + +// @autoclosure should be flattened away +@abi( + func autoclosureTest( + _: @autoclosure () -> Void, + _: () -> Void, + _: @autoclosure () -> Void, + _: () -> Void + ) +) +func autoclosureTest( + _: @autoclosure () -> Void, + _: @autoclosure () -> Void, + _: () -> Void, + _: () -> Void +) {} + +// @_nonEphemeral should be flattened away +// (the diagnostic we get on these is actually part of attr checking) +@abi( + func nonEphemeralTest( + @_nonEphemeral _: UnsafeRawPointer, // expected-error {{unused '_nonEphemeral' attribute in '@abi'}} + _: UnsafeRawPointer, + @_nonEphemeral _: UnsafeRawPointer, // expected-error {{unused '_nonEphemeral' attribute in '@abi'}} + _: UnsafeRawPointer + ) +) +func nonEphemeralTest( + @_nonEphemeral _: UnsafeRawPointer, + @_nonEphemeral _: UnsafeRawPointer, + _: UnsafeRawPointer, + _: UnsafeRawPointer +) {} + +// isolated param should be flattened away +@abi(func isolatedTestMismatch(_: isolated A, _: A)) +func isolatedTestMismatch(_: A, _: isolated A) {} + +@abi(func isolatedTestMatch(_: isolated A, _: A)) +func isolatedTestMatch(_: isolated A, _: A) {} + +// _const should be flattened away +@abi( + func constTest( + _: _const () -> Void, + _: () -> Void, + _: _const () -> Void, + _: () -> Void + ) +) +func constTest( + _: _const () -> Void, + _: _const () -> Void, + _: () -> Void, + _: () -> Void +) {} + +// @noDerivative should match +@abi(func noDerivativeTest1(_ a: @differentiable(reverse) (@noDerivative Double, Double) -> Double)) +func noDerivativeTest1(_: @differentiable(reverse) (@noDerivative Double, Double) -> Double) {} + +@abi(func noDerivativeTest2(_ a: @differentiable(reverse) (Double, Double) -> Double)) // expected-error {{parameter 'a' type '@differentiable(reverse) (Double, Double) -> Double' in '@abi' should match '@differentiable(reverse) (@noDerivative Double, Double) -> Double'}} +func noDerivativeTest2(_: @differentiable(reverse) (@noDerivative Double, Double) -> Double) {} // expected-note {{should match type here}} + +@abi(func noDerivativeTest3(_ a: @differentiable(reverse) (@noDerivative Double, Double) -> Double)) // expected-error {{parameter 'a' type '@differentiable(reverse) (@noDerivative Double, Double) -> Double' in '@abi' should match '@differentiable(reverse) (Double, Double) -> Double'}} +func noDerivativeTest3(_: @differentiable(reverse) (Double, Double) -> Double) {} // expected-note {{should match type here}} + +// @_addressable should match +@abi( + func addressableTest( + _ a: @_addressable String, + _ b: String, // expected-error {{default attribute on parameter 'b' in '@abi' is not compatible with '_addressable'}} + _ c: @_addressable String, // expected-error {{attribute '_addressable' on parameter 'c' in '@abi' is not compatible with default}} + _ d: String + ) +) +func addressableTest( + _: @_addressable String, + _: @_addressable String, // expected-note {{should match type here}} + _: String, // expected-note {{should match type here}} + _: String +) {} + +// Flattening of function type ExtInfo +@abi( + func fnExtInfoTest( + _ a: @escaping () -> AnyObject, + _ b: @Sendable () -> AnyObject, + _ c: () -> sending AnyObject, + _ d: () -> AnyObject, + _ e: @MainActor () -> AnyObject, + _ f: (isolated MainActor) -> AnyObject, + _ g: @isolated(any) () -> AnyObject, // expected-error {{parameter 'g' type '@isolated(any) () -> AnyObject' in '@abi' should match '() -> AnyObject'}} + _ h: @execution(caller) () async -> AnyObject, + _ i: () -> AnyObject, // expected-error {{parameter 'i' type '() -> AnyObject' in '@abi' should match '@isolated(any) () -> AnyObject'}} + _ j: () async -> Void, + _ k: () -> Void, // expected-error {{parameter 'k' type '() -> Void' in '@abi' should match '() async -> Void'}} + _ l: () async -> Void, // expected-error {{parameter 'l' type '() async -> Void' in '@abi' should match '() -> Void'}} + _ m: () -> Void, + _ n: () throws -> Void, + _ o: () -> Void, // expected-error {{parameter 'o' type '() -> Void' in '@abi' should match '() throws -> Void'}} + _ p: () throws -> Void, // expected-error {{parameter 'p' type '() throws -> Void' in '@abi' should match '() -> Void'}} + _ q: () -> Void, + _ r: () -> Void, + _ s: @convention(block) () -> Void, // expected-error {{parameter 's' type '@convention(block) () -> Void' in '@abi' should match '() -> Void'}} + _ t: @convention(thin) () -> Void, // expected-error {{parameter 't' type '@convention(thin) () -> Void' in '@abi' should match '() -> Void'}} + _ u: @convention(c) () -> Void // expected-error {{parameter 'u' type '@convention(c) () -> Void' in '@abi' should match '() -> Void'}} + ) +) +func fnExtInfoTest( + _: () -> AnyObject, + _: () -> AnyObject, + _: () -> AnyObject, + _: () -> AnyObject, + _: () -> AnyObject, + _: (MainActor) -> AnyObject, + _: () -> AnyObject, // expected-note {{should match type here}} + _: () async -> AnyObject, + _: @isolated(any) () -> AnyObject, // expected-note {{should match type here}} + _: () async -> Void, + _: () async -> Void, // expected-note {{should match type here}} + _: () -> Void, // expected-note {{should match type here}} + _: () -> Void, + _: () throws -> Void, + _: () throws -> Void, // expected-note {{should match type here}} + _: () -> Void, // expected-note {{should match type here}} + _: () -> Void, + _: () -> Void, + _: () -> Void, // expected-note {{should match type here}} + _: () -> Void, // expected-note {{should match type here}} + _: () -> Void // expected-note {{should match type here}} +) {} + +// FIXME: Not sure how to reach tryNormalizeOutermostType() generic func + +@abi( + func testMarkerProtocols( + _: A, _: B, + _: Any, _: Sendable, + _: AnyKeyPath, _: AnyKeyPath & Sendable, + _: Any, _: Sendable & BitwiseCopyable + ) +) +func testMarkerProtocols( + _: A, _: B, + _: Sendable, _: Any, + _: AnyKeyPath & Sendable, _: AnyKeyPath, + _: Sendable & BitwiseCopyable, _: Any +) {} + +@abi( + func testNormalProtocols( + _ a: Any, // expected-error {{parameter 'a' type 'Any' in '@abi' should match 'any CustomStringConvertible'}} + _ b: CustomStringConvertible, // expected-error {{parameter 'b' type 'any CustomStringConvertible' in '@abi' should match 'Any'}} + _ c: AnyKeyPath, // expected-error {{parameter 'c' type 'AnyKeyPath' in '@abi' should match 'any AnyKeyPath & CustomStringConvertible'}} + _ d: AnyKeyPath & CustomStringConvertible, // expected-error {{parameter 'd' type 'any AnyKeyPath & CustomStringConvertible' in '@abi' should match 'AnyKeyPath'}} + _ e: Any, // expected-error {{parameter 'e' type 'Any' in '@abi' should match 'any CustomDebugStringConvertible & CustomStringConvertible'}} + _ f: CustomStringConvertible & CustomDebugStringConvertible // expected-error {{parameter 'f' type 'any CustomDebugStringConvertible & CustomStringConvertible' in '@abi' should match 'Any'}} + ) +) +func testNormalProtocols( + _: CustomStringConvertible, // expected-note {{should match type here}} + _: Any, // expected-note {{should match type here}} + _: AnyKeyPath & CustomStringConvertible, // expected-note {{should match type here}} + _: AnyKeyPath, // expected-note {{should match type here}} + _: CustomStringConvertible & CustomDebugStringConvertible, // expected-note {{should match type here}} + _: Any // expected-note {{should match type here}} +) {} + +@abi( + func testNormalProtocolsGeneric( // expected-error {{generic signature '' in '@abi' is not compatible with ''}} + _: A, _: B + ) +) +func testNormalProtocolsGeneric( // expected-note {{should match type here}} + _: A, _: B +) {} + +// +// Static/Instance and interactions with `final` +// + +class ClassStaticAndFinal { + @abi(func class00final00()) + func class00final00() {} + + @abi(class func class10final00()) // expected-error {{class method 'class10final00()' in '@abi' should be instance method to ensure ABI compatibility}} {{8-14=}} + func class10final00() {} + + @abi(static func class20final00()) // expected-error {{static method 'class20final00()' in '@abi' should be non-final instance method to ensure ABI compatibility}} {{8-15=}} + func class20final00() {} + + @abi(func class01final00()) // expected-error {{instance method 'class01final00()' in '@abi' should be class method to ensure ABI compatibility}} {{8-8=class }} + class func class01final00() {} + + @abi(func class02final00()) // expected-error {{non-final instance method 'class02final00()' in '@abi' should be static method to ensure ABI compatibility}} {{8-8=static }} + static func class02final00() {} + + @abi(class func class11final00()) + class func class11final00() {} + + @abi(class func class12final00()) // expected-error {{non-final class method 'class12final00()' in '@abi' should be static method to ensure ABI compatibility}} {{8-13=static}} + static func class12final00() {} + + @abi(static func class21final00()) // expected-error {{static method 'class21final00()' in '@abi' should be non-final class method to ensure ABI compatibility}} {{8-14=class}} + class func class21final00() {} + + @abi(static func class22final00()) + static func class22final00() {} + + @abi(final func class00final10()) // expected-error {{final instance method 'class00final10()' in '@abi' should be non-final instance method to ensure ABI compatibility}} {{8-14=}} + func class00final10() {} + + @abi(class final func class10final10()) // expected-error {{final class method 'class10final10()' in '@abi' should be non-final instance method to ensure ABI compatibility}} {{8-14=}} + func class10final10() {} + + @abi(final func class01final10()) // expected-error {{final instance method 'class01final10()' in '@abi' should be non-final class method to ensure ABI compatibility}} {{8-13=class}} + class func class01final10() {} + + @abi(final func class02final10()) // expected-error {{final instance method 'class02final10()' in '@abi' should be static method to ensure ABI compatibility}} {{8-13=static}} + static func class02final10() {} + + @abi(class final func class11final10()) // expected-error {{final class method 'class11final10()' in '@abi' should be non-final class method to ensure ABI compatibility}} {{14-20=}} + class func class11final10() {} + + @abi(class final func class12final10()) + static func class12final10() {} + + @abi(func class00final01()) // expected-error {{non-final instance method 'class00final01()' in '@abi' should be final instance method to ensure ABI compatibility}} {{8-8=final }} + final func class00final01() {} + + @abi(class func class10final01()) // expected-error {{non-final class method 'class10final01()' in '@abi' should be final instance method to ensure ABI compatibility}} {{8-13=final}} + final func class10final01() {} + + @abi(static func class20final01()) // expected-error {{static method 'class20final01()' in '@abi' should be final instance method to ensure ABI compatibility}} {{8-14=final}} + final func class20final01() {} + + @abi(func class01final01()) // expected-error {{non-final instance method 'class01final01()' in '@abi' should be final class method to ensure ABI compatibility}} {{8-8=final class }} + class final func class01final01() {} + + @abi(class func class11final01()) // expected-error {{non-final class method 'class11final01()' in '@abi' should be final class method to ensure ABI compatibility}} {{8-13=final class}} + class final func class11final01() {} + + @abi(static func class21final01()) + class final func class21final01() {} + + @abi(final func class00final11()) + final func class00final11() {} + + @abi(class final func class10final11()) //expected-error {{final class method 'class10final11()' in '@abi' should be final instance method to ensure ABI compatibility}} {{14-20=}} {{8-13=final}} + final func class10final11() {} + + @abi(final func class01final11()) // expected-error {{final instance method 'class01final11()' in '@abi' should be final class method to ensure ABI compatibility}} {{8-13=final class}} + class final func class01final11() {} + + @abi(class final func class11final11()) + class final func class11final11() {} +} + +struct StaticAndFinal { + @abi(func class00final00()) + func class00final00() {} + + @abi(static func class20final00()) // expected-error {{static method 'class20final00()' in '@abi' should be instance method to ensure ABI compatibility}} {{8-15=}} + func class20final00() {} + + @abi(func class02final00()) // expected-error {{instance method 'class02final00()' in '@abi' should be static method to ensure ABI compatibility}} {{8-8=static }} + static func class02final00() {} + + @abi(static func class22final00()) + static func class22final00() {} +} + +// +// Failable Initializers +// + +struct FailableInits { + @abi(init(i11: Void)) + init(i11: Void) {} + + @abi(init?(i21: Void)) // expected-error {{cannot give non-failable initializer 'init(i21:)' the ABI of a failable initializer}} {{12-13=}} + init(i21: Void) {} + + @abi(init!(i31: Void)) // expected-error {{cannot give non-failable initializer 'init(i31:)' the ABI of a failable initializer}} {{12-13=}} + init(i31: Void) {} + + @abi(init(i12: Void)) // expected-error {{cannot give failable initializer 'init(i12:)' the ABI of a non-failable initializer}} {{12-12=?}} + init?(i12: Void) {} + + @abi(init?(i22: Void)) + init?(i22: Void) {} + + @abi(init!(i32: Void)) + init?(i32: Void) {} + + @abi(init(i13: Void)) // expected-error {{cannot give failable initializer 'init(i13:)' the ABI of a non-failable initializer}} {{12-12=!}} + init!(i13: Void) {} + + @abi(init?(i23: Void)) + init!(i23: Void) {} + + @abi(init!(i33: Void)) + init!(i33: Void) {} +} + +// +// Attributes +// + +// @_originallyDefinedIn -- allowed to vary +@abi(@_originallyDefinedIn(module: "Other", macOS 14) func originallyDefinedIn1()) +@available(macOS 12, *) @_originallyDefinedIn(module: "Other", macOS 14) public func originallyDefinedIn1() {} + +@abi(func originallyDefinedIn2()) +@available(macOS 12, *) @_originallyDefinedIn(module: "Other", macOS 14) public func originallyDefinedIn2() {} + +@abi(@_originallyDefinedIn(module: "Other", macOS 14) func originallyDefinedIn3()) +@available(macOS 12, *) public func originallyDefinedIn3() {} + +@abi(@_originallyDefinedIn(module: "Different", macOS 12) func originallyDefinedIn4()) +@available(macOS 12, *) @_originallyDefinedIn(module: "Other", macOS 14) public func originallyDefinedIn4() {} + +// @Sendable -- allowed to vary +@abi(@Sendable func sendable1()) +@Sendable func sendable1() {} + +@abi(@Sendable func sendable2()) +func sendable2() {} + +@abi(func sendable3()) +@Sendable func sendable3() {} + +// @preconcurrency -- allowed to vary +@abi(@preconcurrency func preconcurrency1()) +@preconcurrency func preconcurrency1() {} + +@abi(@preconcurrency func preconcurrency2()) +func preconcurrency2() {} + +@abi(func preconcurrency3()) +@preconcurrency func preconcurrency3() {} + +// @_preInverseGenerics -- allowed to vary +struct PreInverseGenerics { + @abi(@_preInverseGenerics func fn1(_: consuming T)) + @_preInverseGenerics func fn1(_: consuming T) {} + + @abi(@_preInverseGenerics func fn2(_: consuming T)) + func fn2(_: consuming T) {} + + @abi(func fn3(_: consuming T)) + @_preInverseGenerics func fn3(_: consuming T) {} +} + +// 'nonisolated', 'isolated' arguments, global actors -- allowed to vary +@abi(@MainActor func isolation1()) +@MainActor func isolation1() {} + +@abi(func isolation2()) +@MainActor func isolation2() {} + +@abi(@MainActor func isolation3()) +func isolation3() {} + +@abi(nonisolated func isolation4()) +@MainActor func isolation4() {} + +@abi(@MainActor func isolation5()) +nonisolated func isolation5() {} + +@abi(func isolation6(_: isolated some Actor)) +@MainActor func isolation6(_: some Actor) {} + +@abi(func isolation7(_: some Actor)) +func isolation7(_: isolated some Actor) {} + +@abi(@execution(concurrent) func isolation8() async) +@execution(concurrent) func isolation8() async {} + +@abi(func isolation9() async) +@execution(concurrent) func isolation9() async {} + +@abi(@execution(concurrent) func isolation10() async) +func isolation10() async {} + +@abi(nonisolated func isolation11() async) +@execution(concurrent) func isolation11() async {} + +@abi(@execution(concurrent) func isolation12() async) +nonisolated func isolation12() async {} + +@abi(@execution(caller) func isolation13() async) +@execution(caller) func isolation13() async {} + +@abi(func isolation14() async) +@execution(caller) func isolation14() async {} + +@abi(@execution(caller) func isolation15() async) +func isolation15() async {} + +@abi(nonisolated func isolation16() async) +@execution(caller) func isolation16() async {} + +@abi(@execution(caller) func isolation17() async) +nonisolated func isolation17() async {} + +@abi(@execution(caller) func isolation18() async) +@execution(concurrent) func isolation18() async {} + +@abi(@execution(concurrent) func isolation19() async) +@execution(caller) func isolation19() async {} + +// NSCopying - see attr/attr_abi_objc.swift + +// @LLDBDebuggerFunction -- banned in @abi +@abi(@LLDBDebuggerFunction func lldbDebuggerFunction1()) // expected-error {{unused 'LLDBDebuggerFunction' attribute in '@abi'}} {{6-27=}} +@LLDBDebuggerFunction func lldbDebuggerFunction1() {} + +@abi(@LLDBDebuggerFunction func lldbDebuggerFunction2()) // expected-error {{unused 'LLDBDebuggerFunction' attribute in '@abi'}} {{6-27=}} +func lldbDebuggerFunction2() {} + +@abi(func lldbDebuggerFunction3()) +@LLDBDebuggerFunction func lldbDebuggerFunction3() {} + +// @_compilerInitialized -- banned in @abi +class CompilerInitialized { + @abi(@_compilerInitialized let v1: Int) // expected-error {{unused '_compilerInitialized' attribute in '@abi'}} {{8-29=}} + @_compilerInitialized let v1: Int + + @abi(@_compilerInitialized let v2: Int) // expected-error {{unused '_compilerInitialized' attribute in '@abi'}} {{8-29=}} + let v2: Int + + @abi(let v3: Int) + @_compilerInitialized let v3: Int + + init() {} +} + +// @_hasStorage -- banned in @abi +struct HasStorage { + @abi(@_hasStorage let v1: Int) // expected-error {{unused '_hasStorage' attribute in '@abi'}} {{8-20=}} + @_hasStorage let v1: Int + + @abi(@_hasStorage let v2: Int) // expected-error {{unused '_hasStorage' attribute in '@abi'}} {{8-20=}} + let v2: Int + + @abi(let v3: Int) + @_hasStorage let v3: Int + + init() {} +} + +// @discardableResult -- banned in @abi +@abi(@discardableResult func discardableResult1() -> Int) // expected-error {{unused 'discardableResult' attribute in '@abi'}} {{6-24=}} +@discardableResult func discardableResult1() -> Int { 0 } + +@abi(@discardableResult func discardableResult2() -> Int) // expected-error {{unused 'discardableResult' attribute in '@abi'}} {{6-24=}} +func discardableResult2() -> Int { 0 } + +@abi(func lldbDebuggerFunction3() -> Int) +@discardableResult func discardableResult3() -> Int { 0 } + +// @warn_unqualified_access -- banned in @abi +struct WarnUnqualifiedAccess { + @abi(@warn_unqualified_access func fn1()) // expected-error {{unused 'warn_unqualified_access' attribute in '@abi'}} {{8-32=}} + @warn_unqualified_access func fn1() {} + + @abi(@warn_unqualified_access func fn2()) // expected-error {{unused 'warn_unqualified_access' attribute in '@abi'}} {{8-32=}} + func fn2() {} + + @abi(func fn3()) + @warn_unqualified_access func fn3() {} +} + +// @_disfavoredOverload -- banned in @abi +@abi(@_disfavoredOverload func disfavoredOverload1()) // expected-error {{unused '_disfavoredOverload' attribute in '@abi'}} {{6-26=}} +@_disfavoredOverload func disfavoredOverload1() {} + +@abi(@_disfavoredOverload func disfavoredOverload2()) // expected-error {{unused '_disfavoredOverload' attribute in '@abi'}} {{6-26=}} +func disfavoredOverload2() {} + +@abi(func disfavoredOverload3()) +@_disfavoredOverload func disfavoredOverload3() {} + +// @_nonEphemeral -- banned in @abi +@abi(func nonEphemeral1(@_nonEphemeral _: UnsafeRawPointer)) // expected-error {{unused '_nonEphemeral' attribute in '@abi'}} {{25-39=}} +func nonEphemeral1(@_nonEphemeral _: UnsafeRawPointer) {} + +@abi(func nonEphemeral2(@_nonEphemeral _: UnsafeRawPointer)) // expected-error {{unused '_nonEphemeral' attribute in '@abi'}} {{25-39=}} +func nonEphemeral2(_: UnsafeRawPointer) {} + +@abi(func disfavoredOverload3(_: UnsafeRawPointer)) +func nonEphemeral3(@_nonEphemeral _: UnsafeRawPointer) {} + +// @_inheritActorContext -- banned in @abi +@abi(func inheritActorContext1(@_inheritActorContext fn: @Sendable @escaping () async -> Void)) // expected-error {{unused '_inheritActorContext' attribute in '@abi'}} {{32-53=}} +func inheritActorContext1(@_inheritActorContext fn: @Sendable @escaping () async -> Void) {} + +@abi(func inheritActorContext2(@_inheritActorContext fn: @Sendable @escaping () async -> Void)) // expected-error {{unused '_inheritActorContext' attribute in '@abi'}} {{32-53=}} +func inheritActorContext2(fn: @Sendable @escaping () async -> Void) {} + +@abi(func inheritActorContext3(fn: @Sendable @escaping () async -> Void)) +func inheritActorContext3(@_inheritActorContext fn: @Sendable @escaping () async -> Void) {} + +// @excusivity(checked/unchecked) -- banned in @abi +class Exclusivity { + @abi(var checked00: Int) + var checked00: Int = 0 + + @abi(@exclusivity(checked) var checked10: Int) // expected-error {{unused 'exclusivity(checked)' attribute in '@abi'}} {{8-29=}} + var checked10: Int = 0 + + @abi(@exclusivity(unchecked) var checked20: Int) // expected-error {{unused 'exclusivity(unchecked)' attribute in '@abi'}} {{8-31=}} + var checked20: Int = 0 + + @abi(var checked01: Int) + @exclusivity(checked) var checked01: Int = 0 + + @abi(@exclusivity(checked) var checked11: Int) // expected-error {{unused 'exclusivity(checked)' attribute in '@abi'}} {{8-29=}} + @exclusivity(checked) var checked11: Int = 0 + + @abi(@exclusivity(unchecked) var checked21: Int) // expected-error {{unused 'exclusivity(unchecked)' attribute in '@abi'}} {{8-31=}} + @exclusivity(checked) var checked21: Int = 0 + + @abi(var checked02: Int) + @exclusivity(unchecked) var checked02: Int = 0 + + @abi(@exclusivity(checked) var checked12: Int) // expected-error {{unused 'exclusivity(checked)' attribute in '@abi'}} {{8-29=}} + @exclusivity(unchecked) var checked12: Int = 0 + + @abi(@exclusivity(unchecked) var checked22: Int) // expected-error {{unused 'exclusivity(unchecked)' attribute in '@abi'}} {{8-31=}} + @exclusivity(unchecked) var checked22: Int = 0 +} + +// @_noAllocation -- banned in @abi +@abi(@_noAllocation func noAllocation1()) // expected-error {{unused '_noAllocation' attribute in '@abi'}} {{6-20=}} +@_noAllocation func noAllocation1() {} + +@abi(@_noAllocation func noAllocation2()) // expected-error {{unused '_noAllocation' attribute in '@abi'}} {{6-20=}} +func noAllocation2() {} + +@abi(func noAllocation3()) +@_noAllocation func noAllocation3() {} + +// @_noLocks -- banned in @abi +@abi(@_noLocks func noLocks1()) // expected-error {{unused '_noLocks' attribute in '@abi'}} {{6-15=}} +@_noLocks func noLocks1() {} + +@abi(@_noLocks func noLocks2()) // expected-error {{unused '_noLocks' attribute in '@abi'}} {{6-15=}} +func noLocks2() {} + +@abi(func noLocks3()) +@_noLocks func noLocks3() {} + +// @_noImplicitCopy -- banned in @abi +struct NoImplicitCopy { + @abi(@_noImplicitCopy func fn1()) // expected-error {{unused '_noImplicitCopy' attribute in '@abi'}} {{8-24=}} + @_noImplicitCopy func fn1() {} + + @abi(@_noImplicitCopy func fn2()) // expected-error {{unused '_noImplicitCopy' attribute in '@abi'}} {{8-24=}} + func fn2() {} + + @abi(func fn3()) + @_noImplicitCopy func fn3() {} + + @abi(func fn4(@_noImplicitCopy _: Int)) // expected-error {{unused '_noImplicitCopy' attribute in '@abi'}} {{17-33=}} + func fn4(@_noImplicitCopy _: Int) {} + + @abi(func fn5(@_noImplicitCopy _: Int)) // expected-error {{unused '_noImplicitCopy' attribute in '@abi'}} {{17-33=}} + func fn5(_: Int) {} + + @abi(func fn6(_: Int)) + func fn6(@_noImplicitCopy _: Int) {} +} + +// @_noObjCBridging -- banned in @abi +@abi(@_noObjCBridging func noObjCBridging1()) // expected-error {{unused '_noObjCBridging' attribute in '@abi'}} {{6-22=}} +@_noObjCBridging func noObjCBridging1() {} + +@abi(@_noObjCBridging func noObjCBridging2()) // expected-error {{unused '_noObjCBridging' attribute in '@abi'}} {{6-22=}} +func noObjCBridging2() {} + +@abi(func noObjCBridging3()) +@_noObjCBridging func noObjCBridging3() {} + +// @_noExistentials -- banned in @abi +@abi(@_noExistentials func noExistentials1()) // expected-error {{unused '_noExistentials' attribute in '@abi'}} {{6-22=}} +@_noExistentials func noExistentials1() {} + +@abi(@_noExistentials func noExistentials2()) // expected-error {{unused '_noExistentials' attribute in '@abi'}} {{6-22=}} +func noExistentials2() {} + +@abi(func noExistentials3()) +@_noExistentials func noExistentials3() {} + +// @_noRuntime -- banned in @abi +@abi(@_noRuntime func noRuntime1()) // expected-error {{unused '_noRuntime' attribute in '@abi'}} {{6-17=}} +@_noRuntime func noRuntime1() {} + +@abi(@_noRuntime func noRuntime2()) // expected-error {{unused '_noRuntime' attribute in '@abi'}} {{6-17=}} +func noRuntime2() {} + +@abi(func noRuntime3()) +@_noRuntime func noRuntime3() {} + +// @_noEagerMove -- banned in @abi +struct NoEagerMove { + @abi(@_noEagerMove func fn1()) // expected-error {{unused '_noEagerMove' attribute in '@abi'}} {{8-21=}} + @_noEagerMove func fn1() {} + + @abi(@_noEagerMove func fn2()) // expected-error {{unused '_noEagerMove' attribute in '@abi'}} {{8-21=}} + func fn2() {} + + @abi(func fn3()) + @_noEagerMove func fn3() {} + + @abi(func fn4(@_noEagerMove _: Int)) // expected-error {{unused '_noEagerMove' attribute in '@abi'}} {{17-30=}} + func fn4(@_noEagerMove _: Int) {} + + @abi(func fn5(@_noEagerMove _: Int)) // expected-error {{unused '_noEagerMove' attribute in '@abi'}} {{17-30=}} + func fn5(_: Int) {} + + @abi(func fn6(_: Int)) + func fn6(@_noEagerMove _: Int) {} +} + +// @_eagerMove -- banned in @abi +struct EagerMove { + @abi(@_eagerMove func fn1()) // expected-error {{unused '_eagerMove' attribute in '@abi'}} {{8-19=}} + @_eagerMove func fn1() {} + + @abi(@_eagerMove func fn2()) // expected-error {{unused '_eagerMove' attribute in '@abi'}} {{8-19=}} + func fn2() {} + + @abi(func fn3()) + @_eagerMove func fn3() {} + + @abi(func fn4(@_eagerMove _: Int)) // expected-error {{unused '_eagerMove' attribute in '@abi'}} {{17-28=}} + func fn4(@_eagerMove _: Int) {} + + @abi(func fn5(@_eagerMove _: Int)) // expected-error {{unused '_eagerMove' attribute in '@abi'}} {{17-28=}} + func fn5(_: Int) {} + + @abi(func fn6(_: Int)) + func fn6(@_eagerMove _: Int) {} +} + +// @_lexicalLifetimes -- banned in @abi +@abi(@_lexicalLifetimes func lexicalLifetimes1()) // expected-error {{unused '_lexicalLifetimes' attribute in '@abi'}} {{6-24=}} +@_lexicalLifetimes func lexicalLifetimes1() {} + +@abi(@_lexicalLifetimes func lexicalLifetimes2()) // expected-error {{unused '_lexicalLifetimes' attribute in '@abi'}} {{6-24=}} +func lexicalLifetimes2() {} + +@abi(func lexicalLifetimes3()) +@_lexicalLifetimes func lexicalLifetimes3() {} + +// @_assemblyVision -- banned in @abi +@abi(@_assemblyVision func assemblyVision1()) // expected-error {{unused '_assemblyVision' attribute in '@abi'}} {{6-22=}} +@_assemblyVision func assemblyVision1() {} + +@abi(@_assemblyVision func assemblyVision2()) // expected-error {{unused '_assemblyVision' attribute in '@abi'}} {{6-22=}} +func assemblyVision2() {} + +@abi(func assemblyVision3()) +@_assemblyVision func assemblyVision3() {} + +// @_extern -- banned in @abi +@abi(@_extern(c) @_extern(wasm, module: "foo", name: "bar") func extern1()) // expected-error {{unused '_extern' attribute in '@abi'}} {{18-61=}} expected-error {{unused '_extern' attribute in '@abi'}} {{6-17=}} +@_extern(c) @_extern(wasm, module: "foo", name: "bar") func extern1() + +@abi(@_extern(c) @_extern(wasm, module: "foo", name: "bar") func extern2()) // expected-error {{unused '_extern' attribute in '@abi'}} {{18-61=}} expected-error {{unused '_extern' attribute in '@abi'}} {{6-17=}} +func extern2() {} + +@abi(func extern3()) +@_extern(c) @_extern(wasm, module: "foo", name: "bar") func extern3() + +// @_used -- banned in @abi +@abi(@_used func used1()) // expected-error {{unused '_used' attribute in '@abi'}} {{6-12=}} +@_used func used1() {} + +@abi(@_used func used2()) // expected-error {{unused '_used' attribute in '@abi'}} {{6-12=}} +func used2() {} + +@abi(func used3()) +@_used func used3() {} + +// weak, unowned, unowned(unsafe) -- banned in @abi +class ReferenceOwnership { + @abi(var v00: AnyObject?) + var v00: AnyObject? = nil + + @abi(weak var v10: AnyObject?) // expected-error {{unused 'weak' modifier in '@abi'}} {{8-12=}} + var v10: AnyObject? = nil + + @abi(unowned var v20: AnyObject?) // expected-error {{unused 'unowned' modifier in '@abi'}} {{8-15=}} + var v20: AnyObject? = nil + + @abi(unowned(unsafe) var v30: AnyObject?) // expected-error {{unused 'unowned(unsafe)' modifier in '@abi'}} {{8-23=}} + var v30: AnyObject? = nil + + @abi(var v01: AnyObject?) + weak var v01: AnyObject? = nil + + @abi(weak var v11: AnyObject?) // expected-error {{unused 'weak' modifier in '@abi'}} {{8-12=}} + weak var v11: AnyObject? = nil + + @abi(unowned var v21: AnyObject?) // expected-error {{unused 'unowned' modifier in '@abi'}} {{8-15=}} + weak var v21: AnyObject? = nil + + @abi(unowned(unsafe) var v31: AnyObject?) // expected-error {{unused 'unowned(unsafe)' modifier in '@abi'}} {{8-23=}} + weak var v31: AnyObject? = nil + + @abi(var v02: AnyObject?) + unowned var v02: AnyObject? = nil + + @abi(weak var v12: AnyObject?) // expected-error {{unused 'weak' modifier in '@abi'}} {{8-12=}} + unowned var v12: AnyObject? = nil + + @abi(unowned var v22: AnyObject?) // expected-error {{unused 'unowned' modifier in '@abi'}} {{8-15=}} + unowned var v22: AnyObject? = nil + + @abi(unowned(unsafe) var v32: AnyObject?) // expected-error {{unused 'unowned(unsafe)' modifier in '@abi'}} {{8-23=}} + unowned var v32: AnyObject? = nil + + @abi(var v03: AnyObject?) + unowned(unsafe) var v03: AnyObject? = nil + + @abi(weak var v13: AnyObject?) // expected-error {{unused 'weak' modifier in '@abi'}} {{8-12=}} + unowned(unsafe) var v13: AnyObject? = nil + + @abi(unowned var v23: AnyObject?) // expected-error {{unused 'unowned' modifier in '@abi'}} {{8-15=}} + unowned(unsafe) var v23: AnyObject? = nil + + @abi(unowned(unsafe) var v33: AnyObject?) // expected-error {{unused 'unowned(unsafe)' modifier in '@abi'}} {{8-23=}} + unowned(unsafe) var v33: AnyObject? = nil +} + +// @abi -- banned in @abi (no recursion) +@abi( + @abi(func abiRecursion()) // expected-error {{unused 'abi' attribute in '@abi'}} {{3-29=}} + func abiRecursion() +) +func abiRecursion() {} + +// @unsafe -- banned in @abi +@abi(@unsafe func unsafe1()) // expected-error {{unused 'unsafe' attribute in '@abi'}} {{6-13=}} +@unsafe func unsafe1() {} + +@abi(@unsafe func unsafe2()) // expected-error {{unused 'unsafe' attribute in '@abi'}} {{6-13=}} +func unsafe2() {} + +@abi(func unsafe3()) +@unsafe func unsafe3() {} + +// @safe -- banned in @abi +@abi(@safe func safe1()) // expected-error {{unused 'safe' attribute in '@abi'}} {{6-11=}} +@safe func safe1() {} + +@abi(@safe func safe2()) // expected-error {{unused 'safe' attribute in '@abi'}} {{6-11=}} +func safe2() {} + +@abi(func safe3()) +@safe func safe3() {} + +// Access control, @usableFromInline, @_spi -- banned in @abi +// An ABI-only decl gets its access control from its counterpart. +@abi(internal func accessControl1()) // expected-error {{unused 'internal' modifier in '@abi'}} {{6-14=}} +func accessControl1() {} + +@abi(func accessControl2()) +public func accessControl2() {} + +@abi(@usableFromInline func accessControl3()) // expected-error {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'accessControl3()' is public}} +public func accessControl3() {} + +@abi(private(set) var setterAccess1: Int) // expected-error {{unused 'private' modifier in '@abi'}} {{6-18=}} +var setterAccess1: Int = 42 + +@abi(var setterAccess2: Int) +private(set) var setterAccess2: Int = 42 + +@abi(@usableFromInline func usableFromInline1()) // expected-error {{unused 'usableFromInline' attribute in '@abi'}} {{6-23=}} +@usableFromInline func usableFromInline1() {} + +@abi(func usableFromInline2()) +@usableFromInline func usableFromInline2() {} + +@_spi(foo) public struct SPIType {} // expected-note 2 {{struct declared here}} + +@abi(@_spi(foo) func spi1(_: SPIType)) // expected-error {{unused '_spi' attribute in '@abi'}} {{6-16=}} +@_spi(foo) public func spi1(_: SPIType) {} + +@abi(func spi2(_: SPIType)) +@_spi(foo) public func spi2(_: SPIType) {} + +@abi(func spi3(_: SPIType)) // expected-error {{cannot use struct 'SPIType' here; it is SPI}} +public func spi3(_: SPIType) {} // expected-error {{cannot use struct 'SPIType' here; it is SPI}} + +// @available, @_unavailable*, @backDeployed -- banned in @abi +// An ABI-only decl gets its availability from its counterpart. +@abi(@available(macOS 14, iOS 16, *) func available1()) // expected-error {{unused 'available' attribute in '@abi'}} {{6-37=}} +@available(macOS 14, iOS 16, *) func available1() {} + +@abi(@available(macOS 14, iOS 16, *) func available2()) // expected-error {{unused 'available' attribute in '@abi'}} {{6-37=}} +func available2() {} + +@abi(func available3()) +@available(macOS 14, iOS 16, *) func available3() {} + +@abi( + @available(macOS, unavailable) // expected-error {{unused 'available' attribute in '@abi'}} {{3-34=}} + @available(iOS, deprecated) // expected-error {{unused 'available' attribute in '@abi'}} {{3-31=}} + func available4() +) +@available(macOS 14, iOS 16, *) func available4() {} + +// Additional tests in attr/attr_abi_objc.swift + +@abi(@_unavailableFromAsync func unavailableFromAsync1()) // expected-error {{unused '_unavailableFromAsync' attribute in '@abi'}} {{6-28=}} +@_unavailableFromAsync func unavailableFromAsync1() {} + +@abi(@_unavailableFromAsync func unavailableFromAsync2()) // expected-error {{unused '_unavailableFromAsync' attribute in '@abi'}} {{6-28=}} +func unavailableFromAsync2() {} + +@abi(func unavailableFromAsync3()) +@_unavailableFromAsync func unavailableFromAsync3() {} + +// FIXME: Test @_unavailableInEmbedded (it gets rewritten in the parser) + +@abi(@backDeployed(before: macOS 14) func backDeployed1()) // expected-error {{unused 'backDeployed' attribute in '@abi'}} {{6-37=}} +@backDeployed(before: macOS 14) public func backDeployed1() {} + +@abi(@backDeployed(before: macOS 14) func backDeployed2()) // expected-error {{unused 'backDeployed' attribute in '@abi'}} {{6-37=}} +public func backDeployed2() {} + +@abi(func backDeployed3()) +@backDeployed(before: macOS 14) public func backDeployed3() {} + +// override, @_nonoverride -- banned in @abi +// An ABI-only decl gets its overrides from its counterpart; no marker modifiers +// are required. +class Overridden { + func fn1() {} + + func fn2() {} // expected-note 2 {{overridden declaration is here}} + + func fn3() {} +} + +class Override: Overridden { + @abi(override func fn1()) // expected-error {{unused 'override' modifier in '@abi'}} {{8-16=}} + override func fn1() {} + + @abi(override func fn2()) // expected-error {{unused 'override' modifier in '@abi'}} {{8-16=}} + func fn2() {} // expected-error {{overriding declaration requires an 'override' keyword}} + + @abi(func fn3()) + override func fn3() {} +} + +class NonOverride: Overridden { + @abi(@_nonoverride func fn1()) // expected-error {{unused '_nonoverride' attribute in '@abi'}} {{8-21=}} + @_nonoverride func fn1() {} + + @abi(@_nonoverride func fn2()) // expected-error {{unused '_nonoverride' attribute in '@abi'}} {{8-21=}} + func fn2() {} // expected-error {{overriding declaration requires an 'override' keyword}} + + @abi(func fn3()) + @_nonoverride func fn3() {} +} + +// @_silgen_name -- banned in @abi *and* on declarations with @abi +// Becuase of the way @_silgen_name is implemented, these would interact oddly +// if they were allowed on the same decl. +@_silgen_name("conflictingAttrsSilgenName") +@abi(func silgenName1()) +func silgenName1() {} // expected-error@-2 {{cannot use '@_silgen_name' and '@abi' on the same global function because they serve the same purpose}} {{1-44=}} + +@abi(@_silgen_name("silgenNameWithABI") func silgenName2()) // expected-error {{unused '_silgen_name' attribute in '@abi'}} {{6-40=}} +func silgenName2() {} + +// @_documentation(visibility:metadata:) -- banned in @abi +@abi(@_documentation(visibility: public) func documentation1()) // expected-error {{unused '_documentation' attribute in '@abi'}} {{6-41=}} +@_documentation(visibility: public) func documentation1() {} + +@abi(@_documentation(visibility: public) func documentation2()) // expected-error {{unused '_documentation' attribute in '@abi'}} {{6-41=}} +func documentation2() {} + +@abi(func documentation3()) +@_documentation(visibility: public) func documentation3() {} + +// @_allowFeatureSuppression -- banned in @abi +// Feature suppression should be applied to the API since we can't put `#if` +// inside `@abi`. +@abi(@_allowFeatureSuppression(IsolatedAny) func allowFeatureSuppression1()) // expected-error {{unused '_allowFeatureSuppression' attribute in '@abi'}} {{6-44=}} +@_allowFeatureSuppression(IsolatedAny) func allowFeatureSuppression1() {} + +@abi(@_allowFeatureSuppression(IsolatedAny) func allowFeatureSuppression2()) // expected-error {{unused '_allowFeatureSuppression' attribute in '@abi'}} {{6-44=}} +func allowFeatureSuppression2() {} + +@abi(func allowFeatureSuppression3()) +@_allowFeatureSuppression(IsolatedAny) func allowFeatureSuppression3() {} + +// @objc -- tested in attr/attr_abi_objc.swift +// @IBAction -- tested in attr/attr_abi_objc.swift +// @IBInspectable -- tested in attr/attr_abi_objc.swift +// @GKInspectable -- tested in attr/attr_abi_objc.swift +// @IBOutlet -- tested in attr/attr_abi_objc.swift +// @IBSegueAction -- tested in attr/attr_abi_objc.swift +// @NSManaged -- tested in attr/attr_abi_objc.swift +// @nonobjc -- tested in attr/attr_abi_objc.swift +// optional -- tested in attr/attr_abi_objc.swift +// dynamic -- tested in attr/attr_abi_objc.swift + +// @_cdecl -- banned in @abi +// ABI-only decls inherit cdecl-ness from their counterpart +@abi(@_cdecl("cdecl1") func cdecl1()) // expected-error {{unused '_cdecl' attribute in '@abi'}} {{6-23=}} +@_cdecl("cdecl1") func cdecl1() {} + +@abi(@_cdecl("cdecl2") func cdecl2()) // expected-error {{unused '_cdecl' attribute in '@abi'}} {{6-23=}} +func cdecl2() {} + +@abi(func cdecl3()) +@_cdecl("cdecl3") func cdecl3() {} + +// @implementation -- banned in @abi +// ABI-only decls inherit implementation-ness from their counterpart +@abi(@implementation func implementation1()) // expected-error {{unused 'implementation' attribute in '@abi'}} {{6-21=}} +@_cdecl("implementation1") @implementation func implementation1() {} + +@abi(@implementation func implementation2()) // expected-error {{unused 'implementation' attribute in '@abi'}} {{6-21=}} +@_cdecl("implementation2") func implementation2() {} + +@abi(func implementation3()) +@_cdecl("implementation3") @implementation func implementation3() {} + +// @_expose -- banned in @abi +// ABI-only decls inherit exposure from their counterpart +@abi(@_expose(Cxx) func expose1()) // expected-error {{unused '_expose' attribute in '@abi'}} {{6-19=}} +@_expose(Cxx) func expose1() {} + +@abi(@_expose(Cxx) func expose2()) // expected-error {{unused '_expose' attribute in '@abi'}} {{6-19=}} +func expose2() {} + +@abi(func expose3()) +@_expose(Cxx) func expose3() {} + +// @_section -- banned in @abi +@abi(@_section("fnord") func section1()) // expected-error {{unused '_section' attribute in '@abi'}} {{6-24=}} +@_section("fnord") func section1() {} + +@abi(@_section("fnord") func section2()) // expected-error {{unused '_section' attribute in '@abi'}} {{6-24=}} +func section2() {} + +@abi(func section3()) +@_section("fnord") func section3() {} + +// @inlinable -- automatically cloned into @abi +@abi(@inlinable func inlinable1()) +@inlinable func inlinable1() {} + +@abi(@inlinable func inlinable2()) // expected-error {{extra 'inlinable' attribute in '@abi'}} {{6-16=}} +func inlinable2() {} + +@abi(func inlinable3()) // expected-remark {{inferred '@inlinable' in '@abi' to match attribute on API}} +@inlinable func inlinable3() {} // expected-note {{matches attribute here}} + +// @inline -- automatically cloned into @abi +@abi(@inline(never) func inline1()) +@inline(never) func inline1() {} + +@abi(@inline(never) func inline2()) // expected-error {{extra 'inline(never)' attribute in '@abi'}} {{6-20=}} +func inline2() {} + +@abi(func inline3()) // expected-remark {{inferred '@inline(never)' in '@abi' to match attribute on API}} +@inline(never) func inline3() {} // expected-note {{matches attribute here}} + +// @_transparent -- automatically cloned into @abi +@abi(@_transparent func transparent1()) +@_transparent func transparent1() {} + +@abi(@_transparent func transparent2()) // expected-error {{extra '_transparent' attribute in '@abi'}} {{6-19=}} +func transparent2() {} + +@abi(func transparent3()) // expected-remark {{inferred '@_transparent' in '@abi' to match attribute on API}} +@_transparent func transparent3() {} // expected-note {{matches attribute here}} + +// @_alwaysEmitIntoClient -- automatically cloned into @abi +@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient1()) +@_alwaysEmitIntoClient func alwaysEmitIntoClient1() {} + +@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient2()) // expected-error {{extra '_alwaysEmitIntoClient' attribute in '@abi'}} {{6-28=}} +func alwaysEmitIntoClient2() {} + +@abi(func alwaysEmitIntoClient3()) // expected-remark {{inferred '@_alwaysEmitIntoClient' in '@abi' to match attribute on API}} +@_alwaysEmitIntoClient func alwaysEmitIntoClient3() {} // expected-note {{matches attribute here}} + +// @_optimize(none) -- banned in @abi +@abi(@_optimize(none) func optimize1()) // expected-error {{unused '_optimize(none)' attribute in '@abi'}} {{6-22=}} +@_optimize(none) func optimize1() {} + +@abi(@_optimize(none) func optimize2()) // expected-error {{unused '_optimize(none)' attribute in '@abi'}} {{6-22=}} +func optimize2() {} + +@abi(func optimize3()) +@_optimize(none) func optimize3() {} + +// convenience -- must match in @abi +// This doesn't have direct mangling impact, but a future direction where +// convenience inits could fake designated inits or vice versa might be useful. +class Convenience { + @abi(convenience init(i1: Void)) + convenience init(i1: Void) { fatalError() } + + @abi(convenience init(i2: Void)) // expected-error {{extra 'convenience' modifier in '@abi'}} {{8-19=}} + init(i2: Void) { fatalError() } + + @abi(init(i3: Void)) // expected-error {{missing 'convenience' modifier in '@abi'}} {{8-8=convenience }} + convenience init(i3: Void) { fatalError() } // expected-note {{should match modifier here}} +} + +// required -- must match in @abi +// This doesn't have direct mangling impact, but a future direction where +// required inits could fake normal inits or vice versa might be useful. +class Required { + @abi(required init(i1: Void)) + required init(i1: Void) { fatalError() } + + @abi(required init(i2: Void)) // expected-error {{extra 'required' modifier in '@abi'}} {{8-16=}} + init(i2: Void) { fatalError() } + + @abi(init(i3: Void)) // expected-error {{missing 'required' modifier in '@abi'}} {{8-8=required }} + required init(i3: Void) { fatalError() } // expected-note {{should match modifier here}} +} + +// lazy -- automatically cloned into @abi +class Lazy { + @abi(lazy var v1: Int) + lazy var v1: Int = 0 + + @abi(lazy var v2: Int) // expected-error {{extra 'lazy' modifier in '@abi'}} {{8-12=}} + var v2: Int = 0 + + @abi(var v3: Int) // expected-remark {{inferred 'lazy' in '@abi' to match modifier on API}} + lazy var v3: Int = 0 // expected-note {{matches modifier here}} +} + +// @_fixed_layout -- banned in @abi +class FixedLayoutVars { + @abi(@_fixed_layout var v1: Int) // expected-error {{unused '_fixed_layout' attribute in '@abi'}} {{8-22=}} + @_fixed_layout public var v1: Int = 0 + + @abi(@_fixed_layout var v2: Int) // expected-error {{unused '_fixed_layout' attribute in '@abi'}} {{8-22=}} + public var v2: Int = 0 + + @abi(var v3: Int) + @_fixed_layout public var v3: Int = 0 +} + +// @_specialize -- banned in @abi +// TODO: Maybe use @_specialize in @abi to tweak the ABI of specializations. +// Ban it for now, since there's nothing useful you can do with it yet. +@abi(@_specialize(where T == Int) func specialize1(_: T)) // expected-error {{unused '_specialize' attribute in '@abi'}} {{6-34=}} +@_specialize(where T == Int) func specialize1(_: T) {} + +@abi(@_specialize(where T == Int) func specialize2(_: T)) // expected-error {{unused '_specialize' attribute in '@abi'}} {{6-34=}} +func specialize2(_: T) {} + +@abi(func specialize3(_: T)) +@_specialize(where T == Int) func specialize3(_: T) {} + +// @_effects -- banned in @abi +@abi(@_effects(readonly) func effects1()) // expected-error {{unused '_effects(readonly)' attribute in '@abi'}} {{6-25=}} +@_effects(readonly) func effects1() {} + +@abi(@_effects(readonly) func effects2()) // expected-error {{unused '_effects(readonly)' attribute in '@abi'}} {{6-25=}} +func effects2() {} + +@abi(func effects3()) +@_effects(readonly) func effects3() {} + +// @_implements -- banned in @abi +protocol ImplementsProto { + func f1() + func f2() + func f3() +} + +class Implements: ImplementsProto { + @abi(@_implements(ImplementsProto, f1) func f1()) // expected-error {{unused '_implements' attribute in '@abi'}} {{8-41=}} + @_implements(ImplementsProto, f1) func f1() {} + + @abi(@_implements(ImplementsProto, f2) func f2()) // expected-error {{unused '_implements' attribute in '@abi'}} {{8-41=}} + func f2() {} + + @abi(func f3()) + @_implements(ImplementsProto, f3) func f3() {} +} + +// @_dynamicReplacement -- banned in @abi +struct DynamicReplacement { + dynamic func f1Original() {} + dynamic func f2Original() {} + dynamic func f3Original() {} +} + +extension DynamicReplacement { + @abi(@_dynamicReplacement(for: f1Original) func f1()) // expected-error {{unused '_dynamicReplacement' attribute in '@abi'}} {{8-45=}} + @_dynamicReplacement(for: f1Original) func f1() {} + + @abi(@_dynamicReplacement(for: f2Original) func f2()) // expected-error {{unused '_dynamicReplacement' attribute in '@abi'}} {{8-45=}} + func f2() {} + + @abi(func f3()) + @_dynamicReplacement(for: f3Original) func f3() {} +} + +// @_weakLinked -- tested in attr/attr_weaklinked.swift + +// @_borrowed -- automatically cloned into @abi +protocol BorrowedAttr { + @abi(@_borrowed var v1: Int) + @_borrowed var v1: Int { get set } + + @abi(var v2: Int) // expected-remark {{inferred '@_borrowed' in '@abi' to match attribute on API}} + @_borrowed var v2: Int { get set } // expected-note {{matches attribute here}} + + @abi(@_borrowed var v3: Int) // expected-error {{extra '_borrowed' attribute in '@abi'}} {{8-18=}} + var v3: Int { get set } +} + +// @lifetime -- must match in @abi +// TODO: Probably possible to make these unconstrained as long as we ensure +// that `@_addressableForDependencies` doesn't cause a calling convention +// change. +struct Lifetime: ~Escapable { + @abi(@lifetime(borrow i1) init(i1: UnsafeRawPointer)) + @lifetime(borrow i1) init(i1: UnsafeRawPointer) {} + + @abi(@lifetime(borrow i2) init(i2: UnsafeRawPointer)) // expected-error {{extra 'lifetime' attribute in '@abi'}} {{8-28=}} + init(i2: UnsafeRawPointer) {} + + @abi(init(i3: UnsafeRawPointer)) // expected-error {{missing 'lifetime' attribute in '@abi'}} {{8-8=@lifetime(borrow i3) }} + @lifetime(borrow i3) init(i3: UnsafeRawPointer) {} // expected-note {{should match attribute here}} + + @abi(@lifetime(borrow i4) init(i4: UnsafeRawPointer, i4a: UnsafeRawPointer)) // expected-error {{'lifetime' attribute in '@abi' should match '@lifetime(borrow i4a)'}} {{8-28=@lifetime(borrow i4a)}} + @lifetime(borrow i4a) init(i4: UnsafeRawPointer, i4a: UnsafeRawPointer) {} // expected-note {{should match attribute here}} +} + +// @_unsafeNonescapableResult -- must match in @abi +// TODO: This could probably be allowed to vary in some circumstances. +struct UnsafeNonescapableResult: ~Escapable { + @abi(@_unsafeNonescapableResult init(i1: UnsafeRawPointer)) + @_unsafeNonescapableResult init(i1: UnsafeRawPointer) {} + + @abi(@_unsafeNonescapableResult init(i2: UnsafeRawPointer)) // expected-error {{extra '_unsafeNonescapableResult' attribute in '@abi'}} {{8-34=}} + init(i2: UnsafeRawPointer) {} + + @abi(init(i3: UnsafeRawPointer)) // expected-error {{missing '_unsafeNonescapableResult' attribute in '@abi'}} {{8-8=@_unsafeNonescapableResult }} + @_unsafeNonescapableResult init(i3: UnsafeRawPointer) {} // expected-note {{should match attribute here}} +} + +// distributed -- must match in @abi +@available(SwiftStdlib 5.7, *) +distributed actor Local { + @abi(distributed func fn1()) + distributed func fn1() {} + + @abi(distributed func fn2()) // expected-error {{extra 'distributed' modifier in '@abi'}} {{8-19=}} + func fn2() {} + + @abi(func fn3()) // expected-error {{missing 'distributed' modifier in '@abi'}} {{8-8=distributed }} + distributed func fn3() {} // expected-note {{should match modifier here}} +} + +// _const -- allowed to vary +@abi(func const1(_: _const Int)) +func const1(_: _const Int) {} + +@abi(func const2(_: _const Int)) +func const2(_: Int) {} + +@abi(func const3(_: Int)) +func const3(_: _const Int) {} + +// @derivative, @differentiable, @transpose, @_noDerivative -- banned in @abi +// Too complex to infer or check +// TODO: Figure out if there's something we could do here. +@abi(@differentiable(reverse) func differentiable1(_ x: Float) -> Float) // expected-error {{unused 'differentiable' attribute in '@abi'}} {{6-30=}} +@differentiable(reverse) func differentiable1(_ x: Float) -> Float { x } + +@abi(@differentiable(reverse) func differentiable2(_ x: Float) -> Float) // expected-error {{unused 'differentiable' attribute in '@abi'}} {{6-30=}} +func differentiable2(_ x: Float) -> Float { x } + +@abi(func differentiable3(_ x: Float) -> Float) +@differentiable(reverse) func differentiable3(_ x: Float) -> Float { x } + +@abi( + @derivative(of: differentiable1(_:)) // expected-error {{unused 'derivative' attribute in '@abi'}} {{3-40=}} + func derivative1(_: Float) -> (value: Float, differential: (Float) -> (Float)) +) +@derivative(of: differentiable1(_:)) +func derivative1(_ x: Float) -> (value: Float, differential: (Float) -> (Float)) { + return (x, { $0 }) +} + +@abi( + @derivative(of: differentiable2(_:)) // expected-error {{unused 'derivative' attribute in '@abi'}} {{3-40=}} + func derivative2(_: Float) -> (value: Float, differential: (Float) -> (Float)) +) +func derivative2(_ x: Float) -> (value: Float, differential: (Float) -> (Float)) { + return (x, { $0 }) +} + +@abi( + func derivative3(_: Float) -> (value: Float, differential: (Float) -> (Float)) +) +@derivative(of: differentiable3(_:)) +func derivative3(_ x: Float) -> (value: Float, differential: (Float) -> (Float)) { + return (x, { $0 }) +} + +struct Transpose where T == T.TangentVector { + func fn1(_ x: T, _ y: T) -> T { x + y } + func fn2(_ x: T, _ y: T) -> T { x + y } + func fn3(_ x: T, _ y: T) -> T { x + y } + + @abi( + @transpose(of: fn1, wrt: (0, 1)) // expected-error {{unused 'transpose' attribute in '@abi'}} {{5-38=}} + func t_fn1(_ result: T) -> (T, T) + ) + @transpose(of: fn1, wrt: (0, 1)) + func t_fn1(_ result: T) -> (T, T) { (result, result) } + + @abi( + @transpose(of: fn2, wrt: (0, 1)) // expected-error {{unused 'transpose' attribute in '@abi'}} {{5-38=}} + func t_fn2(_ result: T) -> (T, T) + ) + func t_fn2(_ result: T) -> (T, T) { (result, result) } + + @abi( + func t_fn3(_ result: T) -> (T, T) + ) + @transpose(of: fn3, wrt: (0, 1)) + func t_fn3(_ result: T) -> (T, T) { (result, result) } +} + +struct NoDerivative { + @abi(@noDerivative func fn1()) // expected-error {{unused 'noDerivative' attribute in '@abi'}} {{8-21=}} + @noDerivative func fn1() {} + + @abi(@noDerivative func fn2()) // expected-error {{unused 'noDerivative' attribute in '@abi'}} {{8-21=}} + func fn2() {} + + @abi(func fn3()) + @noDerivative func fn3() {} +} + +// prefix, postfix -- allowed to vary +// Essentially part of the name, which is unconstrained. +prefix operator ← +prefix operator ↑ // expected-note {{prefix operator found here}} +prefix operator → // expected-note {{prefix operator found here}} +prefix operator ↓ + +struct Prefix { + @abi(static prefix func ← (value: Self) -> Self) + static prefix func ← (value: Self) -> Self { value } + + @abi(static prefix func ↑ (value: Self) -> Self) + static func ↑ (value: Self) -> Self { value } // expected-error {{prefix unary operator missing 'prefix' modifier}} + + @abi(static func → (value: Self) -> Self) // expected-error {{prefix unary operator missing 'prefix' modifier}} + static prefix func → (value: Self) -> Self { value } + + // Test ABI-preserving replacement code pattern: + + @abi(static prefix func ↓ (value: Self) -> Self) + static func __oldDownArrow(value: Self) -> Self { value } + + @abi(static func __newDownArrow(value: Self) -> Self) + static prefix func ↓ (value: Self) -> Self { value } +} + +postfix operator ←← +postfix operator ↑↑ // expected-note {{postfix operator found here}} +postfix operator →→ // expected-note {{postfix operator found here}} +postfix operator ↓↓ + +struct Postfix { + @abi(static postfix func ←← (value: Self) -> Self) + static postfix func ←← (value: Self) -> Self { value } + + @abi(static postfix func ↑↑ (value: Self) -> Self) + static func ↑↑ (value: Self) -> Self { value } // expected-error {{postfix unary operator missing 'postfix' modifier}} + + @abi(static func →→ (value: Self) -> Self) // expected-error {{postfix unary operator missing 'postfix' modifier}} + static postfix func →→ (value: Self) -> Self { value } + + // Test ABI-preserving replacement code pattern: + + @abi(static postfix func ↓↓ (value: Self) -> Self) + static func __oldDownArrow(value: Self) -> Self { value } + + @abi(static func __newDownArrow(value: Self) -> Self) + static postfix func ↓↓ (value: Self) -> Self { value } +} + +// Not testing `infix`; it's not *really* valid on funcs. + +// nonmutating, borrowing, consuming, __consuming, mutating -- allowed to vary +// Act like param modifiers; checked against each other separately +struct SelfParamOwnership { + @abi(func fn00()) + func fn00() {} + + @abi(nonmutating func fn10()) + func fn10() {} + + @abi(borrowing func fn20()) + func fn20() {} + + @abi(consuming func fn30()) // expected-error {{modifier 'consuming' on self parameter in '@abi' is not compatible with default}} {{none}} + func fn30() {} // expected-note {{should match modifier here}} + + @abi(__consuming func fn40()) // expected-error {{modifier '__consuming' on self parameter in '@abi' is not compatible with default}} {{none}} + func fn40() {} // expected-note {{should match modifier here}} + + @abi(mutating func fn50()) // expected-error {{modifier 'mutating' on self parameter in '@abi' is not compatible with default}} {{none}} + func fn50() {} // expected-note {{should match modifier here}} + + @abi(func fn01()) + nonmutating func fn01() {} + + @abi(nonmutating func fn11()) + nonmutating func fn11() {} + + @abi(borrowing func fn21()) + nonmutating func fn21() {} + + @abi(consuming func fn31()) // expected-error {{modifier 'consuming' on self parameter in '@abi' is not compatible with default}} {{none}} + nonmutating func fn31() {} // expected-note {{should match modifier here}} + + @abi(__consuming func fn41()) // expected-error {{modifier '__consuming' on self parameter in '@abi' is not compatible with default}} {{none}} + nonmutating func fn41() {} // expected-note {{should match modifier here}} + + @abi(mutating func fn51()) // expected-error {{modifier 'mutating' on self parameter in '@abi' is not compatible with default}} {{none}} + nonmutating func fn51() {} // expected-note {{should match modifier here}} + + @abi(func fn02()) + borrowing func fn02() {} + + @abi(nonmutating func fn12()) + borrowing func fn12() {} + + @abi(borrowing func fn22()) + borrowing func fn22() {} + + @abi(consuming func fn32()) // expected-error {{modifier 'consuming' on self parameter in '@abi' is not compatible with 'borrowing'}} {{none}} + borrowing func fn32() {} // expected-note {{should match modifier here}} + + @abi(__consuming func fn42()) // expected-error {{modifier '__consuming' on self parameter in '@abi' is not compatible with 'borrowing'}} {{none}} + borrowing func fn42() {} // expected-note {{should match modifier here}} + + @abi(mutating func fn52()) // expected-error {{modifier 'mutating' on self parameter in '@abi' is not compatible with 'borrowing'}} {{none}} + borrowing func fn52() {} // expected-note {{should match modifier here}} + + @abi(func fn03()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with 'consuming'}} {{none}} + consuming func fn03() {} // expected-note {{should match modifier here}} + + @abi(nonmutating func fn13()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with 'consuming'}} {{none}} + consuming func fn13() {} // expected-note {{should match modifier here}} + + @abi(borrowing func fn23()) // expected-error {{modifier 'borrowing' on self parameter in '@abi' is not compatible with 'consuming'}} {{none}} + consuming func fn23() {} // expected-note {{should match modifier here}} + + @abi(consuming func fn33()) + consuming func fn33() {} + + @abi(__consuming func fn43()) + consuming func fn43() {} + + @abi(mutating func fn53()) // expected-error {{modifier 'mutating' on self parameter in '@abi' is not compatible with 'consuming'}} {{none}} + consuming func fn53() {} // expected-note {{should match modifier here}} + + @abi(func fn04()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with '__consuming'}} {{none}} + __consuming func fn04() {} // expected-note {{should match modifier here}} + + @abi(nonmutating func fn14()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with '__consuming'}} {{none}} + __consuming func fn14() {} // expected-note {{should match modifier here}} + + @abi(borrowing func fn24()) // expected-error {{modifier 'borrowing' on self parameter in '@abi' is not compatible with '__consuming'}} {{none}} + __consuming func fn24() {} // expected-note {{should match modifier here}} + + @abi(consuming func fn34()) + __consuming func fn34() {} + + @abi(__consuming func fn44()) + __consuming func fn44() {} + + @abi(mutating func fn54()) // expected-error {{modifier 'mutating' on self parameter in '@abi' is not compatible with '__consuming'}} {{none}} + __consuming func fn54() {} // expected-note {{should match modifier here}} + + @abi(func fn05()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with 'mutating'}} {{none}} + mutating func fn05() {} // expected-note {{should match modifier here}} + + @abi(nonmutating func fn15()) // expected-error {{default modifier on self parameter in '@abi' is not compatible with 'mutating'}} {{none}} + mutating func fn15() {} // expected-note {{should match modifier here}} + + @abi(borrowing func fn25()) // expected-error {{modifier 'borrowing' on self parameter in '@abi' is not compatible with 'mutating'}} {{none}} + mutating func fn25() {} // expected-note {{should match modifier here}} + + @abi(consuming func fn35()) // expected-error {{modifier 'consuming' on self parameter in '@abi' is not compatible with 'mutating'}} {{none}} + mutating func fn35() {} // expected-note {{should match modifier here}} + + @abi(__consuming func fn45()) // expected-error {{modifier '__consuming' on self parameter in '@abi' is not compatible with 'mutating'}} {{none}} + mutating func fn45() {} // expected-note {{should match modifier here}} + + @abi(mutating func fn55()) + mutating func fn55() {} +} + +// @_addressableSelf -- act like type attribute on `self` +struct AddressableSelf { + @abi(@_addressableSelf func fn1()) + @_addressableSelf func fn1() {} + + @abi(@_addressableSelf func fn2()) // expected-error {{attribute '_addressableSelf' on self parameter in '@abi' is not compatible with default}} {{none}} + func fn2() {} // expected-note {{should match attribute here}} + + @abi(func fn3()) // expected-error {{default attribute on self parameter in '@abi' is not compatible with '_addressableSelf'}} {{none}} + @_addressableSelf func fn3() {} // expected-note {{should match attribute here}} +} + // // Incorrect usage // diff --git a/test/attr/attr_abi_objc.swift b/test/attr/attr_abi_objc.swift new file mode 100644 index 0000000000000..581d1e5ab358a --- /dev/null +++ b/test/attr/attr_abi_objc.swift @@ -0,0 +1,156 @@ +// RUN: %target-typecheck-verify-swift -enable-experimental-feature ABIAttribute -parse-as-library -Rabi-inference + +// REQUIRES: swift_feature_ABIAttribute +// REQUIRES: objc_interop + +import Foundation + +// @NSCopying -- banned in @abi +class NSCopyingAttr: NSObject { + @abi(@NSCopying var v1: NSArray?) // expected-error {{unused 'NSCopying' attribute in '@abi'}} {{8-18=}} + @NSCopying var v1: NSArray? = nil + + @abi(var v2: NSArray?) + @NSCopying var v2: NSArray? = nil +} + +// Availability +// These tests will only work on a versioned platform. +@available(macOS 99, iOS 99, tvOS 99, watchOS 99, visionOS 99, *) +struct FutureType {} + +@abi(func available5(_: FutureType)) // expected-error {{'FutureType' is only available in }} +func available5(_: FutureType) {} // expected-error {{'FutureType' is only available in }} +// expected-note@-1 2{{add @available attribute to enclosing global function}} (fix-it not tested because it varies by target) + +@abi(func available6(_: FutureType)) +@available(macOS 99, iOS 99, tvOS 99, watchOS 99, visionOS 99, *) func available6(_: FutureType) {} + +// @objc -- banned in @abi +class ObjCAttr: NSObject { + @abi(@objc func fn1()) // expected-error {{unused 'objc' attribute in '@abi'}} {{8-13=}} + @objc func fn1() {} + + @abi(@objc func fn2()) // expected-error {{unused 'objc' attribute in '@abi'}} {{8-13=}} + func fn2() {} + + @abi(func fn3()) + @objc func fn3() {} +} + +// @IBAction -- banned in @abi +class IBActionAttr: NSObject { + @abi(@IBAction func fn1(_: Any)) // expected-error {{unused 'IBAction' attribute in '@abi'}} {{8-17=}} + @IBAction func fn1(_: Any) {} + + @abi(@IBAction func fn2(_: Any)) // expected-error {{unused 'IBAction' attribute in '@abi'}} {{8-17=}} + func fn2(_: Any) {} + + @abi(func fn3(_: Any)) + @IBAction func fn3(_: Any) {} +} + +// @IBInspectable -- banned in @abi +class IBInspectableAttr: NSObject { + @abi(@IBInspectable var v1: Double) // expected-error {{unused 'IBInspectable' attribute in '@abi'}} {{8-22=}} + @IBInspectable var v1: Double = 0.0 + + @abi(@IBInspectable var v2: Double) // expected-error {{unused 'IBInspectable' attribute in '@abi'}} {{8-22=}} + var v2: Double = 0.0 + + @abi(var v3: Double) + @IBInspectable var v3: Double = 0.0 +} + +// @GKInspectable -- banned in @abi +class GKInspectableAttr: NSObject { + @abi(@GKInspectable var v1: Double) // expected-error {{unused 'GKInspectable' attribute in '@abi'}} {{8-22=}} + @GKInspectable var v1: Double = 0.0 + + @abi(@GKInspectable var v2: Double) // expected-error {{unused 'GKInspectable' attribute in '@abi'}} {{8-22=}} + var v2: Double = 0.0 + + @abi(var v3: Double) + @GKInspectable var v3: Double = 0.0 +} + +// @IBOutlet -- banned in @abi +class IBOutletAttr: NSObject { + @abi(@IBOutlet var v1: NSObject!) // expected-error {{unused 'IBOutlet' attribute in '@abi'}} {{8-17=}} + @IBOutlet var v1: NSObject! + + @abi(@IBOutlet var v2: NSObject!) // expected-error {{unused 'IBOutlet' attribute in '@abi'}} {{8-17=}} + var v2: NSObject! + + @abi(var v3: NSObject!) + @IBOutlet var v3: NSObject! +} + +// @IBSegueAction -- banned in @abi +class IBSegueActionAttr: NSObject { + @abi(@IBSegueAction func fn1(_: Any) -> Any) // expected-error {{unused 'IBSegueAction' attribute in '@abi'}} {{8-22=}} + @IBSegueAction func fn1(_: Any) -> Any {} + + @abi(@IBSegueAction func fn2(_: Any) -> Any) // expected-error {{unused 'IBSegueAction' attribute in '@abi'}} {{8-22=}} + func fn2(_: Any) -> Any {} + + @abi(func fn3(_: Any) -> Any) + @IBSegueAction func fn3(_: Any) -> Any {} +} + +// @NSManaged -- banned in @abi +class NSManagedAttr: NSObject { + @abi(@NSManaged var v1: NSObject!) // expected-error {{unused 'NSManaged' attribute in '@abi'}} {{8-18=}} + @NSManaged var v1: NSObject! + + @abi(@NSManaged var v2: NSObject!) // expected-error {{unused 'NSManaged' attribute in '@abi'}} {{8-18=}} + var v2: NSObject! + + @abi(var v3: NSObject!) + @NSManaged var v3: NSObject! +} + +// @nonobjc -- banned in @abi +@objcMembers +class NonObjCAttr: NSObject { + @abi(@nonobjc var v1: NSObject!) // expected-error {{unused 'nonobjc' attribute in '@abi'}} {{8-16=}} + @nonobjc var v1: NSObject! + + @abi(@nonobjc var v2: NSObject!) // expected-error {{unused 'nonobjc' attribute in '@abi'}} {{8-16=}} + var v2: NSObject! + + @abi(var v3: NSObject!) + @nonobjc var v3: NSObject! +} + +// optional -- banned in @abi +@objc protocol OptionalModifier { + @abi( + @objc // expected-error {{unused 'objc' attribute in '@abi'}} {{5-11=}} + optional // expected-error {{unused 'optional' modifier in '@abi'}} {{5-14=}} + func fn1() + ) + @objc optional func fn1() + + @abi( + @objc // expected-error {{unused 'objc' attribute in '@abi'}} {{5-11=}} + optional // expected-error {{unused 'optional' modifier in '@abi'}} {{5-14=}} + func fn2() + ) + @objc func fn2() + + @abi(func fn3()) + @objc optional func fn3() +} + +// dynamic -- banned in @abi +class DynamicModifier: NSObject { + @abi(dynamic func fn1()) // expected-error {{unused 'dynamic' modifier in '@abi'}} {{8-15=}} + dynamic func fn1() {} + + @abi(dynamic func fn2()) // expected-error {{unused 'dynamic' modifier in '@abi'}} {{8-15=}} + func fn2() {} + + @abi(func fn3()) + dynamic func fn3() {} +} diff --git a/test/attr/attr_weaklinked.swift b/test/attr/attr_weaklinked.swift index 2de0a8eaddbb3..a56dbf4bf8ecb 100644 --- a/test/attr/attr_weaklinked.swift +++ b/test/attr/attr_weaklinked.swift @@ -1,6 +1,18 @@ -// RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -enable-experimental-feature ABIAttribute + +// UNSUPPORTED: OS=windows-msvc +// REQUIRES: swift_feature_ABIAttribute -#if !os(Windows) @_weakLinked public func f() { } -#endif +// @_weakLinked -- banned in @abi +struct WeakLinked { + @abi(@_weakLinked func fn1()) // expected-error {{unused '_weakLinked' attribute in '@abi'}} {{8-20=}} + @_weakLinked func fn1() {} + + @abi(@_weakLinked func fn2()) // expected-error {{unused '_weakLinked' attribute in '@abi'}} {{8-20=}} + func fn2() {} + + @abi(func fn3()) + @_weakLinked func fn3() {} +} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index cb0ff4f8f47c2..6a7e6067c7c51 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -1454,9 +1454,8 @@ class SwiftDocumentStructureWalker: public ide::SyntaxModelWalker { // We only report runtime name for classes and protocols with an explicitly // defined ObjC name, i.e. those that have @objc("SomeName") if (D && (isa(D) || isa(D))) { - auto *ObjCNameAttr = D->getAttrs().getAttribute(); - if (ObjCNameAttr && ObjCNameAttr->hasName()) - return ObjCNameAttr->getName()->getString(Buf); + if (auto objcName = D->getExplicitObjCName()) + return objcName->getString(Buf); } return StringRef(); }