Skip to content

Commit c58d9d8

Browse files
committed
Sema: StructuralRequirementsRequest collects protocol typealiases
Introduces rewrite rules for typealiases defined inside the protocol itself. Typealiases defined in protocol extensions do not participate in the rewrite system, except for when they have the same name as an associated type, as per the weird rule codified in the TypeAliasRequirementsRequest for GSB compatibility.
1 parent fa65fd0 commit c58d9d8

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,12 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
491491
return ctx.AllocateCopy(result);
492492
}
493493

494-
// Add requirements for each of the associated types.
495-
for (auto assocTypeDecl : proto->getAssociatedTypeMembers()) {
494+
// Add requirements for each associated type.
495+
llvm::SmallDenseSet<Identifier, 2> assocTypes;
496+
497+
for (auto *assocTypeDecl : proto->getAssociatedTypeMembers()) {
498+
assocTypes.insert(assocTypeDecl->getName());
499+
496500
// Add requirements placed directly on this associated type.
497501
auto assocType = assocTypeDecl->getDeclaredInterfaceType();
498502
realizeInheritedRequirements(assocTypeDecl, assocType,
@@ -510,6 +514,33 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
510514
});
511515
}
512516

517+
// Add requirements for each typealias.
518+
for (auto *decl : proto->getMembers()) {
519+
// Protocol typealiases are modeled as same-type requirements
520+
// where the left hand side is 'Self.X' for some unresolved
521+
// DependentMemberType X, and the right hand side is the
522+
// underlying type of the typealias.
523+
if (auto *typeAliasDecl = dyn_cast<TypeAliasDecl>(decl)) {
524+
if (!typeAliasDecl->isGeneric()) {
525+
// Ignore the typealias if we have an associated type with the same anme
526+
// in the same protocol. This is invalid anyway, but it's just here to
527+
// ensure that we produce the same requirement signature on some tests
528+
// with -requirement-machine-protocol-signatures=verify.
529+
if (assocTypes.contains(typeAliasDecl->getName()))
530+
continue;
531+
532+
auto underlyingType = typeAliasDecl->getStructuralType();
533+
534+
auto subjectType = DependentMemberType::get(
535+
selfTy, typeAliasDecl->getName());
536+
Requirement req(RequirementKind::SameType, subjectType,
537+
underlyingType);
538+
result.push_back({req, typeAliasDecl->getLoc(),
539+
/*inferred=*/false});
540+
}
541+
}
542+
}
543+
513544
return ctx.AllocateCopy(result);
514545
}
515546

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
// Make sure we don't get a cycle <T : P> => P.A => G => <T : P>.
4+
5+
func foo<T : P>(_: T) {}
6+
7+
protocol P {
8+
typealias A = G<Self>
9+
}
10+
11+
struct G<T : P> {}

0 commit comments

Comments
 (0)