Skip to content

Commit 9dd861b

Browse files
authored
Merge pull request #16921 from DougGregor/gsb-canononicalze-concrete-superclass-4.2
2 parents 60dd3fb + b036889 commit 9dd861b

File tree

2 files changed

+41
-22
lines changed

2 files changed

+41
-22
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6981,17 +6981,24 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
69816981
void GenericSignatureBuilder::checkConcreteTypeConstraints(
69826982
TypeArrayView<GenericTypeParamType> genericParams,
69836983
EquivalenceClass *equivClass) {
6984+
// Resolve any thus-far-unresolved dependent types.
6985+
Type resolvedConcreteType =
6986+
resolveDependentMemberTypes(*this, equivClass->concreteType);
6987+
69846988
checkConstraintList<Type>(
69856989
genericParams, equivClass->concreteTypeConstraints,
69866990
[&](const ConcreteConstraint &constraint) {
6987-
return constraint.value->isEqual(equivClass->concreteType);
6991+
if (constraint.value->isEqual(resolvedConcreteType))
6992+
return true;
6993+
6994+
auto resolvedType =
6995+
resolveDependentMemberTypes(*this, constraint.value);
6996+
return resolvedType->isEqual(resolvedConcreteType);
69886997
},
69896998
[&](const Constraint<Type> &constraint) {
69906999
Type concreteType = constraint.value;
69917000

69927001
// If the concrete type is equivalent, the constraint is redundant.
6993-
// FIXME: Should check this constraint after substituting in the
6994-
// archetype anchors for each dependent type.
69957002
if (concreteType->isEqual(equivClass->concreteType))
69967003
return ConstraintRelation::Redundant;
69977004

@@ -7006,33 +7013,28 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
70067013
diag::redundant_same_type_to_concrete,
70077014
diag::same_type_redundancy_here);
70087015

7009-
// Resolve any thus-far-unresolved dependent types.
7010-
equivClass->concreteType =
7011-
resolveDependentMemberTypes(*this, equivClass->concreteType);
7016+
equivClass->concreteType = resolvedConcreteType;
70127017
}
70137018

70147019
void GenericSignatureBuilder::checkSuperclassConstraints(
70157020
TypeArrayView<GenericTypeParamType> genericParams,
70167021
EquivalenceClass *equivClass) {
70177022
assert(equivClass->superclass && "No superclass constraint?");
70187023

7019-
// FIXME: We should be substituting in the canonical type in context so
7020-
// we can resolve superclass requirements, e.g., if you had:
7021-
//
7022-
// class Foo<T>
7023-
// class Bar: Foo<Int>
7024-
//
7025-
// func foo<T, U where U: Bar, U: Foo<T>>(...) { ... }
7026-
//
7027-
// then the second `U: Foo<T>` constraint introduces a `T == Int`
7028-
// constraint, and we will need to perform that substitution for this final
7029-
// check.
7024+
// Resolve any this-far-unresolved dependent types.
7025+
Type resolvedSuperclass =
7026+
resolveDependentMemberTypes(*this, equivClass->superclass);
70307027

70317028
auto representativeConstraint =
70327029
checkConstraintList<Type>(
70337030
genericParams, equivClass->superclassConstraints,
70347031
[&](const ConcreteConstraint &constraint) {
7035-
return constraint.value->isEqual(equivClass->superclass);
7032+
if (constraint.value->isEqual(resolvedSuperclass))
7033+
return true;
7034+
7035+
Type resolvedType =
7036+
resolveDependentMemberTypes(*this, constraint.value);
7037+
return resolvedType->isEqual(equivClass->superclass);
70367038
},
70377039
[&](const Constraint<Type> &constraint) {
70387040
Type superclass = constraint.value;
@@ -7049,15 +7051,16 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
70497051
diag::superclass_redundancy_here);
70507052

70517053
// Resolve any this-far-unresolved dependent types.
7052-
equivClass->superclass =
7053-
resolveDependentMemberTypes(*this, equivClass->superclass);
7054+
equivClass->superclass = resolvedSuperclass;
70547055

70557056
// If we have a concrete type, check it.
70567057
// FIXME: Substitute into the concrete type.
70577058
if (equivClass->concreteType) {
7059+
Type resolvedConcreteType =
7060+
resolveDependentMemberTypes(*this, equivClass->concreteType);
70587061
auto existing = equivClass->findAnyConcreteConstraintAsWritten();
70597062
// Make sure the concrete type fulfills the superclass requirement.
7060-
if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType)){
7063+
if (!equivClass->superclass->isExactSuperclassOf(resolvedConcreteType)){
70617064
Impl->HadAnyError = true;
70627065
if (existing) {
70637066
Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
@@ -7077,7 +7080,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
70777080
diag::type_does_not_inherit,
70787081
representativeConstraint.getSubjectDependentType(
70797082
genericParams),
7080-
equivClass->concreteType, equivClass->superclass);
7083+
resolvedConcreteType, equivClass->superclass);
70817084
}
70827085
} else if (representativeConstraint.source->shouldDiagnoseRedundancy(true)
70837086
&& existing &&

test/Generics/same_type_constraints.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,19 @@ typealias NotAnInt = Double
378378
extension X11 where NotAnInt == Int { }
379379
// expected-warning@-1{{neither type in same-type constraint ('NotAnInt' (aka 'Double') or 'Int') refers to a generic parameter or associated type}}
380380
// expected-error@-2{{generic signature requires types 'NotAnInt' (aka 'Double') and 'Int' to be the same}}
381+
382+
383+
struct X12<T> { }
384+
385+
protocol P12 {
386+
associatedtype A
387+
associatedtype B
388+
}
389+
390+
func testP12a<T: P12>(_: T) where T.A == X12<Int>, T.A == X12<T.B>, T.B == Int { }
391+
// expected-warning@-1{{redundant same-type constraint 'T.B' == 'Int'}}
392+
// expected-note@-2{{same-type constraint 'T.B' == 'Int' written here}}
393+
394+
func testP12b<T: P12>(_: T) where T.B == Int, T.A == X12<T.B>, X12<T.B> == T.A { }
395+
// expected-warning@-1{{redundant same-type constraint 'T.A' == 'X12<Int>'}}
396+
// expected-note@-2{{same-type constraint 'T.A' == 'X12<Int>' written here}}

0 commit comments

Comments
 (0)