Skip to content

Commit b8cd7ef

Browse files
authored
Merge pull request #70866 from kavon/ncgenerics-stdlib-building-v4
Build Stdlib with Noncopyable Generics (Part 4)
2 parents 68e852e + 970c45e commit b8cd7ef

File tree

84 files changed

+801
-278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+801
-278
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,10 @@ option(SWIFT_ENABLE_EXPERIMENTAL_DISTRIBUTED
639639
"Enable experimental distributed actors and functions"
640640
FALSE)
641641

642+
option(SWIFT_ENABLE_EXPERIMENTAL_NONCOPYABLE_GENERICS
643+
"Enable experimental NoncopyableGenerics"
644+
FALSE)
645+
642646
option(SWIFT_ENABLE_EXPERIMENTAL_STRING_PROCESSING
643647
"Enable experimental string processing"
644648
FALSE)
@@ -1230,6 +1234,7 @@ if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
12301234
message(STATUS "Differentiable Programming Support: ${SWIFT_ENABLE_EXPERIMENTAL_DIFFERENTIABLE_PROGRAMMING}")
12311235
message(STATUS "Concurrency Support: ${SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY}")
12321236
message(STATUS "Distributed Support: ${SWIFT_ENABLE_EXPERIMENTAL_DISTRIBUTED}")
1237+
message(STATUS "NoncopyableGenerics Support: ${SWIFT_ENABLE_EXPERIMENTAL_NONCOPYABLE_GENERICS}")
12331238
message(STATUS "String Processing Support: ${SWIFT_ENABLE_EXPERIMENTAL_STRING_PROCESSING}")
12341239
message(STATUS "Backtracing Support: ${SWIFT_ENABLE_BACKTRACING}")
12351240
message(STATUS "Unicode Support: ${SWIFT_STDLIB_ENABLE_UNICODE_DATA}")

