Skip to content

[Integration PR] Noncopyable generics in stdlib (phase 2) + Use new noncopyable types infrastructure #72346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
156912d
[stdlib] MemoryLayout: Add support for non-copyable type arguments
lorentey Feb 16, 2024
97a1222
[stdlib] Unsafe[Mutable]Pointer: Add support for non-copyable Pointee…
lorentey Feb 16, 2024
9c3f228
[stdlib] Optional: Initial support for noncopyable payloads
lorentey Feb 29, 2024
888009d
[stdlib] UnsafeRawPointer: new interactions with noncopyable types
lorentey Mar 5, 2024
156c07c
[stdlib] OpaquePointer: new interactions with noncopyable types
lorentey Mar 5, 2024
1f0dd87
[stdlib] MemoryLayout: Adopt @_preInverseGenerics
lorentey Mar 6, 2024
ee47380
[stdlib] UnsafePointer: Adopt @_preInverseGenerics
lorentey Mar 6, 2024
292c91b
[stdlib] Optional: Adopt @_preInverseGenerics
lorentey Mar 6, 2024
8d4178a
[stdlib] UnsafeRawPointer: Adopt @_preInverseGenerics
lorentey Mar 6, 2024
a9f8b9e
[stdlib] OpaquePointer: Adopt @_preInverseGenerics
lorentey Mar 6, 2024
063425c
[stdlib] Generalize swap(_:_:) for noncopyable types
lorentey Mar 6, 2024
77f893c
[stdlib] UnsafePointer: Add @_preInverseGenerics to stored properties
lorentey Mar 7, 2024
288f85f
[stdlib] UnsafePointer: Add @_preInverseGenerics to _Pointer conformance
lorentey Mar 7, 2024
a043db2
[stdlib] Optional: Add @_preInverseGenerics to ExpressibleByNilLitera…
lorentey Mar 7, 2024
0b7e715
[stdlib] UnsafePointer: Don’t let the compiler synthesize `hashValue`
lorentey Mar 7, 2024
2657a37
[stdlib] UnsafePointer: Resolve most of the symbol mismatches
lorentey Mar 7, 2024
1410df6
[Synchronization] Update symbol expectations
lorentey Mar 7, 2024
690c74e
[stdlib] Unsafe[Mutable]BufferPointer: Add support for non-copyable P…
lorentey Mar 2, 2024
b94a0f9
[stdlib] UnsafeRawBufferPointer: new interactions with noncopyable types
lorentey Mar 5, 2024
48d4064
[stdlib] Add support for noncopyables to swap(_:_:)
lorentey Mar 6, 2024
4da03bd
[stdlib] Result: Initial support for noncopyable payloads
lorentey Mar 5, 2024
883d01a
[stdlib] Add support for noncopyables to withExtendedLifetime(of:) fa…
lorentey Mar 6, 2024
2edb748
[stdlib] Add support for noncopyables to withUnsafePointer(to:) family
lorentey Mar 6, 2024
4530bbe
[stdlib] Temporarily disable round trip validation for debug types
lorentey Mar 12, 2024
68d9fb5
[stdlib][abi] Add expectations for new property descriptors for U[M]B…
lorentey Mar 13, 2024
b015768
[stdlib] Add partial ~Copyable support to withUnsafeTemporaryAllocati…
lorentey Mar 14, 2024
6d4537c
[stdlib] ManagedBuffer: Support for noncopyable Element
lorentey Mar 14, 2024
4f942f4
[stdlib] Add workaround for unexpected ManagedBuffer ABI mismatch
lorentey Mar 14, 2024
72abd6c
[IRGen] Temporarily disable round-tripping debug types
lorentey Mar 14, 2024
cf90aa0
[build] Enable noncopyable generics; disable anything that prevents t…
lorentey Mar 14, 2024
cb920a6
[stdlib] Update SwiftStdlibLegacyABI convention to use `@available(sw…
lorentey Mar 15, 2024
7cf3d1f
[stdlib] withUnsafePointer: Spell out Error conformance on E
lorentey Mar 15, 2024
476e5a6
[stdlib] Make MemoryLayout techically copyable
lorentey Mar 15, 2024
96ab76a
[stdlib] Apply minor review notes
lorentey Mar 15, 2024
d278067
[stdlib] {consuming,borrowing}{Flat,}Map: adopt typed throws
lorentey Mar 15, 2024
60cfafe
[stdlib] Use hasFeature(Foo) instead of opaque $Foo syntax
lorentey Mar 15, 2024
05a19b5
[stdlib] Apply @Azoy’s remaining review notes (thanks!)
lorentey Mar 15, 2024
0d1ee38
[stdlib] Remove all new public API for now
lorentey Mar 15, 2024
e1e3aa1
[Synchronization] Generalize U[M]BP’s AtomicRepresentable conformance
lorentey Mar 15, 2024
41fe7bb
[util] swift-abi-symbol-checker: Don’t exit early for missing additions
lorentey Mar 15, 2024
8722eba
Revert "[build] Enable noncopyable generics; disable anything that pr…
lorentey Mar 15, 2024
dd2eb35
Revert "[IRGen] Temporarily disable round-tripping debug types"
lorentey Mar 15, 2024
9a9b499
[stdlib] Delete leftover workaround
lorentey Mar 15, 2024
acc3eca
Test: update `inverse_copyable_requirement.swift`
kavon Mar 12, 2024
21485fb
un-XFAIL `type_in_function.swift`
kavon Mar 12, 2024
c5e76db
Sema: remove TypeResolver::diagnoseMoveOnlyGeneric
kavon Mar 12, 2024
77d4c44
use new noncopyable types infrastructure
kavon Mar 13, 2024
efc6a33
Sema: remove more unneeded legacy code
kavon Mar 13, 2024
0717e48
more enablement of code
kavon Mar 13, 2024
56a124a
Features: Sendable doesn't use NoncopyableGenerics
kavon Mar 13, 2024
1b64eb6
Test: fold together similar NCGenerics tests
kavon Mar 13, 2024
5e3a3a4
Test: update mangling of non-ABI shared symbols
kavon Mar 13, 2024
95e301d
NCGenerics: claim to have Escapable runtime info.
kavon Mar 13, 2024
ef7d81b
Test: updates for NoncopyableGenerics
kavon Mar 14, 2024
56390a3
Test: fix a number of NCGenerics-specific tests
kavon Mar 14, 2024
c17c93f
Test: disable `move-only-cxx-value-type.swift`
kavon Mar 14, 2024
c5ace27
Test: disable `lazy_parsing.swift`
kavon Mar 14, 2024
05af019
Test: update `xref-extensions-counters.swift`
kavon Mar 14, 2024
547b7bd
Test: misc. test updates for NoncopyableGenerics
kavon Mar 14, 2024
2ff62dd
Test: update for NoncopyableGenerics
kavon Mar 14, 2024
e1737b3
Test: NCGenerics update `generic_classes_objc.sil`
kavon Mar 14, 2024
cf8a46a
XFAIL test for minor issue
kavon Mar 14, 2024
100310b
Test: update for NoncopyableGenerics infra.
kavon Mar 14, 2024
7c5addf
NFC: expose an `InverseRequirement::print`
kavon Mar 14, 2024
6c98b61
APIDigester: Stringify inverses in GenericSigs
kavon Mar 14, 2024
1eb56df
ABI Tests: include Copyable/Escapable in baseline
kavon Mar 14, 2024
576bf6d
Deserialization: handle bogus type in BuiltinConfs
kavon Mar 14, 2024
973332d
Test: update baseline for NoncopyableGenerics
kavon Mar 15, 2024
6bf4732
XFAIL test with a newly revealed mistake
kavon Mar 15, 2024
c0c9e6c
Test: fix and enable test
kavon Mar 15, 2024
c7021ec
XFAIL `parse_stdlib.sil` temporarily
kavon Mar 15, 2024
c65ab63
[test] Update tests for new stdlib
lorentey Mar 15, 2024
0d174a7
[stdlib] ManagedBuffer: Add @_preInverseGenerics for $Embedded
lorentey Mar 15, 2024
61bed88
[test] Un-XFAIL test that is now passing
lorentey Mar 15, 2024
16790ed
[test] XFAIL two new nontrivial test failures
lorentey Mar 15, 2024
b3fa27b
[gardening] update copyright notice
glessard Mar 15, 2024
48f2d21
[abi] Update false positives list for api-digester based ABI/source s…
lorentey Mar 15, 2024
7cedc12
[test][IDE] Update code completion expectation
lorentey Mar 15, 2024
4fe88bc
[test] Temporarily XFAIL tests that expect swiftinterface files to wo…
lorentey Mar 15, 2024
d500dc2
[stdlib] Apply review notes from @glessard (thanks!)
lorentey Mar 15, 2024
8ea0a2d
[test][abi] Remove expectations that got resolved by #72348
lorentey Mar 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4392,10 +4392,6 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
/// Type if it `isEscapable` instead of using this.
CanBeInvertible::Result canBeEscapable() const;

/// Determine whether this type has ~<target>` stated on
/// itself, one of its inherited types or `Self` requirements.
InverseMarking::Mark hasInverseMarking(InvertibleProtocolKind target) const;

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= DeclKind::First_NominalTypeDecl &&
Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7676,9 +7676,6 @@ ERROR(bitwise_copyable_outside_module,none,
(const ValueDecl *))

