Skip to content

Commit 80205ec

Browse files
authored
Merge pull request #71241 from slavapestov/ncgenerics-fixes
Non-copyable generics fixes
2 parents f3189fb + d8f85a3 commit 80205ec

File tree

73 files changed

+922
-682
lines changed

Some content is hidden

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

73 files changed

+922
-682
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5365,10 +5365,6 @@ class ProtocolDecl final : public NominalTypeDecl {
53655365
/// view of the generic system; see RequirementSignature.h for details.
53665366
RequirementSignature getRequirementSignature() const;
53675367

5368-
/// Sometimes we want to make a fake generic signature from the requirements
5369-
/// of a requirement signature.
5370-
GenericSignature getRequirementSignatureAsGenericSignature() const;
5371-
53725368
/// Is the requirement signature currently being computed?
53735369
bool isComputingRequirementSignature() const;
53745370

include/swift/AST/GenericSignature.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,13 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final
310310
return Mem;
311311
}
312312

313+
/// Transform the requirements into a form where implicit Copyable and
314+
/// Escapable conformances are omitted, and their absence is explicitly
315+
/// noted.
316+
void getRequirementsWithInverses(
317+
SmallVector<Requirement, 2> &reqs,
318+
SmallVector<InverseRequirement, 2> &inverses) const;
319+
313320
/// Look up a stored conformance in the generic signature. These are formed
314321
/// from same-type constraints placed on associated types of generic
315322
/// parameters which have conformance constraints on them.

include/swift/AST/PrintOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ struct PrintOptions {
329329
/// Whether to print generic requirements in a where clause.
330330
bool PrintGenericRequirements = true;
331331

332+
/// Whether to print generic signatures with inverse requirements (ie,
333+
/// ~Copyable noting the absence of Copyable) or the internal desugared form
334+
/// (where the implicit Copyable conformance is spelled explicitly).
335+
bool PrintInverseRequirements = false;
336+
332337
/// Whether to print the internal layout name instead of AnyObject, etc.
333338
bool PrintInternalLayoutName = false;
334339

include/swift/AST/RequirementSignature.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ class RequirementSignature final {
7373
GenericSignatureErrors getErrors() const {
7474
return Errors;
7575
}
76+
77+
void getRequirementsWithInverses(
78+
ProtocolDecl *owner,
79+
SmallVector<Requirement, 2> &reqs,
80+
SmallVector<InverseRequirement, 2> &inverses) const;
81+
82+
void print(ProtocolDecl *owner, raw_ostream &OS,
83+
const PrintOptions &Options = PrintOptions()) const;
84+
void print(ProtocolDecl *owner, ASTPrinter &Printer,
85+
const PrintOptions &Opts = PrintOptions()) const;
7686
};
7787

7888
} // end namespace swift

include/swift/AST/SubstitutionMap.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,29 @@ class SubstitutionMap {
101101
/// Build an empty substitution map.
102102
SubstitutionMap() { }
103103

104-
/// Build an interface type substitution map for the given generic
105-
/// signature and a vector of Substitutions that correspond to the
106-
/// requirements of this generic signature.
104+
/// The primitive constructor.
107105
static SubstitutionMap get(GenericSignature genericSig,
108106
ArrayRef<Type> replacementTypes,
109107
ArrayRef<ProtocolConformanceRef> conformances) {
110108
return SubstitutionMap(genericSig, replacementTypes, conformances);
111109
}
112110

113-
/// Build an interface type substitution map for the given generic
114-
/// signature using the mapping in the given substitutions.
111+
/// Translate a substitution map from one generic signature to another
112+
/// "compatible" one. Think carefully before using this.
115113
static SubstitutionMap get(GenericSignature genericSig,
116114
SubstitutionMap substitutions);
117115

118-
/// Build an interface type substitution map for the given generic signature
119-
/// from a type substitution function and conformance lookup function.
116+
/// General form that takes two callbacks.
120117
static SubstitutionMap get(GenericSignature genericSig,
121118
TypeSubstitutionFn subs,
122119
LookupConformanceFn lookupConformance);
123120

121+
/// Takes an array of replacement types already in the correct form, together
122+
/// with a conformance lookup callback.
123+
static SubstitutionMap get(GenericSignature genericSig,
124+
ArrayRef<Type> replacementTypes,
125+
LookupConformanceFn lookupConformance);
126+
124127
/// Build a substitution map from the substitutions represented by
125128
/// the given in-flight substitution.
126129
///
@@ -306,6 +309,15 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
306309
return OS;
307310
}
308311

