Merge pull request #78332 from DougGregor/strict-safety-improvements

Strict safety improvements
This commit is contained in:
Doug Gregor
2025-01-02 08:25:02 -08:00
committed by GitHub
59 changed files with 879 additions and 306 deletions

View File

@@ -22,6 +22,7 @@
#include "swift/AST/Evaluator.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/Import.h"
#include "swift/AST/ProtocolConformanceOptions.h"
#include "swift/AST/SILOptions.h"
#include "swift/AST/SearchPathOptions.h"
#include "swift/AST/Type.h"
@@ -1299,8 +1300,7 @@ public:
SourceLoc loc,
DeclContext *dc,
ProtocolConformanceState state,
bool isUnchecked,
bool isPreconcurrency,
ProtocolConformanceOptions options,
SourceLoc preconcurrencyLoc = SourceLoc());
/// Produce a self-conformance for the given protocol.

View File

@@ -34,6 +34,7 @@
#include "swift/AST/Initializer.h"
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/LifetimeAnnotation.h"
#include "swift/AST/ProtocolConformanceOptions.h"
#include "swift/AST/ReferenceCounting.h"
#include "swift/AST/RequirementSignature.h"
#include "swift/AST/StorageImpl.h"
@@ -725,7 +726,7 @@ protected:
HasAnyUnavailableDuringLoweringValues : 1
);
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+8,
/// If the module is compiled as static library.
StaticLibrary : 1,
@@ -791,7 +792,10 @@ protected:
AllowNonResilientAccess : 1,
/// Whether this module has been built with -package-cmo.
SerializePackageEnabled : 1
SerializePackageEnabled : 1,
/// Whether this module has enabled strict memory safety checking.
StrictMemorySafety : 1
);
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,
@@ -1782,14 +1786,8 @@ public:
/// An entry in the "inherited" list of a type or extension.
struct InheritedEntry : public TypeLoc {
private:
/// Whether there was an @unchecked attribute.
bool IsUnchecked : 1;
/// Whether there was an @retroactive attribute.
bool IsRetroactive : 1;
/// Whether there was an @preconcurrency attribute.
bool IsPreconcurrency : 1;
/// Options on a protocol conformance that are expressed as attributes.
unsigned RawOptions: 8;
/// Whether there was a ~ indicating suppression.
///
@@ -1799,17 +1797,38 @@ private:
public:
InheritedEntry(const TypeLoc &typeLoc);
InheritedEntry(const TypeLoc &typeLoc, bool isUnchecked, bool isRetroactive,
bool isPreconcurrency, bool isSuppressed = false)
: TypeLoc(typeLoc), IsUnchecked(isUnchecked),
IsRetroactive(isRetroactive), IsPreconcurrency(isPreconcurrency),
InheritedEntry(const TypeLoc &typeLoc, ProtocolConformanceOptions options,
bool isSuppressed = false)
: TypeLoc(typeLoc), RawOptions(options.toRaw()),
IsSuppressed(isSuppressed) {}
bool isUnchecked() const { return IsUnchecked; }
bool isRetroactive() const { return IsRetroactive; }
bool isPreconcurrency() const { return IsPreconcurrency; }
ProtocolConformanceOptions getOptions() const {
return ProtocolConformanceOptions(RawOptions);
}
bool isUnchecked() const {
return getOptions().contains(ProtocolConformanceFlags::Unchecked);
}
bool isRetroactive() const {
return getOptions().contains(ProtocolConformanceFlags::Retroactive);
}
bool isPreconcurrency() const {
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
}
bool isUnsafe() const {
return getOptions().contains(ProtocolConformanceFlags::Unsafe);
}
bool isSafe() const {
return getOptions().contains(ProtocolConformanceFlags::Safe);
}
bool isSuppressed() const { return IsSuppressed; }
void setOption(ProtocolConformanceFlags flag) {
RawOptions = (getOptions() | flag).toRaw();
}
void setSuppressed() {
assert(!IsSuppressed && "setting suppressed again!?");
IsSuppressed = true;

View File

@@ -529,7 +529,7 @@ SIMPLE_DECL_ATTR(_addressableSelf, AddressableSelf,
DECL_ATTR(safe, Safe,
OnAbstractFunction | OnSubscript | OnVar | OnMacro | OnNominalType |
OnExtension | OnTypeAlias | UserInaccessible |
OnExtension | OnTypeAlias | OnImport | UserInaccessible |
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
163)

View File

@@ -589,5 +589,9 @@ ERROR(experimental_not_supported_in_production,none,
"experimental feature '%0' cannot be enabled in production compiler",
(StringRef))
GROUPED_WARNING(Ounchecked_with_strict_safety,Unsafe,none,
"'-Ounchecked' is not memory-safe and should not be combined with "
"strict memory safety checking", ())
#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"

View File

@@ -5792,22 +5792,19 @@ ERROR(non_sendable_type,none,
ERROR(sendable_raw_storage,none,
"struct %0 with @_rawLayout does not conform to the 'Sendable' protocol", (DeclName))
ERROR(typeattr_not_inheritance_clause,none,
"'%0' attribute only applies in inheritance clauses", (StringRef))
ERROR(typeattr_not_existential,none,
"'%0' attribute cannot apply to non-protocol type %1", (StringRef, Type))
WARNING(unchecked_conformance_not_special,none,
"@unchecked conformance to %0 has no meaning", (Type))
WARNING(restate_unchecked_sendable,none,
"class %0 must restate inherited '@unchecked Sendable' conformance",
(DeclName))
ERROR(unchecked_not_inheritance_clause,none,
"'unchecked' attribute only applies in inheritance clauses", ())
ERROR(unchecked_not_existential,none,
"'unchecked' attribute cannot apply to non-protocol type %0", (Type))
WARNING(preconcurrency_conformance_not_used,none,
"@preconcurrency attribute on conformance to %0 has no effect", (Type))
ERROR(preconcurrency_not_inheritance_clause,none,
"'preconcurrency' attribute only applies in inheritance clauses", ())
ERROR(preconcurrency_not_existential,none,
"'preconcurrency' attribute cannot apply to non-protocol type %0", (Type))
ERROR(redundant_any_in_existential,none,
"redundant 'any' in type %0",
@@ -8084,22 +8081,33 @@ NOTE(note_reference_to_unsafe_decl,none,
NOTE(note_reference_to_unsafe_typed_decl,none,
"%select{reference|call}0 to %kind1 involves unsafe type %2",
(bool, const ValueDecl *, Type))
NOTE(note_reference_to_unsafe_through_typealias,none,
"reference to %kind0 whose underlying type involves unsafe type %1",
(const ValueDecl *, Type))
NOTE(note_reference_to_nonisolated_unsafe,none,
"reference to nonisolated(unsafe) %kind0 is unsafe in concurrently-executing code",
(const ValueDecl *))
NOTE(note_reference_unowned_unsafe,none,
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
NOTE(note_use_of_unsafe_conformance_is_unsafe,none,
"@unsafe conformance of %0 to %kind1 involves unsafe code",
(Type, const ValueDecl *))
GROUPED_WARNING(conformance_involves_unsafe,Unsafe,none,
"conformance of %0 to %kind1 involves unsafe code; use '@unsafe' to "
"indicate that the conformance is not memory-safe",
(Type, const ValueDecl *))
NOTE(note_witness_unsafe,none,
"unsafe %0 %1 cannot satisfy safe requirement",
(DescriptiveDeclKind, DeclName))
NOTE(note_type_witness_unsafe,none,
"unsafe type %0 cannot satisfy safe associated type %1",
(Type, DeclName))
GROUPED_WARNING(override_safe_withunsafe,Unsafe,none,
"override of safe %0 with unsafe %0", (DescriptiveDeclKind))
GROUPED_WARNING(witness_unsafe,Unsafe,none,
"unsafe %0 %1 cannot satisfy safe requirement",
(DescriptiveDeclKind, DeclName))
GROUPED_WARNING(type_witness_unsafe,Unsafe,none,
"unsafe type %0 cannot satisfy safe associated type %1",
(Type, DeclName))
GROUPED_WARNING(unchecked_conformance_is_unsafe,Unsafe,none,
"@unchecked conformance involves unsafe code", ())
GROUPED_WARNING(use_of_unsafe_conformance_is_unsafe,Unsafe,none,
"@unsafe conformance of %0 to %kind1 involves unsafe code",
(Type, const ValueDecl *))
GROUPED_WARNING(reference_unowned_unsafe,Unsafe,none,
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
GROUPED_WARNING(reference_to_nonisolated_unsafe,Unsafe,none,
@@ -8111,8 +8119,13 @@ GROUPED_WARNING(reference_to_unsafe_decl,Unsafe,none,
GROUPED_WARNING(reference_to_unsafe_typed_decl,Unsafe,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 *))
GROUPED_WARNING(reference_to_unsafe_through_typealias,Unsafe,none,
"reference to %kind0 whose underlying type involves unsafe type %1",
(const ValueDecl *, Type))
GROUPED_WARNING(preconcurrency_import_unsafe,Unsafe,none,
"@preconcurrency import is not memory-safe because it can silently "
"introduce data races; use '@safe(unchecked)' to assert that the "
"code is memory-safe", ())
NOTE(encapsulate_unsafe_in_enclosing_context,none,
"make %kindbase0 @safe(unchecked) to allow it to use unsafe constructs in its definition",
(const Decl *))

View File

@@ -830,6 +830,15 @@ public:
Bits.ModuleDecl.IsConcurrencyChecked = value;
}
/// Whether this module has enable strict memory safety checking.
bool strictMemorySafety() const {
return Bits.ModuleDecl.StrictMemorySafety;
}
void setStrictMemorySafety(bool value = true) {
Bits.ModuleDecl.StrictMemorySafety = value;
}
bool isObjCNameLookupCachePopulated() const {
return Bits.ModuleDecl.ObjCNameLookupCachePopulated;
}

View File

@@ -609,6 +609,12 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
/// The location of the "preconcurrency" attribute if present.
SourceLoc preconcurrencyLoc;
/// The location of the "unsafe" attribute if present.
SourceLoc unsafeLoc;
/// The range of the "safe(unchecked)" attribute if present.
SourceRange safeRange;
/// Whether this inherited entry was suppressed via "~".
bool isSuppressed;
@@ -616,9 +622,11 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
InheritedNominalEntry(NominalTypeDecl *item, SourceLoc loc,
SourceLoc uncheckedLoc, SourceLoc preconcurrencyLoc,
SourceLoc unsafeLoc, SourceRange safeRange,
bool isSuppressed)
: Located(item, loc), uncheckedLoc(uncheckedLoc),
preconcurrencyLoc(preconcurrencyLoc), isSuppressed(isSuppressed) {}
preconcurrencyLoc(preconcurrencyLoc), unsafeLoc(unsafeLoc),
safeRange(safeRange), isSuppressed(isSuppressed) {}
};
/// Retrieve the set of nominal type declarations that are directly

View File

@@ -18,6 +18,7 @@
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/Decl.h"
#include "swift/AST/ProtocolConformanceOptions.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeAlignments.h"
@@ -146,20 +147,21 @@ protected:
SWIFT_INLINE_BITFIELD_EMPTY(RootProtocolConformance, ProtocolConformance);
SWIFT_INLINE_BITFIELD_FULL(NormalProtocolConformance, RootProtocolConformance,
1+1+1+1+bitmax(NumProtocolConformanceStateBits,8)+
1+1+
bitmax(NumProtocolConformanceOptions,8)+
bitmax(NumProtocolConformanceStateBits,8)+
bitmax(NumConformanceEntryKindBits,8),
/// Indicates whether the conformance is invalid.
IsInvalid : 1,
/// The conformance was labeled with @unchecked.
IsUnchecked : 1,
/// The conformance was labeled with @preconcurrency.
IsPreconcurrency : 1,
/// We have allocated the AssociatedConformances array (but not necessarily
/// populated any of its elements).
HasComputedAssociatedConformances : 1,
: NumPadBits,
/// Options.
Options : bitmax(NumProtocolConformanceOptions, 8),
/// The current state of the conformance.
State : bitmax(NumProtocolConformanceStateBits, 8),
/// The reason that this conformance exists.
@@ -567,8 +569,8 @@ class NormalProtocolConformance : public RootProtocolConformance,
public:
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
SourceLoc loc, DeclContext *dc,
ProtocolConformanceState state, bool isUnchecked,
bool isPreconcurrency,
ProtocolConformanceState state,
ProtocolConformanceOptions options,
SourceLoc preconcurrencyLoc)
: RootProtocolConformance(ProtocolConformanceKind::Normal,
conformingType),
@@ -577,12 +579,12 @@ public:
Context(dc) {
assert(!conformingType->hasArchetype() &&
"ProtocolConformances should store interface types");
assert((preconcurrencyLoc.isInvalid() || isPreconcurrency) &&
assert((preconcurrencyLoc.isInvalid() ||
options.contains(ProtocolConformanceFlags::Preconcurrency)) &&
"Cannot have a @preconcurrency location without isPreconcurrency");
setState(state);
Bits.NormalProtocolConformance.IsInvalid = false;
Bits.NormalProtocolConformance.IsUnchecked = isUnchecked;
Bits.NormalProtocolConformance.IsPreconcurrency = isPreconcurrency;
Bits.NormalProtocolConformance.Options = options.toRaw();
Bits.NormalProtocolConformance.HasComputedAssociatedConformances = false;
Bits.NormalProtocolConformance.SourceKind =
unsigned(ConformanceEntryKind::Explicit);
@@ -626,27 +628,42 @@ public:
/// Mark this conformance as invalid.
void setInvalid() { Bits.NormalProtocolConformance.IsInvalid = true; }
ProtocolConformanceOptions getOptions() const {
return ProtocolConformanceOptions(Bits.NormalProtocolConformance.Options);
}
/// Whether this is an "unchecked" conformance.
bool isUnchecked() const {
return Bits.NormalProtocolConformance.IsUnchecked;
return getOptions().contains(ProtocolConformanceFlags::Unchecked);
}
/// Mark the conformance as unchecked (equivalent to the @unchecked
/// conformance attribute).
void setUnchecked() {
// OK to mutate because the flags are not part of the folding set node ID.
Bits.NormalProtocolConformance.IsUnchecked = true;
Bits.NormalProtocolConformance.Options =
(getOptions() | ProtocolConformanceFlags::Unchecked).toRaw();
}
/// Whether this is an preconcurrency conformance.
bool isPreconcurrency() const {
return Bits.NormalProtocolConformance.IsPreconcurrency;
return getOptions().contains(ProtocolConformanceFlags::Preconcurrency);
}
/// Retrieve the location of `@preconcurrency`, if there is one and it is
/// known.
SourceLoc getPreconcurrencyLoc() const { return PreconcurrencyLoc; }
/// Whether this is an "unsafe" conformance.
bool isUnsafe() const {
return getOptions().contains(ProtocolConformanceFlags::Unsafe);
}
/// Whether this is an "safe(unchecked)" conformance.
bool isSafe() const {
return getOptions().contains(ProtocolConformanceFlags::Safe);
}
/// Determine whether we've lazily computed the associated conformance array
/// already.
bool hasComputedAssociatedConformances() const {
@@ -684,8 +701,8 @@ public:
if (auto implying = implyingConformance) {
ImplyingConformance = implying;
PreconcurrencyLoc = implying->getPreconcurrencyLoc();
Bits.NormalProtocolConformance.IsPreconcurrency =
implying->isPreconcurrency();
Bits.NormalProtocolConformance.Options =
implyingConformance->getOptions().toRaw();
}
}

View File

@@ -0,0 +1,60 @@
//===--- ProtocolConformanceOptions.h - Conformance Options -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the options for protocol conformances.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_PROTOCOLCONFORMANCEOPTIONS_H
#define SWIFT_AST_PROTOCOLCONFORMANCEOPTIONS_H
#include "swift/Basic/OptionSet.h"
namespace swift {
/// Flags that describe extra attributes on protocol conformances.
enum class ProtocolConformanceFlags {
/// @unchecked conformance
Unchecked = 0x01,
/// @preconcurrency conformance
Preconcurrency = 0x02,
/// @unsafe conformance
Unsafe = 0x04,
/// @safe(unchecked) conformance
Safe = 0x08,
/// @retroactive conformance
Retroactive = 0x10,
// Note: whenever you add a bit here, update
// NumProtocolConformanceOptions below.
};
/// Options that describe extra attributes on protocol conformances.
using ProtocolConformanceOptions =
OptionSet<ProtocolConformanceFlags>;
inline ProtocolConformanceOptions operator|(
ProtocolConformanceFlags flag1,
ProtocolConformanceFlags flag2) {
return ProtocolConformanceOptions(flag1) | flag2;
}
enum : unsigned {
NumProtocolConformanceOptions = 5
};
} // end namespace swift
#endif

View File

@@ -60,6 +60,8 @@ SIMPLE_TYPE_ATTR(Sendable, Sendable)
SIMPLE_TYPE_ATTR(retroactive, Retroactive)
SIMPLE_TYPE_ATTR(unchecked, Unchecked)
SIMPLE_TYPE_ATTR(preconcurrency, Preconcurrency)
SIMPLE_TYPE_ATTR(unsafe, Unsafe)
SIMPLE_TYPE_ATTR(safe, Safe)
SIMPLE_TYPE_ATTR(_local, Local)
SIMPLE_TYPE_ATTR(_noMetadata, NoMetadata)
TYPE_ATTR(_opaqueReturnTypeOf, OpaqueReturnTypeOf)

View File

@@ -15,14 +15,13 @@
#include "swift/AST/Decl.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/Type.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Basic/Unreachable.h"
namespace swift {
class NormalProtocolConformance;
/// Describes a use of an unsafe construct.
///
/// Every use of an unsafe construct that should be diagnosed will be captured
@@ -44,8 +43,13 @@ public:
NonisolatedUnsafe,
/// A reference to an unsafe declaration.
ReferenceToUnsafe,
/// A reference to a typealias that is not itself unsafe, but has
/// an unsafe underlying type.
ReferenceToUnsafeThroughTypealias,
/// A call to an unsafe declaration.
CallToUnsafe,
/// A @preconcurrency import.
PreconcurrencyImport,
};
private:
@@ -66,7 +70,8 @@ private:
} typeWitness;
struct {
NormalProtocolConformance *conformance;
TypeBase *type;
void *conformanceRef;
DeclContext *declContext;
const void *location;
} conformance;
@@ -77,6 +82,8 @@ private:
TypeBase *type;
const void *location;
} entity;
const ImportDecl *importDecl;
} storage;
UnsafeUse(Kind kind) : kind(kind) { }
@@ -106,6 +113,7 @@ private:
assert(kind == UnownedUnsafe ||
kind == NonisolatedUnsafe ||
kind == ReferenceToUnsafe ||
kind == ReferenceToUnsafeThroughTypealias ||
kind == CallToUnsafe);
UnsafeUse result(kind);
@@ -139,11 +147,14 @@ public:
return result;
}
static UnsafeUse forConformance(NormalProtocolConformance *conformance,
static UnsafeUse forConformance(Type subjectType,
ProtocolConformanceRef conformance,
SourceLoc location,
DeclContext *dc) {
assert(subjectType);
UnsafeUse result(UnsafeConformance);
result.storage.conformance.conformance = conformance;
result.storage.conformance.type = subjectType.getPointer();
result.storage.conformance.conformanceRef = conformance.getOpaqueValue();
result.storage.conformance.declContext = dc;
result.storage.conformance.location = location.getOpaquePointerValue();
return result;
@@ -170,6 +181,20 @@ public:
decl, type, location);
}
static UnsafeUse forReferenceToUnsafeThroughTypealias(const Decl *decl,
DeclContext *dc,
Type type,
SourceLoc location) {
return forReference(ReferenceToUnsafeThroughTypealias, dc,
decl, type, location);
}
static UnsafeUse forPreconcurrencyImport(const ImportDecl *importDecl) {
UnsafeUse result(PreconcurrencyImport);
result.storage.importDecl = importDecl;
return result;
}
Kind getKind() const { return kind; }
/// The location at which this use will be diagnosed.
@@ -180,7 +205,9 @@ public:
return getDecl()->getLoc();
case UnsafeConformance:
return getConformance()->getLoc();
return SourceLoc(
llvm::SMLoc::getFromPointer(
(const char *)storage.conformance.location));
case TypeWitness:
return SourceLoc(
@@ -190,9 +217,13 @@ public:
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
return SourceLoc(
llvm::SMLoc::getFromPointer((const char *)storage.entity.location));
case PreconcurrencyImport:
return storage.importDecl->getLoc();
}
}
@@ -209,11 +240,15 @@ public:
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
return storage.entity.decl;
case UnsafeConformance:
return nullptr;
case PreconcurrencyImport:
return storage.importDecl;
}
}
@@ -229,6 +264,7 @@ public:
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
return storage.entity.declContext;
@@ -237,10 +273,13 @@ public:
case Witness:
case TypeWitness:
return getConformance()->getDeclContext();
return getConformance().getConcrete()->getDeclContext();
case UnsafeConformance:
return storage.conformance.declContext;
case PreconcurrencyImport:
return storage.importDecl->getDeclContext();
}
}
@@ -257,8 +296,10 @@ public:
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
case UnsafeConformance:
case PreconcurrencyImport:
return nullptr;
}
}
@@ -268,38 +309,45 @@ public:
switch (getKind()) {
case Override:
case Witness:
case UnsafeConformance:
case PreconcurrencyImport:
return nullptr;
case UnsafeConformance:
return storage.conformance.type;
case TypeWitness:
return storage.typeWitness.type;
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
return storage.entity.type;
}
}
/// Get the protocol conformance, if there is one.
NormalProtocolConformance *getConformance() const {
ProtocolConformanceRef getConformance() const {
switch (getKind()) {
case UnsafeConformance:
return storage.conformance.conformance;
return ProtocolConformanceRef::getFromOpaqueValue(
storage.conformance.conformanceRef);
case Witness:
return storage.polymorphic.conformance;
return ProtocolConformanceRef(storage.polymorphic.conformance);
case TypeWitness:
return storage.typeWitness.conformance;
return ProtocolConformanceRef(storage.typeWitness.conformance);
case Override:
case UnownedUnsafe:
case NonisolatedUnsafe:
case ReferenceToUnsafe:
case ReferenceToUnsafeThroughTypealias:
case CallToUnsafe:
return nullptr;
case PreconcurrencyImport:
return ProtocolConformanceRef::forInvalid();
}
}
};

View File

@@ -149,6 +149,7 @@ class ExtendedValidationInfo {
unsigned HasCxxInteroperability : 1;
unsigned AllowNonResilientAccess: 1;
unsigned SerializePackageEnabled: 1;
unsigned StrictMemorySafety: 1;
} Bits;
public:
ExtendedValidationInfo() : Bits() {}
@@ -246,6 +247,13 @@ public:
void setIsConcurrencyChecked(bool val = true) {
Bits.IsConcurrencyChecked = val;
}
bool strictMemorySafety() const {
return Bits.StrictMemorySafety;
}
void setStrictMemorySafety(bool val = true) {
Bits.StrictMemorySafety = val;
}
bool hasCxxInteroperability() const { return Bits.HasCxxInteroperability; }
void setHasCxxInteroperability(bool val) {
Bits.HasCxxInteroperability = val;