// -- older ones below --
ERROR(noncopyable_cannot_conform_to_type, none,
"noncopyable %kind0 cannot conform to %1",
(const ValueDecl *, Type))
ERROR(noncopyable_parameter_requires_ownership, none,
"parameter of noncopyable type %0 must specify ownership", (Type))
ERROR(noncopyable_parameter_subscript_unsupported, none,
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/Requirement.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ struct InverseRequirement {
static void expandDefaults(ASTContext &ctx,
ArrayRef<Type> gps,
SmallVectorImpl<StructuralRequirement> &result);

void print(raw_ostream &os, const PrintOptions &opts, bool forInherited=false) const;
};

} // end namespace swift
Expand Down
32 changes: 6 additions & 26 deletions include/swift/Frontend/ModuleInterfaceLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,19 +486,6 @@ struct RequireOSSAModules_t {
explicit operator bool() const { return bool(value); }
};

/// Help prevent confusion between different bools being passed around.
struct RequireNoncopyableGenerics_t {
private:
bool value;
public:
RequireNoncopyableGenerics_t(const ASTContext &ctx)
: RequireNoncopyableGenerics_t(ctx.LangOpts) {}
RequireNoncopyableGenerics_t(const LangOptions &opts)
: value(opts.hasFeature(Feature::NoncopyableGenerics)) {}

explicit operator bool() const { return value; }
};

