Skip to content

Commit 3b9cb5a

Browse files
committed
[GSB] Drop derived-from-concrete superclass/layout/etc. constraints.
Apply the same logic used for self-derived conformance constraints, where we drop constraints derived from concrete conformances, to the remaining kinds of constraints covered by isSelfDerivedSource().
1 parent a892e89 commit 3b9cb5a

File tree

3 files changed

+73
-23
lines changed

3 files changed

+73
-23
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,8 @@ class GenericSignatureBuilder::RequirementSource final
10021002
/// requirement. Such "self-derived" requirements do not make the original
10031003
/// requirement redundant, because without said original requirement, the
10041004
/// derived requirement ceases to hold.
1005-
bool isSelfDerivedSource(PotentialArchetype *pa) const;
1005+
bool isSelfDerivedSource(PotentialArchetype *pa,
1006+
bool &derivedViaConcrete) const;
10061007

10071008
/// Determine whether a requirement \c pa: proto, when formed from this
10081009
/// requirement source, is dependent on itself.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,10 @@ bool RequirementSource::isDerivedViaConcreteConformance() const {
253253
return false;
254254
}
255255

256-
bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
256+
bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa,
257+
bool &derivedViaConcrete) const {
258+
derivedViaConcrete = false;
259+
257260
// If it's not a derived requirement, it's not self-derived.
258261
if (!isDerivedRequirement()) return false;
259262

@@ -274,10 +277,15 @@ bool RequirementSource::isSelfDerivedSource(PotentialArchetype *pa) const {
274277
case RequirementSource::Parent:
275278
return currentPA->isInSameEquivalenceClassAs(pa);
276279

277-
case RequirementSource::NestedTypeNameMatch:
278-
case RequirementSource::Concrete:
279280
case RequirementSource::ProtocolRequirement:
280281
case RequirementSource::InferredProtocolRequirement:
282+
// Note whether we saw derivation through a concrete type.
283+
if (currentPA->isConcreteType())
284+
derivedViaConcrete = true;
285+
return false;
286+
287+
case RequirementSource::NestedTypeNameMatch:
288+
case RequirementSource::Concrete:
281289
case RequirementSource::Superclass:
282290
return false;
283291
}
@@ -3768,6 +3776,38 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
37683776
/*removeSelfDerived=*/true);
37693777
}
37703778

3779+
namespace {
3780+
/// Remove self-derived sources from the given vector of constraints.
3781+
template<typename T>
3782+
void removeSelfDerived(std::vector<Constraint<T>> &constraints) {
3783+
// Remove self-derived constraints.
3784+
Optional<Constraint<T>> remainingConcrete;
3785+
constraints.erase(
3786+
std::remove_if(constraints.begin(), constraints.end(),
3787+
[&](const Constraint<T> &constraint) {
3788+
bool derivedViaConcrete;
3789+
if (constraint.source->isSelfDerivedSource(
3790+
constraint.archetype, derivedViaConcrete))
3791+
return true;
3792+
3793+
if (!derivedViaConcrete)
3794+
return false;
3795+
3796+
// Drop derived-via-concrete requirements.
3797+
if (!remainingConcrete)
3798+
remainingConcrete = constraint;
3799+
3800+
return true;
3801+
}),
3802+
constraints.end());
3803+
3804+
if (constraints.empty() && remainingConcrete)
3805+
constraints.push_back(*remainingConcrete);
3806+
3807+
assert(!constraints.empty() && "All constraints were self-derived!");
3808+
}
3809+
}
3810+
37713811
template<typename T, typename DiagT>
37723812
Constraint<T> GenericSignatureBuilder::checkConstraintList(
37733813
ArrayRef<GenericTypeParamType *> genericParams,
@@ -3784,15 +3824,7 @@ Constraint<T> GenericSignatureBuilder::checkConstraintList(
37843824
bool removeSelfDerived) {
37853825
assert(!constraints.empty() && "No constraints?");
37863826
if (removeSelfDerived) {
3787-
// Remove self-derived constraints.
3788-
constraints.erase(
3789-
std::remove_if(constraints.begin(), constraints.end(),
3790-
[&](const Constraint<T> &constraint) {
3791-
return constraint.source->isSelfDerivedSource(
3792-
constraint.archetype);
3793-
}),
3794-
constraints.end());
3795-
assert(!constraints.empty() && "All constraints were self-derived!");
3827+
::removeSelfDerived(constraints);
37963828
}
37973829

37983830
// Sort the constraints, so we get a deterministic ordering of diagnostics.
@@ -4132,15 +4164,7 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
41324164
auto &constraints = entry.second;
41334165

41344166
// Remove self-derived constraints.
4135-
assert(!constraints.empty() && "No constraints?");
4136-
constraints.erase(
4137-
std::remove_if(constraints.begin(), constraints.end(),
4138-
[&](const Constraint<PotentialArchetype *> &constraint) {
4139-
return constraint.source->isSelfDerivedSource(
4140-
constraint.archetype);
4141-
}),
4142-
constraints.end());
4143-
assert(!constraints.empty() && "All constraints were self-derived!");
4167+
removeSelfDerived(constraints);
41444168

41454169
// Sort the constraints, so we get a deterministic ordering of diagnostics.
41464170
llvm::array_pod_sort(constraints.begin(), constraints.end());

test/Generics/requirement_inference.swift

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,4 +363,29 @@ protocol P25b {
363363
protocol P25c {
364364
associatedtype A: P24
365365
associatedtype B where A == X<B> // expected-error{{use of undeclared type 'X'}}
366-
}
366+
}
367+
368+
// Similar to the above, but with superclass constraints.
369+
protocol P26 {
370+
associatedtype C: X3
371+
}
372+
373+
struct X26<T: X3> : P26 {
374+
typealias C = T
375+
}
376+
377+
// CHECK-LABEL: .P27a@
378+
// CHECK-NEXT: Requirement signature: <Self where Self.B : X3, Self.A == X26<Self.B>>
379+
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : X3, τ_0_0.A == X26<τ_0_0.B>>
380+
protocol P27a {
381+
associatedtype A: P26 // expected-warning{{redundant conformance constraint 'Self.A': 'P26'}}
382+
associatedtype B where A == X26<B> // expected-note{{conformance constraint 'Self.A': 'P26' implied here}}
383+
}
384+
385+
// CHECK-LABEL: .P27b@
386+
// CHECK-NEXT: Requirement signature: <Self where Self.B : X3, Self.A == X26<Self.B>>
387+
// CHECK-NEXT: Canonical requirement signature: <τ_0_0 where τ_0_0.B : X3, τ_0_0.A == X26<τ_0_0.B>>
388+
protocol P27b {
389+
associatedtype A
390+
associatedtype B where A == X26<B>
391+
}

0 commit comments

Comments
 (0)