Skip to content

Commit 57d74fa

Browse files
authored
Merge pull request #16806 from DougGregor/gsb-and-submap
2 parents 147e6e9 + b0cc3ff commit 57d74fa

File tree

3 files changed

+51
-22
lines changed

3 files changed

+51
-22
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6988,17 +6988,24 @@ void GenericSignatureBuilder::checkSameTypeConstraints(
69886988
void GenericSignatureBuilder::checkConcreteTypeConstraints(
69896989
TypeArrayView<GenericTypeParamType> genericParams,
69906990
EquivalenceClass *equivClass) {
6991+
// Resolve any thus-far-unresolved dependent types.
6992+
Type resolvedConcreteType =
6993+
resolveDependentMemberTypes(*this, equivClass->concreteType);
6994+
69916995
checkConstraintList<Type>(
69926996
genericParams, equivClass->concreteTypeConstraints,
69936997
[&](const ConcreteConstraint &constraint) {
6994-
return constraint.value->isEqual(equivClass->concreteType);
6998+
if (constraint.value->isEqual(resolvedConcreteType))
6999+
return true;
7000+
7001+
auto resolvedType =
7002+
resolveDependentMemberTypes(*this, constraint.value);
7003+
return resolvedType->isEqual(resolvedConcreteType);
69957004
},
69967005
[&](const Constraint<Type> &constraint) {
69977006
Type concreteType = constraint.value;
69987007

69997008
// If the concrete type is equivalent, the constraint is redundant.
7000-
// FIXME: Should check this constraint after substituting in the
7001-
// archetype anchors for each dependent type.
70027009
if (concreteType->isEqual(equivClass->concreteType))
70037010
return ConstraintRelation::Redundant;
70047011

@@ -7013,33 +7020,28 @@ void GenericSignatureBuilder::checkConcreteTypeConstraints(
70137020
diag::redundant_same_type_to_concrete,
70147021
diag::same_type_redundancy_here);
70157022

7016-
// Resolve any thus-far-unresolved dependent types.
7017-
equivClass->concreteType =
7018-
resolveDependentMemberTypes(*this, equivClass->concreteType);
7023+
equivClass->concreteType = resolvedConcreteType;
70197024
}
70207025

70217026
void GenericSignatureBuilder::checkSuperclassConstraints(
70227027
TypeArrayView<GenericTypeParamType> genericParams,
70237028
EquivalenceClass *equivClass) {
70247029
assert(equivClass->superclass && "No superclass constraint?");
70257030

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

70387035
auto representativeConstraint =
70397036
checkConstraintList<Type>(
70407037
genericParams, equivClass->superclassConstraints,
70417038
[&](const ConcreteConstraint &constraint) {
7042-
return constraint.value->isEqual(equivClass->superclass);
7039+
if (constraint.value->isEqual(resolvedSuperclass))
7040+
return true;
7041+
7042+
Type resolvedType =
7043+
resolveDependentMemberTypes(*this, constraint.value);
7044+
return resolvedType->isEqual(equivClass->superclass);
70437045
},
70447046
[&](const Constraint<Type> &constraint) {
70457047
Type superclass = constraint.value;
@@ -7056,15 +7058,16 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
70567058
diag::superclass_redundancy_here);
70577059

70587060
// Resolve any this-far-unresolved dependent types.
7059-
equivClass->superclass =
7060-
resolveDependentMemberTypes(*this, equivClass->superclass);
7061+
equivClass->superclass = resolvedSuperclass;
70617062

70627063
// If we have a concrete type, check it.
70637064
// FIXME: Substitute into the concrete type.
70647065
if (equivClass->concreteType) {
7066+
Type resolvedConcreteType =
7067+
resolveDependentMemberTypes(*this, equivClass->concreteType);
70657068
auto existing = equivClass->findAnyConcreteConstraintAsWritten();
70667069
// Make sure the concrete type fulfills the superclass requirement.
7067-
if (!equivClass->superclass->isExactSuperclassOf(equivClass->concreteType)){
7070+
if (!equivClass->superclass->isExactSuperclassOf(resolvedConcreteType)){
70687071
Impl->HadAnyError = true;
70697072
if (existing) {
70707073
Diags.diagnose(existing->source->getLoc(), diag::type_does_not_inherit,
@@ -7084,7 +7087,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
70847087
diag::type_does_not_inherit,
70857088
representativeConstraint.getSubjectDependentType(
70867089
genericParams),
7087-
equivClass->concreteType, equivClass->superclass);
7090+
resolvedConcreteType, equivClass->superclass);
70887091
}
70897092
} else if (representativeConstraint.source->shouldDiagnoseRedundancy(true)
70907093
&& existing &&

lib/AST/SubstitutionMap.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
275275

276276
// Substitute into the replacement type.
277277
replacementType = concreteType.subst(*this);
278+
279+
// If the generic signature is canonical, canonicalize the replacement type.
280+
if (getGenericSignature()->isCanonical())
281+
replacementType = replacementType->getCanonicalType();
282+
278283
return replacementType;
279284
}
280285

@@ -290,6 +295,11 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const {
290295
replacementType = ErrorType::get(type);
291296

292297
replacementType = lookupSubstitution(cast<SubstitutableType>(canonicalType));
298+
299+
// If the generic signature is canonical, canonicalize the replacement type.
300+
if (getGenericSignature()->isCanonical())
301+
replacementType = replacementType->getCanonicalType();
302+
293303
return replacementType;
294304
}
295305

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)