Skip to content

Commit 5a2b193

Browse files
committed
RequirementMachine: Refactor PropertyMap::computeConstraintTermForTypeWitness()
1 parent 8e3f350 commit 5a2b193

File tree

2 files changed

+75
-61
lines changed

2 files changed

+75
-61
lines changed

lib/AST/RequirementMachine/PropertyMap.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,10 @@ class PropertyMap {
227227
SmallVectorImpl<InducedRule> &inducedRules) const;
228228

229229
MutableTerm computeConstraintTermForTypeWitness(
230-
Term key, CanType concreteType, CanType typeWitness,
231-
const MutableTerm &subjectType, ArrayRef<Term> substitutions,
230+
Term key, RequirementKind requirementKind,
231+
CanType concreteType, CanType typeWitness,
232+
const MutableTerm &subjectType,
233+
ArrayRef<Term> substitutions,
232234
RewritePath &path) const;
233235

234236
void recordConcreteConformanceRule(

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -616,34 +616,9 @@ void PropertyMap::concretizeTypeWitnessInConformance(
616616

617617
RewritePath path;
618618

619-
auto simplify = [&](CanType t) -> CanType {
620-
return CanType(t.transformRec([&](Type t) -> Optional<Type> {
621-
if (!t->isTypeParameter())
622-
return None;
623-
624-
auto term = Context.getRelativeTermForType(t->getCanonicalType(),
625-
substitutions);
626-
System.simplify(term);
627-
return Context.getTypeForTerm(term, { });
628-
}));
629-
};
630-
631-
if (simplify(concreteType) == simplify(typeWitness) &&
632-
requirementKind == RequirementKind::SameType) {
633-
// FIXME: ConcreteTypeInDomainMap should support substitutions so
634-
// that we can remove this.
635-
636-
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
637-
llvm::dbgs() << "^^ Type witness is the same as the concrete type\n";
638-
}
639-
640-
// Add a rule T.[P:A] => T.
641-
constraintType = MutableTerm(key);
642-
} else {
643-
constraintType = computeConstraintTermForTypeWitness(
644-
key, concreteType, typeWitness, subjectType,
645-
substitutions, path);
646-
}
619+
constraintType = computeConstraintTermForTypeWitness(
620+
key, requirementKind, concreteType, typeWitness, subjectType,
621+
substitutions, path);
647622

648623
inducedRules.emplace_back(constraintType, subjectType, path);
649624
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
@@ -721,9 +696,69 @@ RewriteSystem::getConcreteTypeWitness(unsigned index) const {
721696
///
722697
/// T.[P:A] => V
723698
MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
724-
Term key, CanType concreteType, CanType typeWitness,
725-
const MutableTerm &subjectType, ArrayRef<Term> substitutions,
699+
Term key, RequirementKind requirementKind,
700+
CanType concreteType, CanType typeWitness,
701+
const MutableTerm &subjectType,
702+
ArrayRef<Term> substitutions,
726703
RewritePath &path) const {
704+
// If the type witness is abstract, introduce a same-type requirement
705+
// between two type parameters.
706+
if (typeWitness->isTypeParameter()) {
707+
// The type witness is a type parameter of the form τ_0_n.X.Y...Z,
708+
// where 'n' is an index into the substitution array.
709+
//
710+
// Add a rule:
711+
//
712+
// T.[concrete: C : P].[P:X] => S[n].X.Y...Z
713+
//
714+
// Where S[n] is the nth substitution term.
715+
716+
// FIXME: Record a rewrite path.
717+
return Context.getRelativeTermForType(typeWitness, substitutions);
718+
}
719+
720+
// Otherwise the type witness is concrete, but may contain type
721+
// parameters in structural position.
722+
723+
// Compute the concrete type symbol [concrete: C.X].
724+
SmallVector<Term, 3> result;
725+
auto typeWitnessSchema =
726+
remapConcreteSubstitutionSchema(typeWitness, substitutions,
727+
Context, result);
728+
auto typeWitnessSymbol =
729+
Symbol::forConcreteType(typeWitnessSchema, result, Context);
730+
System.simplifySubstitutions(typeWitnessSymbol);
731+
732+
auto concreteConformanceSymbol = *(subjectType.end() - 2);
733+
auto assocTypeSymbol = *(subjectType.end() - 1);
734+
735+
RewriteSystem::ConcreteTypeWitness witness(concreteConformanceSymbol,
736+
assocTypeSymbol,
737+
typeWitnessSymbol);
738+
unsigned witnessID = System.recordConcreteTypeWitness(witness);
739+
740+
// If it is equal to the parent type, introduce a same-type requirement
741+
// between the two parameters.
742+
if (requirementKind == RequirementKind::SameType &&
743+
typeWitnessSymbol.getConcreteType() == concreteType &&
744+
typeWitnessSymbol.getSubstitutions() == substitutions) {
745+
// FIXME: ConcreteTypeInDomainMap should support substitutions so
746+
// that we can remove this.
747+
748+
if (Debug.contains(DebugFlags::ConcretizeNestedTypes)) {
749+
llvm::dbgs() << "^^ Type witness is the same as the concrete type\n";
750+
}
751+
752+
// Add a rule T.[concrete: C : P].[P:X] => T.[concrete: C : P].
753+
MutableTerm result(key);
754+
result.add(concreteConformanceSymbol);
755+
756+
return result;
757+
}
758+
759+
// If the type witness is completely concrete, try to introduce a
760+
// same-type requirement with another representative type parameter,
761+
// if we have one.
727762
if (!typeWitness->hasTypeParameter()) {
728763
// Check if we have a shorter representative we can use.
729764
auto domain = key.getRootProtocols();
@@ -737,46 +772,23 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
737772
llvm::dbgs() << "^^ Type witness can re-use property bag of "
738773
<< found->second << "\n";
739774
}
775+
776+
// FIXME: Record a rewrite path.
740777
return result;
741778
}
742779
}
743780
}
744781