include/swift/AST/Decl.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,13 +3191,35 @@ class TypeDecl : public ValueDecl {
31913191

31923192
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
31933193

3194-
/// Is it possible for this type to lack a Copyable constraint?
3194+
struct CanBeInvertible {
3195+
/// Indicates how "strongly" a TypeDecl will conform to an invertible
3196+
/// protocol. Supports inequality comparisons and casts to bool.
3197+
enum Result : unsigned {
3198+
Never = 0, // Never conforms.
3199+
Conditionally = 1, // Conditionally conforms.
3200+
Always = 2, // Always conforms.
3201+
};
3202+
};
3203+
3204+
/// "Does a conformance for Copyable exist for this type declaration?"
3205+
///
3206+
/// This doesn't mean that all instance of this type are Copyable, because
3207+
/// if a conditional conformance to Copyable exists, this method will return
3208+
/// true.
3209+
///
31953210
/// If you need a more precise answer, ask this Decl's corresponding
3196-
/// Type if it `isNoncopyable` instead of using this.
3197-
bool canBeNoncopyable() const;
3211+
/// Type if it `isCopyable` instead of using this.
3212+
CanBeInvertible::Result canBeCopyable() const;
31983213

3199-
/// Is this declaration escapable?
3200-
bool isEscapable() const;
3214+
/// "Does a conformance for Escapable exist for this type declaration?"
3215+
///
3216+
/// This doesn't mean that all instance of this type are Escapable, because
3217+
/// if a conditional conformance to Escapable exists, this method will return
3218+
/// true.
3219+
///
3220+
/// If you need a more precise answer, ask this Decl's corresponding
3221+
/// Type if it `isEscapable` instead of using this.
3222+
CanBeInvertible::Result canBeEscapable() const;
32013223

32023224
/// Determine how the given invertible protocol was written on this TypeDecl,
32033225
/// if at all.

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,9 @@ ERROR(serialization_target_too_new_repl,none,
863863
"deployment target of %0 %3: %4",
864864
(StringRef, llvm::VersionTuple, Identifier, llvm::VersionTuple,
865865
StringRef))
866+
ERROR(serialization_noncopyable_generics_mismatch,none,
867+
"module %0 was not compiled with NoncopyableGenerics",
868+
(Identifier))
866869

867870
ERROR(serialization_fatal,Fatal,
868871
"fatal error encountered while reading from module '%0'; "

include/swift/AST/Types.h

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -651,21 +651,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
651651

652652
bool isPlaceholder();
653653

654-
/// Returns true if this type lacks conformance to Copyable in the context,
655-
/// if provided.
656-
bool isNoncopyable(GenericEnvironment *env = nullptr);
657-
bool isNoncopyable(const DeclContext *dc) {
658-
assert(dc);
659-
return isNoncopyable(dc->getGenericEnvironmentOfContext());
660-
};
654+
/// Returns true if this contextual type does not satisfy a conformance to
655+
/// Copyable.
656+
bool isNoncopyable();
661657

662-
/// Returns true if this type conforms to Escapable in the context,
663-
/// if provided.
664-
bool isEscapable(GenericEnvironment *env = nullptr);
665-
bool isEscapable(const DeclContext *dc) {
666-
assert(dc);
667-
return isEscapable(dc->getGenericEnvironmentOfContext());
668-
};
658+
/// Returns true if this contextual type satisfies a conformance to Escapable.
659+
bool isEscapable();
669660

670661
/// Does the type have outer parenthesis?
671662
bool hasParenSugar() const { return getKind() == TypeKind::Paren; }
@@ -5574,7 +5565,9 @@ class SILMoveOnlyWrappedType final : public TypeBase,
55745565
: TypeBase(TypeKind::SILMoveOnlyWrapped, &innerType->getASTContext(),
55755566
innerType->getRecursiveProperties()),
55765567
innerType(innerType) {
5577-
assert(!innerType->isNoncopyable() && "Inner type must be copyable");
5568+
// If it has a type parameter, we can't check whether it's copyable.
5569+
assert(innerType->hasTypeParameter() ||
5570+
!innerType->isNoncopyable() && "Inner type must be copyable");
55785571
}
55795572

55805573
public:

include/swift/Config.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#cmakedefine01 SWIFT_ENABLE_EXPERIMENTAL_DISTRIBUTED
1616

17+
#cmakedefine01 SWIFT_ENABLE_EXPERIMENTAL_NONCOPYABLE_GENERICS
18+
1719
#cmakedefine01 SWIFT_ENABLE_GLOBAL_ISEL_ARM64
1820

1921
#endif // SWIFT_CONFIG_H

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,19 @@ struct RequireOSSAModules_t {
487487
explicit operator bool() const { return bool(value); }
488488
};
489489

490+
/// Help prevent confusion between different bools being passed around.
491+
struct RequireNoncopyableGenerics_t {
492+
private:
493+
bool value;
494+
public:
495+
RequireNoncopyableGenerics_t(const ASTContext &ctx)
496+
: RequireNoncopyableGenerics_t(ctx.LangOpts) {}
497+
RequireNoncopyableGenerics_t(const LangOptions &opts)
498+
: value(opts.hasFeature(Feature::NoncopyableGenerics)) {}
499+
500+
explicit operator bool() const { return value; }
501+
};
502+
490503
class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
491504
friend class ModuleInterfaceLoader;
492505
ASTContext &Ctx;
@@ -495,22 +508,26 @@ class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
495508
std::string BackupInterfaceDir;
496509
ModuleInterfaceLoaderOptions Opts;
497510
RequireOSSAModules_t RequiresOSSAModules;
511+
RequireNoncopyableGenerics_t RequireNCGenerics;
498512

499513
public:
500514
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
501-
StringRef prebuiltCacheDir,
502-
StringRef BackupInterfaceDir,
503-
ModuleInterfaceLoaderOptions opts,
504-
RequireOSSAModules_t requiresOSSAModules)
515+
StringRef prebuiltCacheDir,
516+
StringRef BackupInterfaceDir,
517+
ModuleInterfaceLoaderOptions opts,
518+
RequireOSSAModules_t requiresOSSAModules,
519+
RequireNoncopyableGenerics_t requireNCGenerics)
505520
: Ctx(Ctx), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
506521
BackupInterfaceDir(BackupInterfaceDir),
507-
Opts(opts), RequiresOSSAModules(requiresOSSAModules) {}
522+
Opts(opts), RequiresOSSAModules(requiresOSSAModules),
523+
RequireNCGenerics(requireNCGenerics) {}
508524
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
509-
StringRef prebuiltCacheDir,
510-
ModuleInterfaceLoaderOptions opts,
511-
RequireOSSAModules_t requiresOSSAModules):
525+
StringRef prebuiltCacheDir,
526+
ModuleInterfaceLoaderOptions opts,
527+
RequireOSSAModules_t requiresOSSAModules,
528+
RequireNoncopyableGenerics_t requireNCGenerics):
512529
ModuleInterfaceCheckerImpl(Ctx, cacheDir, prebuiltCacheDir, StringRef(),
513-
opts, requiresOSSAModules) {}
530+
opts, requiresOSSAModules, requireNCGenerics) {}
514531
std::vector<std::string>
515532
getCompiledModuleCandidatesForInterface(StringRef moduleName,
516533
StringRef interfacePath) override;
@@ -586,6 +603,7 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
586603
bool SerializeDependencyHashes,
587604
bool TrackSystemDependencies, ModuleInterfaceLoaderOptions Opts,
588605
RequireOSSAModules_t RequireOSSAModules,
606+
RequireNoncopyableGenerics_t RequireNCGenerics,
589607
bool silenceInterfaceDiagnostics);
590608

