Skip to content

Commit 01965d2

Browse files
authored
Merge pull request #40559 from slavapestov/typealias-in-protocol-fixes
Don't resolve protocol typealiases as DependentMemberTypes in Structural mode
2 parents 536b036 + 637bcf8 commit 01965d2

File tree

7 files changed

+73
-145
lines changed

7 files changed

+73
-145
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3998,8 +3998,16 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
39983998
ProtocolDecl *proto,
39993999
const RequirementSource *source,
40004000
bool onlySameTypeConstraints) {
4001-
auto protocolSubMap = SubstitutionMap::getProtocolSubstitutions(
4002-
proto, selfType.getDependentType(*this), ProtocolConformanceRef(proto));
4001+
auto selfTy = selfType.getDependentType(*this);
4002+
4003+
auto subst = [&](Requirement req) -> Optional<Requirement> {
4004+
return req.subst(
4005+
[&](SubstitutableType *t) -> Type {
4006+
assert(isa<GenericTypeParamType>(t));
4007+
return selfTy;
4008+
},
4009+
MakeAbstractConformanceForGenericType());
4010+
};
40034011

40044012
auto result = ConstraintResult::Resolved;
40054013

@@ -4015,7 +4023,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
40154023
if (onlySameTypeConstraints && req.getKind() != RequirementKind::SameType)
40164024
continue;
40174025

4018-
auto substReq = req.subst(protocolSubMap);
4026+
auto substReq = subst(req);
40194027
auto reqResult = substReq
40204028
? addRequirement(*substReq, innerSource, nullptr)
40214029
: ConstraintResult::Conflicting;
@@ -4045,8 +4053,9 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
40454053

40464054
auto innerSource = FloatingRequirementSource::viaProtocolRequirement(
40474055
source, proto, reqRepr->getSeparatorLoc(), /*inferred=*/false);
4048-
addRequirement(req, reqRepr, innerSource,
4049-
&protocolSubMap, nullptr);
4056+
4057+
if (auto substReq = subst(req))
4058+
addRequirement(*substReq, reqRepr, innerSource, nullptr);
40504059
return false;
40514060
});
40524061

@@ -4159,7 +4168,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
41594168
source, proto, SourceLoc(), /*inferred=*/true);
41604169

41614170
auto rawReq = Requirement(RequirementKind::SameType, firstType, secondType);
4162-
if (auto req = rawReq.subst(protocolSubMap))
4171+
if (auto req = subst(rawReq))
41634172
addRequirement(*req, inferredSameTypeSource, proto->getParentModule());
41644173
};
41654174

@@ -4189,8 +4198,10 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
41894198

41904199
auto innerSource = FloatingRequirementSource::viaProtocolRequirement(
41914200
source, proto, reqRepr->getSeparatorLoc(), /*inferred=*/false);
4192-
addRequirement(req, reqRepr, innerSource, &protocolSubMap,
4193-
/*inferForModule=*/nullptr);
4201+
if (auto substReq = subst(req)) {
4202+
addRequirement(*substReq, reqRepr, innerSource,
4203+
/*inferForModule=*/nullptr);
4204+
}
41944205
return false;
41954206
});
41964207

@@ -5171,28 +5182,19 @@ ConstraintResult
51715182
GenericSignatureBuilder::addRequirement(const Requirement &req,
51725183
FloatingRequirementSource source,
51735184
ModuleDecl *inferForModule) {
5174-
return addRequirement(req, nullptr, source, nullptr, inferForModule);
5185+
return addRequirement(req, nullptr, source, inferForModule);
51755186
}
51765187