745-
if (typeWitness->isTypeParameter()) {
746-
// The type witness is a type parameter of the form τ_0_n.X.Y...Z,
747-
// where 'n' is an index into the substitution array.
748-
//
749-
// Add a rule:
750-
//
751-
// T.[concrete: C : P].[P:X] => S[n].X.Y...Z
752-
//
753-
// Where S[n] is the nth substitution term.
754-
return Context.getRelativeTermForType(typeWitness, substitutions);
755-
}
756-
757-
// The type witness is a concrete type.
782+
// Otherwise, add a concrete type requirement for the type witness.
758783
//
759784
// Add a rule:
760785
//
761-
// T.[concrete: C : P].[P:X].[concrete: Foo.A] => T.[concrete: C : P].[P:A].
786+
// T.[concrete: C : P].[P:X].[concrete: C.X] => T.[concrete: C : P].[P:X].
762787
MutableTerm constraintType = subjectType;
763-
764-
SmallVector<Term, 3> result;
765-
auto typeWitnessSchema =
766-
remapConcreteSubstitutionSchema(typeWitness, substitutions,
767-
Context, result);
768-
769-
constraintType.add(
770-
Symbol::forConcreteType(
771-
typeWitnessSchema, result, Context));
772-
773-
RewriteSystem::ConcreteTypeWitness witness(*(constraintType.end() - 3),
774-
*(constraintType.end() - 2),
775-
*(constraintType.end() - 1));
776-
unsigned index = System.recordConcreteTypeWitness(witness);
788+
constraintType.add(typeWitnessSymbol);
777789

778790
path.add(RewriteStep::forConcreteTypeWitness(
779-
index, /*inverse=*/false));
791+
witnessID, /*inverse=*/false));
780792

781793
return constraintType;
782794
}

0 commit comments

Comments
 (0)