Skip to content

Commit 0238a50

Browse files
committed
[Name lookup] Allow where clauses to find typealiases declared in a protocol.
Within the where clause of (e.g.) an extension, unqualified name lookup is permitted to find associated types. Extend this to also include finding typealiases declared within the protocol itself. This is service of the IndexDistance change (SE-0191), and fixes rdar://problem/35490504. (cherry picked from commit 5431400)
1 parent 65b4172 commit 0238a50

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4131,6 +4131,19 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirement(
41314131
diagnoseMismatch);
41324132
}
41334133

4134+
/// Determine whether the given type has a type parameter or directly
4135+
/// references a deprecated typealias.
4136+
static bool hasTypeParameterOrIsDeprecatedTypealias(Type type){
4137+
if (type->hasTypeParameter()) return true;
4138+
4139+
if (auto typeAlias = dyn_cast<NameAliasType>(type.getPointer())) {
4140+
return typeAlias->getDecl()->getAttrs().getDeprecated(
4141+
type->getASTContext());
4142+
}
4143+
4144+
return false;
4145+
}
4146+
41344147
ConstraintResult GenericSignatureBuilder::addSameTypeRequirementDirect(
41354148
ResolvedType type1, ResolvedType type2,
41364149
FloatingRequirementSource source,
@@ -4286,9 +4299,9 @@ ConstraintResult GenericSignatureBuilder::addRequirement(
42864299

42874300
case RequirementReprKind::SameType: {
42884301
// Require that at least one side of the requirement contain a type
4289-
// parameter.
4290-
if (!Req->getFirstType()->hasTypeParameter() &&
4291-
!Req->getSecondType()->hasTypeParameter()) {
4302+
// parameter or directly reference a deprecated declaration.
4303+
if (!hasTypeParameterOrIsDeprecatedTypealias(Req->getFirstType()) &&
4304+
!hasTypeParameterOrIsDeprecatedTypealias(Req->getSecondType())) {
42924305
if (!Req->getFirstType()->hasError() &&
42934306
!Req->getSecondType()->hasError()) {
42944307
Impl->HadAnyError = true;

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/decl/typealias/protocol.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,28 @@ 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-error{{neither type in same-type 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}}

0 commit comments

Comments
 (0)