Skip to content

Commit b009bf6

Browse files
authored
Merge pull request #22630 from xedin/add-generic-context-to-locator
[ConstraintLocator] Add generic signature to `OpenedGeneric` element
2 parents bd10bbc + 4f0f090 commit b009bf6

File tree

5 files changed

+113
-53
lines changed

5 files changed

+113
-53
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,35 @@ const Requirement &RequirementFailure::getRequirement() const {
9999
// If this is a conditional requirement failure we need to
100100
// fetch conformance from constraint system associated with
101101
// type requirement this conditional conformance belongs to.
102-
if (isConditional()) {
103-
auto conformanceRef = getConformanceRef();
104-
return conformanceRef.getConditionalRequirements()[getRequirementIndex()];
105-
}
106-
107-
return getGenericContext()->getGenericRequirements()[getRequirementIndex()];
102+
auto requirements = isConditional()
103+
? Conformance->getConditionalRequirements()
104+
: Signature->getRequirements();
105+
return requirements[getRequirementIndex()];
108106
}
109107

110-
ProtocolConformanceRef RequirementFailure::getConformanceRef() const {
111-
assert(isConditional());
112-
108+
ProtocolConformance *RequirementFailure::getConformanceForConditionalReq(
109+
ConstraintLocator *locator) {
113110
auto &cs = getConstraintSystem();
114-
auto *locator = getLocator();
111+
auto path = locator->getPath();
112+
assert(!path.empty());
113+
114+
if (!path.back().isConditionalRequirement()) {
115+
assert(path.back().isTypeParameterRequirement());
116+
return nullptr;
117+
}
115118

116-
auto *typeReqLoc =
117-
cs.getConstraintLocator(getRawAnchor(), locator->getPath().drop_back(),
118-
/*summaryFlags=*/0);
119+
auto *typeReqLoc = cs.getConstraintLocator(getRawAnchor(), path.drop_back(),
120+
/*summaryFlags=*/0);
119121

120-
auto conformance = llvm::find_if(
122+
auto result = llvm::find_if(
121123
cs.CheckedConformances,
122124
[&](const std::pair<ConstraintLocator *, ProtocolConformanceRef>
123125
&conformance) { return conformance.first == typeReqLoc; });
124-
assert(conformance != cs.CheckedConformances.end());
125-
return conformance->second;
126+
assert(result != cs.CheckedConformances.end());
127+
128+
auto conformance = result->second;
129+
assert(conformance.isConcrete());
130+
return conformance.getConcrete();
126131
}
127132

128133
ValueDecl *RequirementFailure::getDeclRef() const {
@@ -169,13 +174,25 @@ ValueDecl *RequirementFailure::getDeclRef() const {
169174
return ownerType->getAnyGeneric();
170175
}
171176

177+
GenericSignature *RequirementFailure::getSignature(ConstraintLocator *locator) {
178+
if (isConditional())
179+
return Conformance->getGenericSignature();
180+
181+
auto path = locator->getPath();
182+
for (auto iter = path.rbegin(); iter != path.rend(); ++iter) {
183+
const auto &elt = *iter;
184+
if (elt.getKind() == ConstraintLocator::OpenedGeneric)
185+
return elt.getGenericSignature();
186+
}
187+
188+
llvm_unreachable("Type requirement failure should always have signature");
189+
}
190+
172191
const DeclContext *RequirementFailure::getRequirementDC() const {
173192
// In case of conditional requirement failure, we don't
174193
// have to guess where the it comes from.
175-
if (isConditional()) {
176-
auto *conformance = getConformanceRef().getConcrete();
177-
return conformance->getDeclContext();
178-
}
194+
if (isConditional())
195+
return Conformance->getDeclContext();
179196

180197
const auto &req = getRequirement();
181198
auto *DC = AffectedDecl->getDeclContext();
@@ -242,10 +259,9 @@ void RequirementFailure::emitRequirementNote(const Decl *anchor, Type lhs,
242259
auto &req = getRequirement();
243260

244261
if (isConditional()) {
245-
auto *conformance = getConformanceRef().getConcrete();
246262
emitDiagnostic(anchor, diag::requirement_implied_by_conditional_conformance,
247-
resolveType(conformance->getType()),
248-
conformance->getProtocol()->getDeclaredInterfaceType());
263+
resolveType(Conformance->getType()),
264+
Conformance->getProtocol()->getDeclaredInterfaceType());
249265
return;
250266
}
251267

lib/Sema/CSDiagnostics.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,29 @@ class RequirementFailure : public FailureDiagnostic {
166166
using DiagInReference = Diag<DescriptiveDeclKind, DeclName, Type, Type, Type>;
167167
using DiagAsNote = Diag<Type, Type, Type, Type, StringRef>;
168168

169+
/// If this failure associated with one of the conditional requirements,
170+
/// this field would represent conformance where requirement comes from.
171+
const ProtocolConformance *Conformance = nullptr;
172+
173+
/// The source of the requirement, if available. One exception
174+
/// is failure associated with conditional requirement where
175+
/// underlying conformance is specialized.
176+
const GenericSignature *Signature;
177+
169178
const ValueDecl *AffectedDecl;
170179
/// If possible, find application expression associated
171180
/// with current generic requirement failure, that helps
172181
/// to diagnose failures related to arguments.
173182
const ApplyExpr *Apply = nullptr;
174183

175-
/// If this failure associated with one of the conditional requirements.
176-
bool IsConditional = false;
177-
178184
public:
179185
RequirementFailure(ConstraintSystem &cs, Expr *expr, RequirementKind kind,
180186
ConstraintLocator *locator)
181-
: FailureDiagnostic(expr, cs, locator), AffectedDecl(getDeclRef()) {
187+
: FailureDiagnostic(expr, cs, locator),
188+
Conformance(getConformanceForConditionalReq(locator)),
189+
Signature(getSignature(locator)), AffectedDecl(getDeclRef()) {
182190
assert(locator);
191+
assert(isConditional() || Signature);
183192
assert(AffectedDecl);
184193

185194
auto path = locator->getPath();
@@ -190,8 +199,6 @@ class RequirementFailure : public FailureDiagnostic {
190199
last.isConditionalRequirement());
191200
assert(static_cast<RequirementKind>(last.getValue2()) == kind);
192201

193-
IsConditional = last.isConditionalRequirement();
194-
195202
// It's possible sometimes not to have no base expression.
196203
if (!expr)
197204
return;
@@ -227,11 +234,7 @@ class RequirementFailure : public FailureDiagnostic {
227234

228235
protected:
229236
/// Determine whether this is a conditional requirement failure.
230-
bool isConditional() const { return IsConditional; }
231-
232-
/// If this is a failure in condition requirement, retrieve
233-
/// conformance information.
234-
ProtocolConformanceRef getConformanceRef() const;
237+
bool isConditional() const { return bool(Conformance); }
235238

236239
/// Retrieve declaration contextual where current
237240
/// requirement has been introduced.
@@ -268,11 +271,19 @@ class RequirementFailure : public FailureDiagnostic {
268271
/// Retrieve declaration associated with failing generic requirement.
269272
ValueDecl *getDeclRef() const;
270273

274+
/// Retrieve generic signature where this parameter originates from.
275+
GenericSignature *getSignature(ConstraintLocator *locator);
276+
271277
void emitRequirementNote(const Decl *anchor, Type lhs, Type rhs) const;
272278

273279
/// Determine whether given declaration represents a static
274280
/// or instance property/method, excluding operators.
275281
static bool isStaticOrInstanceMember(const ValueDecl *decl);
282+
283+
/// If this is a failure in conditional requirement, retrieve
284+
/// conformance information.
285+
ProtocolConformance *
286+
getConformanceForConditionalReq(ConstraintLocator *locator);
276287
};
277288

278289
/// Diagnostics for failed conformance checks originating from

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,20 +1612,27 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
16121612
if (type1->hasDependentMember() || type2->hasDependentMember())
16131613
return nullptr;
16141614

1615-
auto req = path.back();
1615+
auto reqPath = path.take_back(2);
1616+
auto req = reqPath.back();
16161617

16171618
ConstraintLocator *reqLoc = nullptr;
16181619
if (req.isConditionalRequirement()) {
1619-
// If underlaying conformance requirement has been fixed as
1620-
// we there is no reason to fix up conditional requirements.
1621-
if (cs.hasFixFor(cs.getConstraintLocator(anchor, req)))
1620+
// path is - ... -> open generic -> type req # -> cond req #,
1621+
// to identify type requirement we only need `open generic -> type req #`
1622+
// part, because that's how fixes for type requirements are recorded.
1623+
reqPath = path.drop_back().take_back(2);
1624+
// If underlying conformance requirement has been fixed,
1625+
// then there is no reason to fix up conditional requirements.
1626+
if (cs.hasFixFor(cs.getConstraintLocator(anchor, reqPath,
1627+
/*summaryFlags=*/0)))
16221628
return nullptr;
16231629

16241630
// For conditional requirements we need a full path.
16251631
reqLoc = cs.getConstraintLocator(anchor, path, /*summaryFlags=*/0);
16261632
} else {
16271633
// Build simplified locator which only contains anchor and requirement info.
1628-
reqLoc = cs.getConstraintLocator(anchor, req);
1634+
reqLoc = cs.getConstraintLocator(anchor, reqPath,
1635+
/*summaryFlags=*/0);
16291636
}
16301637

16311638
auto reqKind = static_cast<RequirementKind>(req.getValue2());
@@ -2784,9 +2791,14 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
27842791
path.back().isConditionalRequirement()) {
27852792
ConstraintLocator *reqLoc = nullptr;
27862793
if (path.back().isConditionalRequirement()) {
2794+
// Drop 'conditional requirement' element remainder
2795+
// of the path is going to point to type requirement
2796+
// this conditional comes from.
2797+
auto reqPath = ArrayRef<LocatorPathElt>(path).drop_back();
27872798
// Underlying conformance requirement is itself fixed,
2788-
// this wouldn't lead to right solution.
2789-
if (hasFixFor(getConstraintLocator(anchor, path.back())))
2799+
// this wouldn't lead to a right solution.
2800+
if (hasFixFor(getConstraintLocator(anchor, reqPath.take_back(2),
2801+
/*summaryFlags=*/0)))
27902802
return SolutionKind::Error;
27912803

27922804
// For conditional requirements we need complete path, which includes
@@ -2795,8 +2807,11 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
27952807
} else {
27962808
// Let's strip all of the unnecessary information from locator,
27972809
// diagnostics only care about anchor - to lookup type,
2798-
// and what was the requirement# which is not satisfied.
2799-
reqLoc = getConstraintLocator(anchor, path.back());
2810+
// generic signature where requirement comes from, and
2811+
// what was the requirement# which is not satisfied.
2812+
auto reqPath = ArrayRef<LocatorPathElt>(path).take_back(2);
2813+
reqLoc = getConstraintLocator(anchor, reqPath,
2814+
/*summaryFlags=*/0);
28002815
}
28012816

28022817
auto *fix = MissingConformance::create(*this, type, protocol, reqLoc);

lib/Sema/ConstraintLocator.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ class ConstraintLocator : public llvm::FoldingSetNode {
152152
case AutoclosureResult:
153153
case Requirement:
154154
case Witness:
155-
case OpenedGeneric:
156155
case ImplicitlyUnwrappedDisjunctionChoice:
157156
case DynamicLookupResult:
158157
case ContextualType:
159158
return 0;
160159

160+
case OpenedGeneric:
161161
case GenericArgument:
162162
case NamedTupleElement:
163163
case TupleElement:
@@ -236,6 +236,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
236236
StoredGenericParameter,
237237
StoredRequirement,
238238
StoredWitness,
239+
StoredGenericSignature,
239240
StoredKindAndValue
240241
};
241242

@@ -249,11 +250,11 @@ class ConstraintLocator : public llvm::FoldingSetNode {
249250
/// kind. Use \c encodeStorage and \c decodeStorage to work with this value.
250251
///
251252
/// \note The "storage kind" is stored in the \c storedKind field.
252-
uint64_t storage : 62;
253+
uint64_t storage : 61;
253254

254255
/// The kind of value stored in \c storage. Valid values are those
255256
/// from the StoredKind enum.
256-
uint64_t storedKind : 2;
257+
uint64_t storedKind : 3;
257258

258259
/// Encode a path element kind and a value into the storage format.
259260
static uint64_t encodeStorage(PathElementKind kind, unsigned value) {
@@ -281,6 +282,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
281282
"Path element kind does not require 2 values");
282283
}
283284

285+
PathElement(GenericSignature *sig)
286+
: storage((reinterpret_cast<uintptr_t>(sig) >> 3)),
287+
storedKind(StoredGenericSignature) {}
288+
284289
friend class ConstraintLocator;
285290

286291
public:
@@ -292,7 +297,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
292297
}
293298

294299
PathElement(GenericTypeParamType *type)
295-
: storage((reinterpret_cast<uintptr_t>(type) >> 2)),
300+
: storage((reinterpret_cast<uintptr_t>(type) >> 3)),
296301
storedKind(StoredGenericParameter)
297302
{
298303
static_assert(alignof(GenericTypeParamType) >= 4,
@@ -301,7 +306,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
301306
}
302307

303308
PathElement(PathElementKind kind, ValueDecl *decl)
304-
: storage((reinterpret_cast<uintptr_t>(decl) >> 2)),
309+
: storage((reinterpret_cast<uintptr_t>(decl) >> 3)),
305310
storedKind(kind == Witness ? StoredWitness : StoredRequirement)
306311
{
307312
assert((kind == Witness || kind == Requirement) &&
@@ -339,6 +344,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
339344
return PathElement(KeyPathComponent, position);
340345
}
341346

347+
static PathElement getOpenedGeneric(GenericSignature *sig) {
348+
return PathElement(sig);
349+
}
350+
342351
/// Get a path element for a conditional requirement.
343352
static PathElement
344353
getConditionalRequirementComponent(unsigned index, RequirementKind kind) {
@@ -364,6 +373,9 @@ class ConstraintLocator : public llvm::FoldingSetNode {
364373
case StoredWitness:
365374
return Witness;
366375

376+
case StoredGenericSignature:
377+
return OpenedGeneric;
378+
367379
case StoredKindAndValue:
368380
return decodeStorage(storage).first;
369381
}
@@ -399,22 +411,28 @@ class ConstraintLocator : public llvm::FoldingSetNode {
399411
/// Retrieve the declaration for a witness path element.
400412
ValueDecl *getWitness() const {
401413
assert(getKind() == Witness && "Is not a witness");
402-
return reinterpret_cast<ValueDecl *>(storage << 2);
414+
return reinterpret_cast<ValueDecl *>(storage << 3);
403415
}
404416

405417
/// Retrieve the actual archetype for a generic parameter path
406418
/// element.
407419
GenericTypeParamType *getGenericParameter() const {
408420
assert(getKind() == GenericParameter &&
409421
"Not a generic parameter path element");
410-
return reinterpret_cast<GenericTypeParamType *>(storage << 2);
422+
return reinterpret_cast<GenericTypeParamType *>(storage << 3);
411423
}
412424

413425
/// Retrieve the declaration for a requirement path element.
414426
ValueDecl *getRequirement() const {
415427
assert((static_cast<StoredKind>(storedKind) == StoredRequirement) &&
416428
"Is not a requirement");
417-
return reinterpret_cast<ValueDecl *>(storage << 2);
429+
return reinterpret_cast<ValueDecl *>(storage << 3);
430+
}
431+
432+
GenericSignature *getGenericSignature() const {
433+
assert((static_cast<StoredKind>(storedKind) == StoredGenericSignature) &&
434+
"Is not an opened generic");
435+
return reinterpret_cast<GenericSignature *>(storage << 3);
418436
}
419437

420438
/// Return the summary flags for this particular element.

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ void ConstraintSystem::openGeneric(
10791079
// Remember that any new constraints generated by opening this generic are
10801080
// due to the opening.
10811081
locatorPtr = getConstraintLocator(
1082-
locator.withPathElement(ConstraintLocator::OpenedGeneric));
1082+
locator.withPathElement(LocatorPathElt::getOpenedGeneric(sig)));
10831083

10841084
bindArchetypesFromContext(*this, outerDC, locatorPtr, replacements);
10851085

@@ -1124,7 +1124,7 @@ void ConstraintSystem::openGenericRequirements(
11241124

11251125
addConstraint(
11261126
*openedReq,
1127-
locator.withPathElement(ConstraintLocator::OpenedGeneric)
1127+
locator.withPathElement(LocatorPathElt::getOpenedGeneric(signature))
11281128
.withPathElement(
11291129
LocatorPathElt::getTypeRequirementComponent(pos, kind)));
11301130
}

0 commit comments

Comments
 (0)