51775188
ConstraintResult
51785189
GenericSignatureBuilder::addRequirement(const Requirement &req,
51795190
const RequirementRepr *reqRepr,
51805191
FloatingRequirementSource source,
5181-
const SubstitutionMap *subMap,
51825192
ModuleDecl *inferForModule) {
5183-
// Local substitution for types in the requirement.
5184-
auto subst = [&](Type t) {
5185-
if (subMap)
5186-
return t.subst(*subMap);
5187-
5188-
return t;
5189-
};
5190-
5191-
auto firstType = subst(req.getFirstType());
5193+
auto firstType = req.getFirstType();
51925194
switch (req.getKind()) {
51935195
case RequirementKind::Superclass:
51945196
case RequirementKind::Conformance: {
5195-
auto secondType = subst(req.getSecondType());
5197+
auto secondType = req.getSecondType();
51965198

51975199
if (inferForModule) {
51985200
inferRequirements(*inferForModule, firstType,
@@ -5220,7 +5222,7 @@ GenericSignatureBuilder::addRequirement(const Requirement &req,
52205222
}
52215223

52225224
case RequirementKind::SameType: {
5223-
auto secondType = subst(req.getSecondType());
5225+
auto secondType = req.getSecondType();
52245226

52255227
if (inferForModule) {
52265228
inferRequirements(*inferForModule, firstType,
@@ -8567,8 +8569,8 @@ InferredGenericSignatureRequest::evaluate(
85678569
}
85688570
}
85698571

8570-
builder.addRequirement(req, reqRepr, source, nullptr,
8571-
lookupDC->getParentModule());
8572+
builder.addRequirement(req, reqRepr, source,
8573+
lookupDC->getParentModule());
85728574
return false;
85738575
};
85748576

lib/AST/GenericSignatureBuilder.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@ class GenericSignatureBuilder {
571571
ConstraintResult addRequirement(const Requirement &req,
572572
const RequirementRepr *reqRepr,
573573
FloatingRequirementSource source,
574-
const SubstitutionMap *subMap,
575574
ModuleDecl *inferForModule);
576575

577576
/// Add all of a generic signature's parameters and requirements.

lib/Sema/TypeCheckType.cpp

Lines changed: 30 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -220,50 +220,6 @@ Type TypeResolution::resolveDependentMemberType(
220220
baseTy);
221221
}
222222

223-
Type TypeResolution::resolveSelfAssociatedType(Type baseTy,
224-
DeclContext *DC,
225-
Identifier name) const {
226-
switch (stage) {
227-
case TypeResolutionStage::Structural:
228-
return DependentMemberType::get(baseTy, name);
229-
230-
case TypeResolutionStage::Interface:
231-
// Handled below.
232-
break;
233-
}
234-
235-
assert(stage == TypeResolutionStage::Interface);
236-
auto genericSig = getGenericSignature();
237-
if (!genericSig)
238-
return ErrorType::get(baseTy);
239-
240-
// Look for a nested type with the given name.
241-
auto nestedType = genericSig->lookupNestedType(baseTy, name);
242-
assert(nestedType);
243-
244-
// If the nested type has been resolved to an associated type, use it.
245-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(nestedType)) {
246-
return DependentMemberType::get(baseTy, assocType);
247-
}
248-
249-
if (nestedType->getDeclContext()->getSelfClassDecl()) {
250-
// We found a member of a class from a protocol or protocol
251-
// extension.
252-
//
253-
// Get the superclass of the 'Self' type parameter.
254-
if (auto concreteTy = genericSig->getConcreteType(baseTy))
255-
baseTy = concreteTy;
256-
else {
257-
baseTy = genericSig->getSuperclassBound(baseTy);
258-
assert(baseTy);
259-
}
260-
assert(baseTy);
261-
}
262-
263-
return TypeChecker::substMemberTypeWithBase(DC->getParentModule(), nestedType,
264-
baseTy);
265-
}
266-
267223
bool TypeResolution::areSameType(Type type1, Type type2) const {
268224
if (type1->isEqual(type2))
269225
return true;
@@ -450,23 +406,14 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl,
450406

451407
if (selfType->is<GenericTypeParamType>()) {
452408
if (typeDecl->getDeclContext()->getSelfProtocolDecl()) {
453-
if (isa<AssociatedTypeDecl>(typeDecl) ||
454-
(isa<TypeAliasDecl>(typeDecl) &&
455-
!cast<TypeAliasDecl>(typeDecl)->isGeneric())) {
456-
// FIXME: We should use this lookup method for the Interface
457-
// stage too, but right now that causes problems with
458-
// Sequence.SubSequence vs Collection.SubSequence; the former
459-
// is more canonical, but if we return that instead of the
460-
// latter, we infer the wrong associated type in some cases,
461-
// because we use the Sequence.SubSequence default instead of
462-
// the Collection.SubSequence default, even when the conforming
463-
// type wants to conform to Collection.
464-
if (getStage() == TypeResolutionStage::Structural) {
465-
return resolveSelfAssociatedType(selfType, foundDC,
466-
typeDecl->getName());
467-
} else if (auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl)) {
468-
typeDecl = assocType->getAssociatedTypeAnchor();
469-
}
409+
auto *aliasDecl = dyn_cast<TypeAliasDecl>(typeDecl);
410+
if (getStage() == TypeResolutionStage::Structural &&
411+
aliasDecl && !aliasDecl->isGeneric()) {
412+
return aliasDecl->getStructuralType();
413+
}
414+
415+
if (auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl)) {
416+
typeDecl = assocType->getAssociatedTypeAnchor();
470417
}
471418
}
472419

@@ -543,10 +490,6 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
543490
noteLoc = loc;
544491
}
545492

546-
if (contextSig) {
547-
parentTy = contextSig.getGenericEnvironment()->mapTypeIntoContext(parentTy);
548-
}
549-
550493
const auto subMap = parentTy->getContextSubstitutions(decl->getDeclContext());
551494
const auto genericSig = decl->getGenericSignature();
552495

@@ -556,7 +499,16 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
556499
decl->getDeclaredInterfaceType(),
557500
genericSig.getGenericParams(),
558501
genericSig.getRequirements(),
559-
QueryTypeSubstitutionMap{subMap});
502+
[&](SubstitutableType *type) -> Type {
503+
auto result = QueryTypeSubstitutionMap{subMap}(type);
504+
if (result->hasTypeParameter()) {
505+
if (contextSig) {
506+
auto *genericEnv = contextSig.getGenericEnvironment();
507+
return genericEnv->mapTypeIntoContext(result);
508+
}
509+
}
510+
return result;
511+
});
560512

561513
switch (result) {
562514
case RequirementCheckResult::Failure:
@@ -845,15 +797,6 @@ Type TypeResolution::applyUnboundGenericArguments(
845797
// Check the generic arguments against the requirements of the declaration's
846798
// generic signature.
847799

848-
// First, map substitutions into context.
849-
TypeSubstitutionMap contextualSubs = subs;
850-
if (const auto contextSig = getGenericSignature()) {
851-
auto *genericEnv = contextSig.getGenericEnvironment();
852-
for (auto &pair : contextualSubs) {
853-
pair.second = genericEnv->mapTypeIntoContext(pair.second);
854-
}
855-
}
856-
857800
SourceLoc noteLoc = decl->getLoc();
858801
if (noteLoc.isInvalid())
859802
noteLoc = loc;
@@ -862,7 +805,16 @@ Type TypeResolution::applyUnboundGenericArguments(
862805
module, loc, noteLoc,
863806
UnboundGenericType::get(decl, parentTy, getASTContext()),
864807
genericSig.getGenericParams(), genericSig.getRequirements(),
865-
QueryTypeSubstitutionMap{contextualSubs});
808+
[&](SubstitutableType *type) -> Type {
809+
auto result = QueryTypeSubstitutionMap{subs}(type);
810+
if (result->hasTypeParameter()) {
811+
if (const auto contextSig = getGenericSignature()) {
812+
auto *genericEnv = contextSig.getGenericEnvironment();
813+
return genericEnv->mapTypeIntoContext(result);
814+
}
815+
}
816+
return result;
817+
});
866818

867819
switch (result) {
868820
case RequirementCheckResult::Failure:
@@ -2478,14 +2430,7 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
24782430
// context, and then set isNoEscape if @escaping is not present.
24792431
if (!ty) ty = resolveType(repr, instanceOptions);
24802432
if (!ty || ty->hasError()) return ty;
2481-
2482-
// Type aliases inside protocols are not yet resolved in the structural
2483-
// stage of type resolution
2484-
if (ty->is<DependentMemberType>() &&
2485-
resolution.getStage() == TypeResolutionStage::Structural) {
2486-
return ty;
2487-
}
2488-
2433+
24892434
// Handle @escaping
24902435
if (ty->is<FunctionType>()) {
24912436
if (attrs.has(TAK_escaping)) {
@@ -3463,7 +3408,7 @@ NeverNullType TypeResolver::resolveArrayType(ArrayTypeRepr *repr,
34633408
return ErrorType::get(getASTContext());
34643409
}
34653410

3466-
ASTContext &ctx = baseTy->getASTContext();
3411+
ASTContext &ctx = getASTContext();
34673412
// If the standard library isn't loaded, we ought to let the user know
34683413
// something has gone terribly wrong, since the rest of the compiler is going
34693414
// to assume it can canonicalize [T] to Array<T>.

lib/Sema/TypeCheckType.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,11 +452,6 @@ class TypeResolution {
452452
SourceRange baseRange,
453453
ComponentIdentTypeRepr *ref) const;
454454

455-
/// Resolve an unqualified reference to an associated type or type alias
456-
/// in a protocol.
457-
Type resolveSelfAssociatedType(Type baseTy, DeclContext *DC,
458-
Identifier name) const;
459-
460455
/// Determine whether the given two types are equivalent within this
461456
/// type resolution context.
462457
bool areSameType(Type type1, Type type2) const;
Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,27 @@
11
// RUN: %target-typecheck-verify-swift
22

3-
// Reference to associated type from 'where' clause should not be
3+
// References to associated type from 'where' clause should be
44
// ambiguous when there's a typealias with the same name in another
5-
// protocol.
6-
//
7-
// FIXME: The semantics here are still really iffy. There's also a
8-
// case to be made that type aliases in protocol extensions should
9-
// only act as defaults and not as same-type constraints. However,
10-
// if we decide to go down that route, it's important that *both*
11-
// the unqualified (T) and qualified (Self.T) lookups behave the
12-
// same.
5+
// unrelated protocol.
6+
137
protocol P1 {
14-
typealias T = Int // expected-note {{found this candidate}}
8+
typealias T = Int // expected-note 3{{found this candidate}}
159
}
1610

1711
protocol P2 {
18-
associatedtype T // expected-note {{found this candidate}}
12+
associatedtype T // expected-note 3{{found this candidate}}
1913
}
2014

21-
// FIXME: This extension's generic signature is still minimized differently from
22-
// the next one. We need to decide if 'T == Int' is a redundant requirement or
23-
// not.
24-
extension P1 where Self : P2, T == Int {
25-
func takeT1(_: T) {}
26-
func takeT2(_: Self.T) {}
15+
extension P1 where Self : P2, T == Int { // expected-error {{'T' is ambiguous for type lookup in this context}}
16+
func takeT11(_: T) {} // expected-error {{'T' is ambiguous for type lookup in this context}}
17+
func takeT12(_: Self.T) {}
2718
}
2819

2920
extension P1 where Self : P2 {
3021
// FIXME: This doesn't make sense -- either both should
3122
// succeed, or both should be ambiguous.
32-
func takeT1(_: T) {} // expected-error {{'T' is ambiguous for type lookup in this context}}
33-
func takeT2(_: Self.T) {}
23+
func takeT21(_: T) {} // expected-error {{'T' is ambiguous for type lookup in this context}}
24+
func takeT22(_: Self.T) {}
3425
}
3526

3627
// Same as above, but now we have two visible associated types with the same
@@ -39,20 +30,17 @@ protocol P3 {
3930
associatedtype T
4031
}
4132

42-
// FIXME: This extension's generic signature is still minimized differently from
43-
// the next one. We need to decide if 'T == Int' is a redundant requirement or
44-
// not.
4533
extension P2 where Self : P3, T == Int {
46-
func takeT1(_: T) {}
47-
func takeT2(_: Self.T) {}
34+
func takeT31(_: T) {}
35+
func takeT32(_: Self.T) {}
4836
}
4937

5038
extension P2 where Self : P3 {
51-
func takeT1(_: T) {}
52-
func takeT2(_: Self.T) {}
39+
func takeT41(_: T) {}
40+
func takeT42(_: Self.T) {}
5341
}
5442

5543
protocol P4 : P2, P3 {
56-
func takeT1(_: T)
57-
func takeT2(_: Self.T)
44+
func takeT51(_: T)
45+
func takeT52(_: Self.T)
5846
}

test/decl/typealias/protocol.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ extension P10 {
268268
typealias U = Float
269269
}
270270

271-
extension P10 where T == Int { } // expected-warning{{neither type in same-type constraint ('Self.T' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
271+
extension P10 where T == Int { } // expected-warning{{neither type in same-type constraint ('Int' or 'Int') refers to a generic parameter or associated type}}
272272

273273
extension P10 where A == X<T> { }
274274

@@ -277,7 +277,7 @@ extension P10 where A == X<U> { }
277277
extension P10 where A == X<Self.U> { }
278278

279279
extension P10 where V == Int { } // expected-warning {{'V' is deprecated: just use Int, silly}}
280-
// expected-warning@-1{{neither type in same-type constraint ('Self.V' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
280+
// expected-warning@-1{{neither type in same-type constraint ('Int' or 'Int') refers to a generic parameter or associated type}}
281281

282282
// rdar://problem/36003312
283283
protocol P11 {

0 commit comments

Comments
 (0)