Skip to content

Commit bbd5691

Browse files
authored
Merge pull request swiftlang#40603 from slavapestov/rqm-is-canonical-type-fix
RequirementMachine: Improved isCanonicalTypeInContext()
2 parents 1647cdd + f5545bb commit bbd5691

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,23 +1611,25 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
16111611
break;
16121612

16131613
case RequirementKind::SameType: {
1614-
auto isCanonicalAnchor = [&](Type type) {
1615-
if (auto *dmt = type->getAs<DependentMemberType>())
1616-
return canSig->isCanonicalTypeInContext(dmt->getBase());
1614+
auto hasCanonicalOrConcreteParent = [&](Type type) {
1615+
if (auto *dmt = type->getAs<DependentMemberType>()) {
1616+
return (canSig->isCanonicalTypeInContext(dmt->getBase()) ||
1617+
canSig->isConcreteType(dmt->getBase()));
1618+
}
16171619
return type->is<GenericTypeParamType>();
16181620
};
16191621

16201622
auto firstType = reqt.getFirstType();
16211623
auto secondType = reqt.getSecondType();
1622-
if (!isCanonicalAnchor(firstType)) {
1624+
if (!hasCanonicalOrConcreteParent(firstType)) {
16231625
llvm::errs() << "Left hand side does not have a canonical parent: ";
16241626
reqt.dump(llvm::errs());
16251627
llvm::errs() << "\n";
16261628
abort();
16271629
}
16281630

16291631
if (reqt.getSecondType()->isTypeParameter()) {
1630-
if (!isCanonicalAnchor(secondType)) {
1632+
if (!hasCanonicalOrConcreteParent(secondType)) {
16311633
llvm::errs() << "Right hand side does not have a canonical parent: ";
16321634
reqt.dump(llvm::errs());
16331635
llvm::errs() << "\n";

lib/AST/RequirementMachine/GenericSignatureQueries.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -260,26 +260,38 @@ RequirementMachine::getLongestValidPrefix(const MutableTerm &term) const {
260260
/// concrete type).
261261
bool RequirementMachine::isCanonicalTypeInContext(Type type) const {
262262
// Look for non-canonical type parameters.
263-
return !type.findIf([&](Type component) -> bool {
264-
if (!component->isTypeParameter())
265-
return false;
263+
class Walker : public TypeWalker {
264+
const RequirementMachine &Self;
266265

267-
auto term = Context.getMutableTermForType(component->getCanonicalType(),
268-
/*proto=*/nullptr);
266+
public:
267+
explicit Walker(const RequirementMachine &self) : Self(self) {}
269268

270-
System.simplify(term);
271-
verify(term);
269+
Action walkToTypePre(Type component) override {
270+
if (!component->isTypeParameter())
271+
return Action::Continue;
272272

273-
auto *props = Map.lookUpProperties(term);
274-
if (!props)
275-
return false;
273+
auto term = Self.Context.getMutableTermForType(
274+
component->getCanonicalType(),
275+
/*proto=*/nullptr);
276276

277-
if (props->isConcreteType())
278-
return true;
277+
Self.System.simplify(term);
278+
Self.verify(term);
279279

280-
auto anchor = Context.getTypeForTerm(term, {});
281-
return CanType(anchor) != CanType(component);
282-
});
280+
auto anchor = Self.Context.getTypeForTerm(term, {});
281+
if (CanType(anchor) != CanType(component))
282+
return Action::Stop;
283+
284+
auto *props = Self.Map.lookUpProperties(term);
285+
if (props && props->isConcreteType())
286+
return Action::Stop;
287+
288+
// The parent of a canonical type parameter might be non-canonical
289+
// because it is concrete.
290+
return Action::SkipChildren;
291+
}
292+
};
293+
294+
return !type.walk(Walker(*this));
283295
}
284296

285297
/// Unlike most other queries, the input type can be any type, not just a

0 commit comments

Comments
 (0)