class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
friend class ModuleInterfaceLoader;
ASTContext &Ctx;
Expand All @@ -507,26 +494,22 @@ class ModuleInterfaceCheckerImpl: public ModuleInterfaceChecker {
std::string BackupInterfaceDir;
ModuleInterfaceLoaderOptions Opts;
RequireOSSAModules_t RequiresOSSAModules;
RequireNoncopyableGenerics_t RequireNCGenerics;

public:
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
StringRef prebuiltCacheDir,
StringRef BackupInterfaceDir,
ModuleInterfaceLoaderOptions opts,
RequireOSSAModules_t requiresOSSAModules,
RequireNoncopyableGenerics_t requireNCGenerics)
RequireOSSAModules_t requiresOSSAModules)
: Ctx(Ctx), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir),
BackupInterfaceDir(BackupInterfaceDir),
Opts(opts), RequiresOSSAModules(requiresOSSAModules),
RequireNCGenerics(requireNCGenerics) {}
Opts(opts), RequiresOSSAModules(requiresOSSAModules) {}
explicit ModuleInterfaceCheckerImpl(ASTContext &Ctx, StringRef cacheDir,
StringRef prebuiltCacheDir,
ModuleInterfaceLoaderOptions opts,
RequireOSSAModules_t requiresOSSAModules,
RequireNoncopyableGenerics_t requireNCGenerics):
RequireOSSAModules_t requiresOSSAModules):
ModuleInterfaceCheckerImpl(Ctx, cacheDir, prebuiltCacheDir, StringRef(),
opts, requiresOSSAModules, requireNCGenerics) {}
opts, requiresOSSAModules) {}
std::vector<std::string>
getCompiledModuleCandidatesForInterface(StringRef moduleName,
StringRef interfacePath) override;
Expand Down Expand Up @@ -602,7 +585,6 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
bool SerializeDependencyHashes, bool TrackSystemDependencies,
ModuleInterfaceLoaderOptions Opts,
RequireOSSAModules_t RequireOSSAModules,
RequireNoncopyableGenerics_t RequireNCGenerics,
bool silenceInterfaceDiagnostics);

/// Unconditionally build \p InPath (a swiftinterface file) to \p OutPath (as
Expand Down Expand Up @@ -657,8 +639,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
const ClangImporterOptions &clangImporterOpts,
const CASOptions &casOpts,
bool suppressRemarks,
RequireOSSAModules_t requireOSSAModules,
RequireNoncopyableGenerics_t requireNCGenerics);
RequireOSSAModules_t requireOSSAModules);
bool extractSwiftInterfaceVersionAndArgs(CompilerInvocation &subInvocation,
SwiftInterfaceInfo &interfaceInfo,
StringRef interfacePath,
Expand All @@ -671,8 +652,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
ModuleInterfaceLoaderOptions LoaderOpts, bool buildModuleCacheDirIfAbsent,
StringRef moduleCachePath, StringRef prebuiltCachePath,
StringRef backupModuleInterfaceDir, bool serializeDependencyHashes,
bool trackSystemDependencies, RequireOSSAModules_t requireOSSAModules,
RequireNoncopyableGenerics_t requireNCGenerics);
bool trackSystemDependencies, RequireOSSAModules_t requireOSSAModules);