591609
/// Unconditionally build \p InPath (a swiftinterface file) to \p OutPath (as
@@ -640,7 +658,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
640658
const LangOptions &LangOpts,
641659
const ClangImporterOptions &clangImporterOpts,
642660
bool suppressRemarks,
643-
RequireOSSAModules_t requireOSSAModules);
661+
RequireOSSAModules_t requireOSSAModules,
662+
RequireNoncopyableGenerics_t requireNCGenerics);
644663
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,
645664
SwiftInterfaceInfo &interfaceInfo,
646665
StringRef interfacePath,
@@ -654,7 +673,8 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
654673
StringRef moduleCachePath, StringRef prebuiltCachePath,
655674
StringRef backupModuleInterfaceDir,
656675
bool serializeDependencyHashes, bool trackSystemDependencies,
657-
RequireOSSAModules_t requireOSSAModules);
676+
RequireOSSAModules_t requireOSSAModules,
677+
RequireNoncopyableGenerics_t requireNCGenerics);
658678

659679
template<typename ...ArgTypes>
660680
static InFlightDiagnostic diagnose(StringRef interfacePath,

include/swift/SIL/SILType.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -763,9 +763,13 @@ class SILType {
763763
/// Returns true if this is the AnyObject SILType;
764764
bool isAnyObject() const { return getASTType()->isAnyObject(); }
765765

766-
/// Returns true if this type is a first class move only type or a move only
767-
/// wrapped type.
768-
bool isMoveOnly() const;
766+
/// Returns true if this type is a noncopyable type. Otherwise, if the type
767+
/// satisfies \c isMoveOnlyWrapped(), then it returns true iff \c orWrapped
768+
/// is true. That is,
769+
///
770+
/// orWrapped == false --> isNoncopyable
771+
/// orWrapped == true --> isNoncopyable || isMoveOnlyWrapped
772+
bool isMoveOnly(bool orWrapped=true) const;
769773

770774
/// Return true if this is a value type (struct/enum) that requires
771775
/// deinitialization beyond destruction of its members.

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
176176
ModuleLoadingBehavior transitiveBehavior,
177177
bool isFramework,
178178
bool isRequiredOSSAModules,
179+
bool isRequiredNoncopyableGenerics,
179180
StringRef SDKName,
180181
StringRef packageName,
181182
llvm::vfs::FileSystem *fileSystem,
@@ -205,6 +206,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
205206
bool isFramework);
206207

207208
bool isRequiredOSSAModules() const;
209+
bool isRequiredNoncopyableGenerics() const;
208210

209211
/// Check whether the module with a given name can be imported without
210212
/// importing it.

include/swift/Serialization/Validation.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ enum class Status {
8282

8383
/// The module file was built with a different SDK than the one in use
8484
/// to build the client.
85-
SDKMismatch
85+
SDKMismatch,
86+
87+
/// The module file was not built with support for NoncopyableGenerics,
88+
/// yet that is required to by this compiler.
89+
NotUsingNoncopyableGenerics,
8690
};
8791

8892
/// Returns the string for the Status enum.
@@ -249,6 +253,8 @@ struct SearchPath {
249253
/// refers directly into this buffer.
250254
/// \param requiresOSSAModules If true, necessitates the module to be
251255
/// compiled with -enable-ossa-modules.
256+
/// \param requiresNoncopyableGenerics requires the module to have been built
257+
/// with the feature \c NoncopyableGenerics enabled.
252258
/// \param requiredSDK If not empty, only accept modules built with
253259
/// a compatible SDK. The StringRef represents the canonical SDK name.
254260
/// \param[out] extendedInfo If present, will be populated with additional
@@ -257,7 +263,8 @@ struct SearchPath {
257263
/// \param[out] dependencies If present, will be populated with list of
258264
/// input files the module depends on, if present in INPUT_BLOCK.
259265
ValidationInfo validateSerializedAST(
260-
StringRef data, bool requiresOSSAModules, StringRef requiredSDK,
266+
StringRef data, bool requiresOSSAModules, bool requiresNoncopyableGenerics,
267+
StringRef requiredSDK,
261268
ExtendedValidationInfo *extendedInfo = nullptr,
262269
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies =
263270
nullptr,

lib/AST/ASTMangler.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,15 @@ void ASTMangler::appendExistentialLayout(
11411141
bool DroppedRequiresClass = false;
11421142
bool SawRequiresClass = false;
11431143
for (auto proto : layout.getProtocols()) {
1144+
// Skip invertible protocols
1145+
//
1146+
// TODO: reconsituteInverses so the absence of such protocols gets mangled.
1147+
// I think here we need to see if any protocols inheritsFrom
1148+
// Copyable/Escapable, and if not, and none of those are found in the layout
1149+
// then it must have had an inverse.
1150+
if (proto->getInvertibleProtocolKind())
1151+
continue;
1152+
11441153
// If we aren't allowed to emit marker protocols, suppress them here.
11451154
if (!AllowMarkerProtocols && proto->isMarkerProtocol()) {
11461155
if (proto->requiresClass())
@@ -2996,14 +3005,28 @@ void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
29963005
appendOperator("d");
29973006
}
29983007

3008+
/// Filters out requirements stating that a type conforms to one of the
3009+
/// invertible protocols.
3010+
/// TODO: reconsituteInverses so the absence of conformances gets mangled
3011+
static void withoutInvertibleRequirements(ArrayRef<Requirement> requirements,
3012+
SmallVector<Requirement, 4> &output) {
3013+
for (auto req : requirements) {
3014+
// Skip conformance requirements for invertible protocols.
3015+
if (req.getKind() == RequirementKind::Conformance
3016+
&& req.getProtocolDecl()->getInvertibleProtocolKind())
3017+
continue;
3018+
3019+
output.push_back(req);
3020+
}
3021+
}
3022+
29993023
bool ASTMangler::appendGenericSignature(GenericSignature sig,
30003024
GenericSignature contextSig) {
30013025
auto canSig = sig.getCanonicalSignature();
30023026

30033027
unsigned initialParamDepth;
30043028
ArrayRef<CanTypeWrapper<GenericTypeParamType>> genericParams;
3005-
ArrayRef<Requirement> requirements;
3006-
SmallVector<Requirement, 4> requirementsBuffer;
3029+
SmallVector<Requirement, 4> requirements;
30073030
if (contextSig) {
30083031
// If the signature is the same as the context signature, there's nothing
30093032
// to do.
@@ -3033,16 +3056,16 @@ bool ASTMangler::appendGenericSignature(GenericSignature sig,
30333056
contextSig.getRequirements().empty()) {
30343057
initialParamDepth = 0;
30353058
genericParams = canSig.getGenericParams();
3036-
requirements = canSig.getRequirements();
3059+
withoutInvertibleRequirements(canSig.getRequirements(), requirements);
30373060
} else {
3038-
requirementsBuffer = canSig.requirementsNotSatisfiedBy(contextSig);
3039-
requirements = requirementsBuffer;
3061+
withoutInvertibleRequirements(
3062+
canSig.requirementsNotSatisfiedBy(contextSig), requirements);
30403063
}
30413064
} else {
30423065
// Use the complete canonical signature.
30433066
initialParamDepth = 0;
30443067
genericParams = canSig.getGenericParams();
3045-
requirements = canSig.getRequirements();
3068+
withoutInvertibleRequirements(canSig.getRequirements(), requirements);
30463069
}
30473070

30483071
if (genericParams.empty() && requirements.empty())

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3288,7 +3288,7 @@ class Verifier : public ASTWalker {
32883288
PrettyStackTraceDecl debugStack("verifying DestructorDecl", DD);
32893289

32903290
auto *ND = DD->getDeclContext()->getSelfNominalTypeDecl();
3291-
if (!isa<ClassDecl>(ND) && !ND->canBeNoncopyable() && !DD->isInvalid()) {
3291+
if (!isa<ClassDecl>(ND) && ND->canBeCopyable() && !DD->isInvalid()) {
32923292
Out << "DestructorDecls outside classes/move only types should be "
32933293
"marked invalid\n";
32943294
abort();

lib/AST/ConformanceLookup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -620,10 +620,10 @@ LookupConformanceInModuleRequest::evaluate(
620620
// We only need to do this until we are properly dealing with or
621621
// omitting Copyable conformances in modules/interfaces.
622622

623-
if (nominal->canBeNoncopyable())
624-
return ProtocolConformanceRef::forMissingOrInvalid(type, protocol);
625-
else
623+
if (nominal->canBeCopyable())
626624
return ProtocolConformanceRef(protocol);
625+
else
626+
return ProtocolConformanceRef::forMissingOrInvalid(type, protocol);
627627
}
628628

629629
// Try to infer the conformance.

0 commit comments

Comments
 (0)