Skip to content

Commit c79a89b

Browse files
committed
RequirementMachine: Improved isCanonicalTypeInContext()
We would bail out early if there was no property map entry for this key. But this means if a term without properties was non-canonical, this method would still return false. On the other hand, it is possible for a DependentMemberType to be canonical, even if its parent is not, in the case where the parent is fixed to a concrete type. To handle this properly, change the type walk to use a TypeWalker directly instead of findIf(); this allows us to return Action::SkipChildren upon encountering a DependentMemberType. The primary use of isCanonicalTypeInContext() was from inside GenericSignature::verify(). So the assertion there will become stricter.
1 parent 4c5cc21 commit c79a89b

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

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)