Skip to content

Commit d7bb7e6

Browse files
committed
RequirementMachine: Implement GenericSignature::isCanonicalTypeInContext() query
1 parent 499bff2 commit d7bb7e6

File tree

3 files changed

+68
-3
lines changed

3 files changed

+68
-3
lines changed

include/swift/AST/RequirementMachine.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class RequirementMachine final {
6666
bool isConcreteType(Type depType) const;
6767
Type getConcreteType(Type depType) const;
6868
bool areSameTypeParameterInContext(Type depType1, Type depType2) const;
69+
bool isCanonicalTypeInContext(Type type) const;
6970
Type getCanonicalTypeInContext(Type type,
7071
TypeArrayView<GenericTypeParamType> genericParams) const;
7172
ConformanceAccessPath getConformanceAccessPath(Type type,

lib/AST/GenericSignature.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,39 @@ bool GenericSignatureImpl::isCanonicalTypeInContext(Type type) const {
787787
if (!type->hasTypeParameter())
788788
return true;
789789

790-
auto &builder = *getGenericSignatureBuilder();
791-
return isCanonicalTypeInContext(type, builder);
790+
auto computeViaGSB = [&]() {
791+
auto &builder = *getGenericSignatureBuilder();
792+
return isCanonicalTypeInContext(type, builder);
793+
};
794+
795+
auto computeViaRQM = [&]() {
796+
auto *machine = getRequirementMachine();
797+
return machine->isCanonicalTypeInContext(type);
798+
};
799+
800+
auto &ctx = getASTContext();
801+
if (ctx.LangOpts.EnableRequirementMachine) {
802+
auto rqmResult = computeViaRQM();
803+
804+
#ifndef NDEBUG
805+
auto gsbResult = computeViaGSB();
806+
807+
if (gsbResult != rqmResult) {
808+
llvm::errs() << "RequirementMachine::isCanonicalTypeInContext() is broken\n";
809+
llvm::errs() << "Generic signature: " << GenericSignature(this) << "\n";
810+
llvm::errs() << "Dependent type: "; type.dump(llvm::errs());
811+
llvm::errs() << "\n";
812+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult << "\n";
813+
llvm::errs() << "RequirementMachine says: " << rqmResult << "\n";
814+
getRequirementMachine()->dump(llvm::errs());
815+
abort();
816+
}
817+
#endif
818+
819+
return rqmResult;
820+
} else {
821+
return computeViaGSB();
822+
}
792823
}
793824

794825
bool GenericSignatureImpl::isCanonicalTypeInContext(

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,40 @@ RequirementMachine::Implementation::getLongestValidPrefix(const MutableTerm &ter
637637
return prefix;
638638
}
639639

640-
/// Unlike the other queries, the input type can be any type, not just a
640+
/// Unlike most other queries, the input type can be any type, not just a
641+
/// type parameter.
642+
///
643+
/// Returns true if all structural components that are type parameters are
644+
/// in their canonical form, and are not concrete (in which case they're
645+
/// not considered canonical, since they can be replaced with their
646+
/// concrete type).
647+
bool RequirementMachine::isCanonicalTypeInContext(Type type) const {
648+
auto &protos = Impl->System.getProtocols();
649+
650+
// Look for non-canonical type parameters.
651+
return !type.findIf([&](Type component) -> bool {
652+
if (!component->isTypeParameter())
653+
return false;
654+
655+
auto term = Impl->Context.getMutableTermForType(component->getCanonicalType(),
656+
/*proto=*/nullptr);
657+
658+
Impl->System.simplify(term);
659+
Impl->verify(term);
660+
661+
auto *equivClass = Impl->Map.lookUpEquivalenceClass(term);
662+
if (!equivClass)
663+
return false;
664+
665+
if (equivClass->isConcreteType())
666+
return true;
667+
668+
auto anchor = Impl->Context.getTypeForTerm(term, {}, protos);
669+
return CanType(anchor) != CanType(component);
670+
});
671+
}
672+
673+
/// Unlike most other queries, the input type can be any type, not just a
641674
/// type parameter.
642675
///
643676
/// Replaces all structural components that are type parameters with their

0 commit comments

Comments
 (0)