mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #75413 from DougGregor/unsafe
Introduce `@unsafe` and the ability to prohibit use of unsafe entities
This commit is contained in:
@@ -357,7 +357,7 @@ protected:
|
||||
// for the inline bitfields.
|
||||
union { uint64_t OpaqueBits;
|
||||
|
||||
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1+1+1+1+1,
|
||||
SWIFT_INLINE_BITFIELD_BASE(Decl, bitmax(NumDeclKindBits,8)+1+1+1+1+1+1+1+1+1+1+1+1,
|
||||
Kind : bitmax(NumDeclKindBits,8),
|
||||
|
||||
/// Whether this declaration is invalid.
|
||||
@@ -372,10 +372,6 @@ protected:
|
||||
/// Use getClangNode() to retrieve the corresponding Clang AST.
|
||||
FromClang : 1,
|
||||
|
||||
/// Whether this declaration was added to the surrounding
|
||||
/// DeclContext of an active #if config clause.
|
||||
EscapedFromIfConfig : 1,
|
||||
|
||||
/// Whether this declaration is syntactically scoped inside of
|
||||
/// a local context, but should behave like a top-level
|
||||
/// declaration for name lookup purposes. This is used by
|
||||
@@ -404,7 +400,13 @@ protected:
|
||||
|
||||
/// True if we're in the common case where the SPIGroupsRequest
|
||||
/// request returned an empty array of identifiers.
|
||||
NoSPIGroups : 1
|
||||
NoSPIGroups : 1,
|
||||
|
||||
/// True if we have computed whether this declaration is unsafe.
|
||||
IsUnsafeComputed : 1,
|
||||
|
||||
/// True if this declaration has been determined to be "unsafe".
|
||||
IsUnsafe : 1
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD_FULL(PatternBindingDecl, Decl, 1+1+2+16,
|
||||
@@ -857,6 +859,7 @@ protected:
|
||||
friend class ExpandPeerMacroRequest;
|
||||
friend class GlobalActorAttributeRequest;
|
||||
friend class SPIGroupsRequest;
|
||||
friend class IsUnsafeRequest;
|
||||
|
||||
private:
|
||||
llvm::PointerUnion<DeclContext *, ASTContext *> Context;
|
||||
@@ -916,12 +919,13 @@ protected:
|
||||
Bits.Decl.Invalid = false;
|
||||
Bits.Decl.Implicit = false;
|
||||
Bits.Decl.FromClang = false;
|
||||
Bits.Decl.EscapedFromIfConfig = false;
|
||||
Bits.Decl.Hoisted = false;
|
||||
Bits.Decl.LacksObjCInterfaceOrImplementation = false;
|
||||
Bits.Decl.NoMemberAttributeMacros = false;
|
||||
Bits.Decl.NoGlobalActorAttribute = false;
|
||||
Bits.Decl.NoSPIGroups = false;
|
||||
Bits.Decl.IsUnsafeComputed = false;
|
||||
Bits.Decl.IsUnsafe = false;
|
||||
}
|
||||
|
||||
/// Get the Clang node associated with this declaration.
|
||||
@@ -1180,15 +1184,26 @@ public:
|
||||
/// Whether this declaration predates the introduction of concurrency.
|
||||
bool preconcurrency() const;
|
||||
|
||||
/// Whether this declaration is considered "unsafe", i.e., should not be
|
||||
/// used in a "safe" dialect.
|
||||
bool isUnsafe() const;
|
||||
|
||||
private:
|
||||
bool isUnsafeComputed() const {
|
||||
return Bits.Decl.IsUnsafeComputed;
|
||||
}
|
||||
|
||||
bool isUnsafeRaw() const {
|
||||
return Bits.Decl.IsUnsafe;
|
||||
}
|
||||
|
||||
void setUnsafe(bool value) {
|
||||
assert(!Bits.Decl.IsUnsafeComputed);
|
||||
Bits.Decl.IsUnsafe = value;
|
||||
Bits.Decl.IsUnsafeComputed = true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool escapedFromIfConfig() const {
|
||||
return Bits.Decl.EscapedFromIfConfig;
|
||||
}
|
||||
|
||||
void setEscapedFromIfConfig(bool Escaped) {
|
||||
Bits.Decl.EscapedFromIfConfig = Escaped;
|
||||
}
|
||||
|
||||
bool getSemanticAttrsComputed() const {
|
||||
return Bits.Decl.SemanticAttrsComputed;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,13 @@ SIMPLE_DECL_ATTR(sensitive, Sensitive,
|
||||
OnStruct | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
|
||||
159)
|
||||
|
||||
LAST_DECL_ATTR(PreInverseGenerics)
|
||||
SIMPLE_DECL_ATTR(unsafe, Unsafe,
|
||||
OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType |
|
||||
UserInaccessible |
|
||||
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
|
||||
160)
|
||||
|
||||
LAST_DECL_ATTR(Unsafe)
|
||||
|
||||
#undef DECL_ATTR_ALIAS
|
||||
#undef CONTEXTUAL_DECL_ATTR_ALIAS
|
||||
|
||||
@@ -7964,5 +7964,33 @@ NOTE(sending_function_result_with_sending_param_note, none,
|
||||
"isolation domain through a result of an invocation of value",
|
||||
())
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: Strict Safety Diagnostics
|
||||
//------------------------------------------------------------------------------
|
||||
ERROR(unsafe_attr_disabled,none,
|
||||
"attribute requires '-enable-experimental-feature AllowUnsafeAttribute'", ())
|
||||
WARNING(override_safe_withunsafe,none,
|
||||
"override of safe %0 with unsafe %0", (DescriptiveDeclKind))
|
||||
WARNING(witness_unsafe,none,
|
||||
"unsafe %0 %1 cannot satisfy safe requirement",
|
||||
(DescriptiveDeclKind, DeclName))
|
||||
WARNING(type_witness_unsafe,none,
|
||||
"unsafe type %0 cannot satisfy safe associated type %1",
|
||||
(Type, DeclName))
|
||||
WARNING(unchecked_conformance_is_unsafe,none,
|
||||
"@unchecked conformance involves unsafe code", ())
|
||||
WARNING(unowned_unsafe_is_unsafe,none,
|
||||
"unowned(unsafe) involves unsafe code", ())
|
||||
WARNING(nonisolated_unsafe_is_unsafe,none,
|
||||
"nonisolated(unsafe) involves unsafe code", ())
|
||||
WARNING(reference_to_unsafe_decl,none,
|
||||
"%select{reference|call}0 to unsafe %kindbase1",
|
||||
(bool, const ValueDecl *))
|
||||
WARNING(reference_to_unsafe_typed_decl,none,
|
||||
"%select{reference|call}0 to %kindbase1 involves unsafe type %2",
|
||||
(bool, const ValueDecl *, Type))
|
||||
NOTE(unsafe_decl_here,none,
|
||||
"unsafe %kindbase0 declared here", (const ValueDecl *))
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_MACROS
|
||||
#include "DefineDiagnosticMacros.h"
|
||||
|
||||
@@ -5065,6 +5065,24 @@ public:
|
||||
bool isCached() const { return true; }
|
||||
};
|
||||
|
||||
class IsUnsafeRequest
|
||||
: public SimpleRequest<IsUnsafeRequest,
|
||||
bool(Decl *decl),
|
||||
RequestFlags::SeparatelyCached> {
|
||||
public:
|
||||
using SimpleRequest::SimpleRequest;
|
||||
|
||||
private:
|
||||
friend SimpleRequest;
|
||||
|
||||
bool evaluate(Evaluator &evaluator, Decl *decl) const;
|
||||
|
||||
public:
|
||||
bool isCached() const { return true; }
|
||||
std::optional<bool> getCachedResult() const;
|
||||
void cacheResult(bool value) const;
|
||||
};
|
||||
|
||||
#define SWIFT_TYPEID_ZONE TypeChecker
|
||||
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
|
||||
#include "swift/Basic/DefineTypeIDZone.h"
|
||||
|
||||
@@ -593,3 +593,6 @@ SWIFT_REQUEST(TypeChecker, CaptureInfoRequest,
|
||||
SWIFT_REQUEST(TypeChecker, ParamCaptureInfoRequest,
|
||||
CaptureInfo(ParamDecl *),
|
||||
SeparatelyCached, NoLocationInfo)
|
||||
SWIFT_REQUEST(TypeChecker, IsUnsafeRequest,
|
||||
bool(Decl *),
|
||||
SeparatelyCached, NoLocationInfo)
|
||||
|
||||
@@ -185,7 +185,10 @@ public:
|
||||
/// Contains a PackArchetypeType. Also implies HasPrimaryArchetype.
|
||||
HasPackArchetype = 0x20000,
|
||||
|
||||
Last_Property = HasPackArchetype
|
||||
/// Whether this type contains an unsafe type.
|
||||
IsUnsafe = 0x040000,
|
||||
|
||||
Last_Property = IsUnsafe
|
||||
};
|
||||
enum { BitWidth = countBitsUsed(Property::Last_Property) };
|
||||
|
||||
@@ -266,6 +269,8 @@ public:
|
||||
|
||||
bool hasPackArchetype() const { return Bits & HasPackArchetype; }
|
||||
|
||||
bool isUnsafe() const { return Bits & IsUnsafe; }
|
||||
|
||||
/// Does a type with these properties structurally contain a
|
||||
/// parameterized existential type?
|
||||
bool hasParameterizedExistential() const {
|
||||
@@ -431,12 +436,12 @@ protected:
|
||||
NumProtocols : 16
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+29,
|
||||
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+28,
|
||||
/// Type variable options.
|
||||
Options : 7,
|
||||
: NumPadBits,
|
||||
/// The unique number assigned to this type variable.
|
||||
ID : 29
|
||||
ID : 28
|
||||
);
|
||||
|
||||
SWIFT_INLINE_BITFIELD_FULL(ErrorUnionType, TypeBase, 32,
|
||||
@@ -709,6 +714,11 @@ public:
|
||||
return getRecursiveProperties().hasPackArchetype();
|
||||
}
|
||||
|
||||
/// Whether the type contains an @unsafe type in it anywhere.
|
||||
bool isUnsafe() const {
|
||||
return getRecursiveProperties().isUnsafe();
|
||||
}
|
||||
|
||||
/// Determine whether the type involves a primary, pack or local archetype.
|
||||
///
|
||||
/// FIXME: Replace all remaining callers with a more precise check.
|
||||
@@ -6637,7 +6647,8 @@ private:
|
||||
GenericEnvironment *GenericEnv,
|
||||
Type InterfaceType,
|
||||
ArrayRef<ProtocolDecl *> ConformsTo,
|
||||
Type Superclass, LayoutConstraint Layout);
|
||||
Type Superclass, LayoutConstraint Layout,
|
||||
RecursiveTypeProperties Properties);
|
||||
};
|
||||
BEGIN_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
|
||||
END_CAN_TYPE_WRAPPER(PrimaryArchetypeType, ArchetypeType)
|
||||
@@ -6918,7 +6929,8 @@ public:
|
||||
private:
|
||||
PackArchetypeType(const ASTContext &Ctx, GenericEnvironment *GenericEnv,
|
||||
Type InterfaceType, ArrayRef<ProtocolDecl *> ConformsTo,
|
||||
Type Superclass, LayoutConstraint Layout, PackShape Shape);
|
||||
Type Superclass, LayoutConstraint Layout, PackShape Shape,
|
||||
RecursiveTypeProperties properties);
|
||||
};
|
||||
BEGIN_CAN_TYPE_WRAPPER(PackArchetypeType, ArchetypeType)
|
||||
END_CAN_TYPE_WRAPPER(PackArchetypeType, ArchetypeType)
|
||||
|
||||
Reference in New Issue
Block a user