312+
/// A function object suitable for use as a \c TypeSubstitutionFn that
313+
/// queries an array of replacement types.
314+
struct QueryReplacementTypeArray {
315+
GenericSignature sig;
316+
ArrayRef<Type> types;
317+
318+
Type operator()(SubstitutableType *type) const;
319+
};
320+
309321
/// A function object suitable for use as a \c TypeSubstitutionFn that
310322
/// queries an underlying \c SubstitutionMap.
311323
struct QuerySubstitutionMap {

include/swift/AST/TypeCheckRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,24 @@ class ValueWitnessRequest
29102910
void cacheResult(Witness value) const;
29112911
};
29122912

2913+
class ResolveValueWitnessesRequest
2914+
: public SimpleRequest<ResolveValueWitnessesRequest,
2915+
evaluator::SideEffect(NormalProtocolConformance *),
2916+
RequestFlags::Cached> {
2917+
public:
2918+
using SimpleRequest::SimpleRequest;
2919+
2920+
private:
2921+
friend SimpleRequest;
2922+
2923+
// Evaluation.
2924+
evaluator::SideEffect
2925+
evaluate(Evaluator &evaluator, NormalProtocolConformance *conformance) const;
2926+
2927+
public:
2928+
bool isCached() const { return true; }
2929+
};
2930+
29132931
class AssociatedConformanceRequest
29142932
: public SimpleRequest<AssociatedConformanceRequest,
29152933
ProtocolConformanceRef(NormalProtocolConformance *,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ SWIFT_REQUEST(TypeChecker, ResolveTypeWitnessesRequest,
441441
SWIFT_REQUEST(TypeChecker, ValueWitnessRequest,
442442
Witness(NormalProtocolConformance *, ValueDecl *),
443443
SeparatelyCached, NoLocationInfo)
444+
SWIFT_REQUEST(TypeChecker, ResolveValueWitnessesRequest,
445+
evaluator::SideEffect(NormalProtocolConformance *),
446+
Cached, NoLocationInfo)
444447
SWIFT_REQUEST(TypeChecker, PatternTypeRequest,
445448
Type(ContextualPattern),
446449
Cached, HasNearestLocation)

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,10 @@ namespace swift {
793793
/// Debug the generic signatures computed by the generic signature builder.
794794
bool DebugGenericSignatures = false;
795795

796+
/// If this is set, we skip the inverse transform and print explicit
797+
/// Copyable/Escapable requirements in the above.
798+
bool DebugInverseRequirements = false;
799+
796800
/// Whether we are debugging the constraint solver.
797801
///
798802
/// This option enables verbose debugging output from the constraint

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,9 @@ def disable_round_trip_debug_types : Flag<["-"], "disable-round-trip-debug-types
440440
def debug_generic_signatures : Flag<["-"], "debug-generic-signatures">,
441441
HelpText<"Debug generic signatures">;
442442

443+
def debug_inverse_requirements : Flag<["-"], "debug-inverse-requirements">,
444+
HelpText<"Print real requirements in -debug_generic_signatures output">;
445+
443446
def debug_forbid_typecheck_prefix : Separate<["-"], "debug-forbid-typecheck-prefix">,
444447
HelpText<"Triggers llvm fatal_error if typechecker tries to typecheck a decl "
445448
"with the provided prefix name">;

lib/AST/ASTDemangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,8 @@ ASTBuilder::createGenericSignature(ArrayRef<BuiltType> builtParams,
953953
SubstitutionMap
954954
ASTBuilder::createSubstitutionMap(BuiltGenericSignature sig,
955955
ArrayRef<BuiltType> replacements) {
956-
return SubstitutionMap::get(sig, replacements, {});
956+
return SubstitutionMap::get(sig, replacements,
957+
LookUpConformanceInSignature(sig.getPointer()));
957958
}
958959

959960
Type ASTBuilder::subst(Type subject, const BuiltSubstitutionMap &Subs) const {

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,9 +1192,13 @@ namespace {
11921192
printCommon(PD, "protocol", label);
11931193

11941194
if (PD->isRequirementSignatureComputed()) {
1195-
auto requirements = PD->getRequirementSignatureAsGenericSignature();
1196-
std::string reqSigStr = requirements->getAsString();
1197-
printFieldQuoted(reqSigStr, "requirement_signature");
1195+
auto reqSig = PD->getRequirementSignature();
1196+
1197+
std::string reqSigStr;
1198+
llvm::raw_string_ostream out(reqSigStr);
1199+
reqSig.print(PD, out);
1200+
1201+
printFieldQuoted(out.str(), "requirement_signature");
11981202
} else {
11991203
printFlag("uncomputed_requirement_signature");
12001204
}

lib/AST/ASTMangler.cpp

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3005,35 +3005,29 @@ void ASTMangler::appendTypeListElement(Identifier name, Type elementType,
30053005
appendOperator("d");
30063006
}
30073007

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-
30233008
bool ASTMangler::appendGenericSignature(GenericSignature sig,
30243009
GenericSignature contextSig) {
30253010
auto canSig = sig.getCanonicalSignature();
30263011

3012+
// FIXME: We just ignore invertible requirements for now.
3013+
SmallVector<Requirement, 2> reqs;
3014+
SmallVector<InverseRequirement, 2> inverseReqs;
3015+
canSig->getRequirementsWithInverses(reqs, inverseReqs);
3016+
30273017
unsigned initialParamDepth;
30283018
ArrayRef<CanTypeWrapper<GenericTypeParamType>> genericParams;
3029-
SmallVector<Requirement, 4> requirements;
30303019
if (contextSig) {
30313020
// If the signature is the same as the context signature, there's nothing
30323021
// to do.
30333022
if (contextSig.getCanonicalSignature() == canSig) {
30343023
return false;
30353024
}
30363025

3026+
// FIXME: We just ignore invertible requirements for now.
3027+
SmallVector<Requirement, 2> contextReqs;
3028+
SmallVector<InverseRequirement, 2> contextInverseReqs;
3029+
contextSig->getRequirementsWithInverses(contextReqs, contextInverseReqs);
3030+
30373031
// The signature depth starts above the depth of the context signature.
30383032
if (!contextSig.getGenericParams().empty()) {
30393033
initialParamDepth = contextSig.getGenericParams().back()->getDepth() + 1;
@@ -3053,26 +3047,25 @@ bool ASTMangler::appendGenericSignature(GenericSignature sig,
30533047
// have a special-case mangling for that.
30543048
if (genericParams.empty() &&
30553049
contextSig.getGenericParams().size() == 1 &&
3056-
contextSig.getRequirements().empty()) {
3050+
contextReqs.empty()) {
30573051
initialParamDepth = 0;
30583052
genericParams = canSig.getGenericParams();
3059-
withoutInvertibleRequirements(canSig.getRequirements(), requirements);
30603053
} else {
3061-
withoutInvertibleRequirements(
3062-
canSig.requirementsNotSatisfiedBy(contextSig), requirements);
3054+
llvm::erase_if(reqs, [&](Requirement req) {
3055+
return contextSig->isRequirementSatisfied(req);
3056+
});
30633057
}
30643058
} else {
30653059
// Use the complete canonical signature.
30663060
initialParamDepth = 0;
30673061
genericParams = canSig.getGenericParams();
3068-
withoutInvertibleRequirements(canSig.getRequirements(), requirements);
30693062
}
30703063

3071-
if (genericParams.empty() && requirements.empty())
3064+
if (genericParams.empty() && reqs.empty())
30723065
return false;
30733066

30743067
appendGenericSignatureParts(sig, genericParams,
3075-
initialParamDepth, requirements);
3068+
initialParamDepth, reqs);
30763069
return true;
30773070
}
30783071

0 commit comments

Comments
 (0)