Skip to content

Commit 8314a55

Browse files
authored
Merge pull request #13332 from DougGregor/where-clause-ref-typealias-in-protocol-4.1
[4.1] [Name lookup] Allow where clauses to find typealiases declared in a protocol.
2 parents 65b4172 + b90ce71 commit 8314a55

File tree

5 files changed

+58
-25
lines changed

5 files changed

+58
-25
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,10 +1686,11 @@ ERROR(requires_not_suitable_archetype,none,
16861686
"type %0 in conformance requirement does not refer to a "
16871687
"generic parameter or associated type",
16881688
(TypeLoc))
1689-
ERROR(requires_no_same_type_archetype,none,
1690-
"neither type in same-type refers to a generic parameter or "
1691-
"associated type",
1692-
())
1689+
WARNING(requires_no_same_type_archetype,none,
1690+
"neither type in same-type constraint (%0 or %1) refers to a "
1691+
"generic parameter or associated type",
1692+
(Type, Type))
1693+
16931694
ERROR(requires_generic_params_made_equal,none,
16941695
"same-type requirement makes generic parameters %0 and %1 equivalent",
16951696
(Type, Type))

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4285,21 +4285,16 @@ ConstraintResult GenericSignatureBuilder::addRequirement(
42854285
}
42864286

42874287
case RequirementReprKind::SameType: {
4288-
// Require that at least one side of the requirement contain a type
4289-
// parameter.
4288+
// Warn if neither side of the requirement contains a type parameter.
42904289
if (!Req->getFirstType()->hasTypeParameter() &&
4291-
!Req->getSecondType()->hasTypeParameter()) {
4292-
if (!Req->getFirstType()->hasError() &&
4293-
!Req->getSecondType()->hasError()) {
4294-
Impl->HadAnyError = true;
4295-
4296-
Diags.diagnose(Req->getEqualLoc(),
4297-
diag::requires_no_same_type_archetype)
4298-
.highlight(Req->getFirstTypeLoc().getSourceRange())
4299-
.highlight(Req->getSecondTypeLoc().getSourceRange());
4300-
}
4301-
4302-
return ConstraintResult::Concrete;
4290+
!Req->getSecondType()->hasTypeParameter() &&
4291+
!Req->getFirstType()->hasError() &&
4292+
!Req->getSecondType()->hasError()) {
4293+
Diags.diagnose(Req->getEqualLoc(),
4294+
diag::requires_no_same_type_archetype,
4295+
Req->getFirstType(), Req->getSecondType())
4296+
.highlight(Req->getFirstTypeLoc().getSourceRange())
4297+
.highlight(Req->getSecondTypeLoc().getSourceRange());
43034298
}
43044299

43054300
auto firstType = subst(Req->getFirstType());

lib/Sema/TypeCheckType.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,8 @@ resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
10241024
}
10251025

10261026
// If the lookup occurs from within a trailing 'where' clause of
1027-
// a constrained extension, also look for associated types.
1027+
// a constrained extension, also look for associated types and typealiases
1028+
// in the protocol.
10281029
if (genericParams->hasTrailingWhereClause() &&
10291030
comp->getIdLoc().isValid() &&
10301031
TC.Context.SourceMgr.rangeContainsTokenLoc(
@@ -1047,12 +1048,15 @@ resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
10471048
decls)) {
10481049
for (const auto decl : decls) {
10491050
// FIXME: Better ambiguity handling.
1050-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
1051-
comp->setValue(assocType, DC);
1052-
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
1053-
diagnoseErrors, resolver,
1054-
unsatisfiedDependency);
1055-
}
1051+
auto typeDecl = dyn_cast<TypeDecl>(decl);
1052+
if (!typeDecl) continue;
1053+
1054+
if (!isa<ProtocolDecl>(typeDecl->getDeclContext())) continue;
1055+
1056+
comp->setValue(typeDecl, DC);
1057+
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
1058+
diagnoseErrors, resolver,
1059+
unsatisfiedDependency);
10561060
}
10571061
}
10581062
}

test/Generics/same_type_constraints.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,10 @@ struct StructTakingP1<T: P1> { }
371371
func resultTypeSuppress<T: P1>() -> StructTakingP1<T> {
372372
return StructTakingP1()
373373
}
374+
375+
// Check directly-concrete same-type constraints
376+
typealias NotAnInt = Double
377+
378+
extension X11 where NotAnInt == Int { }
379+
// expected-warning@-1{{neither type in same-type constraint ('NotAnInt' (aka 'Double') or 'Int') refers to a generic parameter or associated type}}
380+
// expected-error@-2{{generic signature requires types 'NotAnInt' (aka 'Double') and 'Int' to be the same}}

test/decl/typealias/protocol.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,29 @@ protocol P9 {
252252

253253
func testT9a<T: P9, U>(_: T, _: U) where T.A == U { }
254254
func testT9b<T: P9>(_: T) where T.A == Float { } // expected-error{{'T.A' cannot be equal to both 'Float' and 'P9.A' (aka 'Int')}}
255+
256+
257+
struct X<T> { }
258+
259+
protocol P10 {
260+
associatedtype A
261+
typealias T = Int
262+
263+
@available(*, deprecated, message: "just use Int, silly")
264+
typealias V = Int
265+
}
266+
267+
extension P10 {
268+
typealias U = Float
269+
}
270+
271+
extension P10 where T == Int { } // expected-warning{{neither type in same-type constraint ('P10.T' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
272+
273+
extension P10 where A == X<T> { }
274+
275+
extension P10 where A == X<U> { } // expected-error{{use of undeclared type 'U'}}
276+
277+
extension P10 where A == X<Self.U> { }
278+
279+
extension P10 where V == Int { } // expected-warning 3{{'V' is deprecated: just use Int, silly}}
280+
// expected-warning@-1{{neither type in same-type constraint ('P10.V' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}

0 commit comments

Comments
 (0)