template<typename ...ArgTypes>
static InFlightDiagnostic diagnose(StringRef interfacePath,
Expand Down
2 changes: 0 additions & 2 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ class SerializedModuleLoaderBase : public ModuleLoader {
ModuleLoadingBehavior transitiveBehavior,
bool isFramework,
bool isRequiredOSSAModules,
bool isRequiredNoncopyableGenerics,
StringRef SDKName,
StringRef packageName,
llvm::vfs::FileSystem *fileSystem,
Expand Down Expand Up @@ -212,7 +211,6 @@ class SerializedModuleLoaderBase : public ModuleLoader {
bool isFramework);

bool isRequiredOSSAModules() const;
bool isRequiredNoncopyableGenerics() const;

/// Check whether the module with a given name can be imported without
/// importing it.
Expand Down
8 changes: 1 addition & 7 deletions include/swift/Serialization/Validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ enum class Status {
/// The module file was built with a different SDK than the one in use
/// to build the client.
SDKMismatch,

/// The module file was built with a different NoncopyableGenerics feature
/// mode than the compiler loading it.
NoncopyableGenericsMismatch,
};

/// Returns the string for the Status enum.
Expand Down Expand Up @@ -262,8 +258,6 @@ struct SearchPath {
/// refers directly into this buffer.
/// \param requiresOSSAModules If true, necessitates the module to be
/// compiled with -enable-ossa-modules.
/// \param requiresNoncopyableGenerics requires the module to have been built
/// with the feature \c NoncopyableGenerics enabled.
/// \param requiredSDK If not empty, only accept modules built with
/// a compatible SDK. The StringRef represents the canonical SDK name.
/// \param[out] extendedInfo If present, will be populated with additional
Expand All @@ -272,7 +266,7 @@ struct SearchPath {
/// \param[out] dependencies If present, will be populated with list of
/// input files the module depends on, if present in INPUT_BLOCK.
ValidationInfo validateSerializedAST(
StringRef data, bool requiresOSSAModules, bool requiresNoncopyableGenerics,
StringRef data, bool requiresOSSAModules,
StringRef requiredSDK,
ExtendedValidationInfo *extendedInfo = nullptr,
SmallVectorImpl<SerializationOptions::FileDependency> *dependencies =
Expand Down
29 changes: 25 additions & 4 deletions lib/APIDigester/ModuleAnalyzerNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ static PrintOptions getTypePrintOpts(CheckerOptions CheckerOpts) {
PrintOptions Opts;
Opts.SynthesizeSugarOnTypes = true;
Opts.UseOriginallyDefinedInModuleNames = true;
Opts.PrintInverseRequirements = true; // Only inverses are relevant for ABI stability
if (!CheckerOpts.Migrator) {
// We should always print fully qualified type names for checking either
// API or ABI stability.
Expand Down Expand Up @@ -1222,8 +1223,15 @@ Requirement getCanonicalRequirement(Requirement &Req) {
}
}

// Get an inverse requirement with the subject type canonicalized.
InverseRequirement getCanonicalInverseRequirement(InverseRequirement &Req) {
return {Req.subject->getCanonicalType(), Req.protocol, Req.loc};
}

static
StringRef printGenericSignature(SDKContext &Ctx, ArrayRef<Requirement> AllReqs,
StringRef printGenericSignature(SDKContext &Ctx,
ArrayRef<Requirement> AllReqs,
ArrayRef<InverseRequirement> Inverses,
bool Canonical) {
llvm::SmallString<32> Result;
llvm::raw_svector_ostream OS(Result);
Expand All @@ -1243,6 +1251,17 @@ StringRef printGenericSignature(SDKContext &Ctx, ArrayRef<Requirement> AllReqs,
else
Req.print(OS, Opts);
}
for (auto Inv: Inverses) {
if (!First) {
OS << ", ";
} else {
First = false;
}
if (Canonical)
getCanonicalInverseRequirement(Inv).print(OS, Opts);
else
Inv.print(OS, Opts);
}
OS << ">";
return Ctx.buffer(OS.str());
}
Expand All @@ -1251,8 +1270,10 @@ static StringRef printGenericSignature(SDKContext &Ctx, Decl *D, bool Canonical)
llvm::SmallString<32> Result;
llvm::raw_svector_ostream OS(Result);
if (auto *PD = dyn_cast<ProtocolDecl>(D)) {
return printGenericSignature(Ctx, PD->getRequirementSignature().getRequirements(),
Canonical);
SmallVector<Requirement, 2> reqs;
SmallVector<InverseRequirement, 2> inverses;
PD->getRequirementSignature().getRequirementsWithInverses(PD, reqs, inverses);
return printGenericSignature(Ctx, reqs, inverses, Canonical);
}
PrintOptions Opts = getTypePrintOpts(Ctx.getOpts());
if (auto *GC = D->getAsGenericContext()) {
Expand All @@ -1269,7 +1290,7 @@ static StringRef printGenericSignature(SDKContext &Ctx, Decl *D, bool Canonical)

static
StringRef printGenericSignature(SDKContext &Ctx, ProtocolConformance *Conf, bool Canonical) {
return printGenericSignature(Ctx, Conf->getConditionalRequirements(), Canonical);
return printGenericSignature(Ctx, Conf->getConditionalRequirements(), {}, Canonical);
}

static std::optional<uint8_t>
Expand Down
47 changes: 25 additions & 22 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7424,6 +7424,13 @@ void Requirement::print(ASTPrinter &printer, const PrintOptions &opts) const {
PrintAST(printer, opts).printRequirement(*this);
}

void InverseRequirement::print(raw_ostream &os,
const PrintOptions &opts,
bool forInherited) const {
StreamPrinter printer(os);
PrintAST(printer, opts).printRequirement(*this, forInherited);
}

std::string GenericSignatureImpl::getAsString() const {
return GenericSignature(const_cast<GenericSignatureImpl *>(this))
.getAsString();
Expand Down Expand Up @@ -7727,17 +7734,15 @@ static void getSyntacticInheritanceClause(const ProtocolDecl *proto,
InvertibleProtocolSet inverses = InvertibleProtocolSet::full();

for (auto *inherited : proto->getInheritedProtocols()) {
if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
if (auto ip = inherited->getInvertibleProtocolKind()) {
inverses.remove(*ip);
continue;
}
if (auto ip = inherited->getInvertibleProtocolKind()) {
inverses.remove(*ip);
continue;
}

for (auto ip : InvertibleProtocolSet::full()) {
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
if (inherited->inheritsFrom(proto))
inverses.remove(ip);
}
for (auto ip : InvertibleProtocolSet::full()) {
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
if (inherited->inheritsFrom(proto))
inverses.remove(ip);
}

Results.emplace_back(TypeLoc::withoutLoc(inherited->getDeclaredInterfaceType()),
Expand All @@ -7746,19 +7751,17 @@ static void getSyntacticInheritanceClause(const ProtocolDecl *proto,
/*isPreconcurrency=*/false);
}

if (ctx.LangOpts.hasFeature(Feature::NoncopyableGenerics)) {
for (auto ip : inverses) {
InvertibleProtocolSet singleton;
singleton.insert(ip);
for (auto ip : inverses) {
InvertibleProtocolSet singleton;
singleton.insert(ip);

auto inverseTy = ProtocolCompositionType::get(
ctx, ArrayRef<Type>(), singleton,
/*hasExplicitAnyObject=*/false);
Results.emplace_back(TypeLoc::withoutLoc(inverseTy),
/*isUnchecked=*/false,
/*isRetroactive=*/false,
/*isPreconcurrency=*/false);
}
auto inverseTy = ProtocolCompositionType::get(
ctx, ArrayRef<Type>(), singleton,
/*hasExplicitAnyObject=*/false);
Results.emplace_back(TypeLoc::withoutLoc(inverseTy),
/*isUnchecked=*/false,
/*isRetroactive=*/false,
/*isPreconcurrency=*/false);
}
}

Expand Down
13 changes: 0 additions & 13 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,6 @@ struct CollectGenericParams {
auto protocolType = synthesizeType(SC, conf.Protocol);
Requirement req = {RequirementKind::Conformance, type, protocolType};

// If it's an invertible protocol and NoncopyableGenerics is disabled
// then skip the requirement.
if (req.getProtocolDecl()->getInvertibleProtocolKind())
if (!SC.Context.LangOpts.hasFeature(Feature::NoncopyableGenerics))
return;

AddedRequirements.push_back(req);
}

Expand Down Expand Up @@ -736,13 +730,6 @@ namespace {
Requirement req(RequirementKind::Conformance,
generator.build(*this),
proto->getDeclaredInterfaceType());

// If it's an invertible protocol and NoncopyableGenerics is disabled
// then skip the requirement.
if (req.getProtocolDecl()->getInvertibleProtocolKind())
if (!Context.LangOpts.hasFeature(Feature::NoncopyableGenerics))
return;

addedRequirements.push_back(req);
}

Expand Down
Loading