Skip to content

Commit 4c83fe8

Browse files
committed
RequirementMachine: Generalize ConcreteTypeWitness to TypeWitness
1 parent b1a3d2c commit 4c83fe8

File tree

4 files changed

+114
-76
lines changed

4 files changed

+114
-76
lines changed

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -636,48 +636,53 @@ void PropertyMap::concretizeTypeWitnessInConformance(
636636
}
637637
}
638638

639-
RewriteSystem::ConcreteTypeWitness::ConcreteTypeWitness(
640-
Symbol concreteConformance,
641-
Symbol assocType,
642-
Symbol concreteType)
643-
: ConcreteConformance(concreteConformance),
644-
AssocType(assocType),
645-
ConcreteType(concreteType) {
646-
assert(concreteConformance.getKind() == Symbol::Kind::ConcreteConformance);
647-
assert(assocType.getKind() == Symbol::Kind::AssociatedType);
648-
assert(concreteType.getKind() == Symbol::Kind::ConcreteType);
649-
assert(assocType.getProtocols().size() == 1);
650-
assert(assocType.getProtocols()[0] == concreteConformance.getProtocol());
639+
RewriteSystem::TypeWitness::TypeWitness(
640+
Term lhs, llvm::PointerUnion<Symbol, Term> rhs)
641+
: LHS(lhs), RHS(rhs) {
642+
assert(LHS.size() >= 2);
643+
assert(getConcreteConformance().getKind() ==
644+
Symbol::Kind::ConcreteConformance);
645+
assert(getAssocType().getKind() == Symbol::Kind::AssociatedType);
646+
if (RHS.is<Symbol>())
647+
assert(RHS.get<Symbol>().getKind() == Symbol::Kind::ConcreteType);
648+
assert(getAssocType().getProtocols().size() == 1);
649+
assert(getAssocType().getProtocols()[0] ==
650+
getConcreteConformance().getProtocol());
651651
}
652652

653653
bool swift::rewriting::operator==(
654-
const RewriteSystem::ConcreteTypeWitness &lhs,
655-
const RewriteSystem::ConcreteTypeWitness &rhs) {
656-
return (lhs.ConcreteConformance == rhs.ConcreteConformance &&
657-
lhs.AssocType == rhs.AssocType &&
658-
lhs.ConcreteType == rhs.ConcreteType);
654+
const RewriteSystem::TypeWitness &lhs,
655+
const RewriteSystem::TypeWitness &rhs) {
656+
return (lhs.LHS == rhs.LHS &&
657+
lhs.RHS == rhs.RHS);
659658
}
660659

661-
unsigned RewriteSystem::recordConcreteTypeWitness(
662-
RewriteSystem::ConcreteTypeWitness witness) {
663-
auto key = std::make_pair(witness.ConcreteConformance,
664-
witness.AssocType);
665-
unsigned index = ConcreteTypeWitnesses.size();
666-
auto inserted = ConcreteTypeWitnessMap.insert(std::make_pair(key, index));
660+
void RewriteSystem::TypeWitness::dump(llvm::raw_ostream &out) const {
661+
out << "Subject type: " << LHS << "\n";
662+
if (RHS.is<Symbol>())
663+
out << "Concrete type witness: " << RHS.get<Symbol>() << "\n";
664+
else
665+
out << "Abstract type witness: " << RHS.get<Term>() << "\n";
666+
}
667+
668+
unsigned RewriteSystem::recordTypeWitness(
669+
RewriteSystem::TypeWitness witness) {
670+
unsigned index = TypeWitnesses.size();
671+
auto inserted = TypeWitnessMap.insert(std::make_pair(witness.LHS, index));
667672

668673
if (!inserted.second) {
669674
index = inserted.first->second;
670675
} else {
671-
ConcreteTypeWitnesses.push_back(witness);
676+
TypeWitnesses.push_back(witness);
672677
}
673678

674-
assert(ConcreteTypeWitnesses[index] == witness);
679+
assert(TypeWitnesses[index] == witness);
675680
return index;
676681
}
677682

678-
const RewriteSystem::ConcreteTypeWitness &
679-
RewriteSystem::getConcreteTypeWitness(unsigned index) const {
680-
return ConcreteTypeWitnesses[index];
683+
const RewriteSystem::TypeWitness &
684+
RewriteSystem::getTypeWitness(unsigned index) const {
685+
return TypeWitnesses[index];
681686
}
682687

683688
/// Given the key of a property bag known to have \p concreteType,
@@ -737,13 +742,9 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
737742
auto typeWitnessSymbol =
738743
Symbol::forConcreteType(typeWitnessSchema, result, Context);
739744

740-
auto concreteConformanceSymbol = *(subjectType.end() - 2);
741-
auto assocTypeSymbol = *(subjectType.end() - 1);
742-
743-
RewriteSystem::ConcreteTypeWitness witness(concreteConformanceSymbol,
744-
assocTypeSymbol,
745-
typeWitnessSymbol);
746-
unsigned witnessID = System.recordConcreteTypeWitness(witness);
745+
RewriteSystem::TypeWitness witness(Term::get(subjectType, Context),
746+
typeWitnessSymbol);
747+
unsigned witnessID = System.recordTypeWitness(witness);
747748

748749
// Simplify the substitution terms in the type witness symbol.
749750
RewritePath substPath;
@@ -764,7 +765,7 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
764765

765766
// Add a rule T.[concrete: C : P] => T.[concrete: C : P].[P:X].
766767
MutableTerm result(key);
767-
result.add(concreteConformanceSymbol);
768+
result.add(witness.getConcreteConformance());
768769

769770
// ([concrete: C : P] => [concrete: C : P].[P:X].[concrete: C])
770771
path.add(RewriteStep::forSameTypeWitness(

lib/AST/RequirementMachine/RewriteLoop.cpp

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,11 @@ void RewritePathEvaluator::applyConcreteTypeWitness(const RewriteStep &step,
436436
checkA();
437437
auto &term = A.back();
438438

439-
const auto &witness = system.getConcreteTypeWitness(step.RuleID);
439+
const auto &witness = system.getTypeWitness(step.RuleID);
440440
auto fail = [&]() {
441441
llvm::errs() << "Bad concrete type witness term:\n";
442442
llvm::errs() << term << "\n\n";
443-
llvm::errs() << "Conformance: " << witness.ConcreteConformance << "\n";
444-
llvm::errs() << "Assoc type: " << witness.AssocType << "\n";
445-
llvm::errs() << "Concrete type: " << witness.ConcreteType << "\n";
443+
witness.dump(llvm::errs());
446444
llvm::errs() << "End offset: " << step.EndOffset << "\n";
447445
llvm::errs() << "Inverse: " << step.Inverse << "\n";
448446
abort();
@@ -453,9 +451,9 @@ void RewritePathEvaluator::applyConcreteTypeWitness(const RewriteStep &step,
453451
//
454452
// U.[concrete: C : P].[P:X].[concrete: C.X].V
455453
if (term.size() <= step.EndOffset + 3 ||
456-
*(term.end() - step.EndOffset - 3) != witness.ConcreteConformance ||
457-
*(term.end() - step.EndOffset - 2) != witness.AssocType ||
458-
*(term.end() - step.EndOffset - 1) != witness.ConcreteType) {
454+
*(term.end() - step.EndOffset - 3) != witness.getConcreteConformance() ||
455+
*(term.end() - step.EndOffset - 2) != witness.getAssocType() ||
456+
*(term.end() - step.EndOffset - 1) != witness.getConcreteType()) {
459457
fail();
460458
}
461459

@@ -471,16 +469,16 @@ void RewritePathEvaluator::applyConcreteTypeWitness(const RewriteStep &step,
471469
//
472470
// U.[concrete: C : P].[P:X].V
473471
if (term.size() <= step.EndOffset + 2 ||
474-
*(term.end() - step.EndOffset - 2) != witness.ConcreteConformance ||
475-
*(term.end() - step.EndOffset - 1) != witness.AssocType) {
472+
*(term.end() - step.EndOffset - 2) != witness.getConcreteConformance() ||
473+
*(term.end() - step.EndOffset - 1) != witness.getAssocType()) {
476474
fail();
477475
}
478476

479477
// Get the subterm U.[concrete: C : P].[P:X].
480478
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset);
481479

482480
// Add the symbol [concrete: C.X].
483-
newTerm.add(witness.ConcreteType);
481+
newTerm.add(witness.getConcreteType());
484482

485483
// Add the subterm V, to get
486484
//
@@ -496,35 +494,35 @@ void RewritePathEvaluator::applySameTypeWitness(const RewriteStep &step,
496494
checkA();
497495
auto &term = A.back();
498496

499-
const auto &witness = system.getConcreteTypeWitness(step.RuleID);
497+
const auto &witness = system.getTypeWitness(step.RuleID);
500498
auto fail = [&]() {
501499
llvm::errs() << "Bad same-type witness term:\n";
502500
llvm::errs() << term << "\n\n";
503-
llvm::errs() << "Conformance: " << witness.ConcreteConformance << "\n";
504-
llvm::errs() << "Assoc type: " << witness.AssocType << "\n";
505-
llvm::errs() << "Concrete type: " << witness.ConcreteType << "\n";
501+
witness.dump(llvm::errs());
506502
abort();
507503
};
508504

505+
auto concreteConformanceSymbol = witness.getConcreteConformance();
506+
509507
#ifndef NDEBUG
510-
if (witness.ConcreteType.getConcreteType() !=
511-
witness.ConcreteConformance.getConcreteType()) {
508+
if (witness.getConcreteType().getConcreteType() !=
509+
concreteConformanceSymbol.getConcreteType()) {
512510
fail();
513511
}
514512
#endif
515513

516514
auto witnessConcreteType = Symbol::forConcreteType(
517-
witness.ConcreteConformance.getConcreteType(),
518-
witness.ConcreteConformance.getSubstitutions(),
515+
concreteConformanceSymbol.getConcreteType(),
516+
concreteConformanceSymbol.getSubstitutions(),
519517
system.getRewriteContext());
520518

521519
if (!step.Inverse) {
522520
// Make sure the term takes the following form, where |V| == EndOffset:
523521
//
524522
// U.[concrete: C : P].[P:X].[concrete: C].V
525523
if (term.size() <= step.EndOffset + 3 ||
526-
*(term.end() - step.EndOffset - 3) != witness.ConcreteConformance ||
527-
*(term.end() - step.EndOffset - 2) != witness.AssocType ||
524+
*(term.end() - step.EndOffset - 3) != concreteConformanceSymbol ||
525+
*(term.end() - step.EndOffset - 2) != witness.getAssocType() ||
528526
*(term.end() - step.EndOffset - 1) != witnessConcreteType) {
529527
fail();
530528
}
@@ -541,15 +539,15 @@ void RewritePathEvaluator::applySameTypeWitness(const RewriteStep &step,
541539
//
542540
// U.[concrete: C : P].V
543541
if (term.size() <= step.EndOffset + 1 ||
544-
*(term.end() - step.EndOffset - 1) != witness.ConcreteConformance) {
542+
*(term.end() - step.EndOffset - 1) != concreteConformanceSymbol) {
545543
fail();
546544
}
547545

548546
// Get the subterm U.[concrete: C : P].
549547
MutableTerm newTerm(term.begin(), term.end() - step.EndOffset);
550548

551549
// Add the symbol [P:X].
552-
newTerm.add(witness.AssocType);
550+
newTerm.add(witness.getAssocType());
553551

554552
// Add the symbol [concrete: C].
555553
newTerm.add(witnessConcreteType);

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ struct RewriteStep {
118118
/// If inverted: the concrete type symbol [concrete: C.X] is introduced.
119119
///
120120
/// The RuleID field is repurposed to store the result of calling
121-
/// RewriteSystem::recordConcreteTypeWitness(). This index is then
122-
/// passed in to RewriteSystem::getConcreteTypeWitness() when applying
121+
/// RewriteSystem::recordTypeWitness(). This index is then passed in
122+
/// to RewriteSystem::getTypeWitness() when applying
123123
/// the step.
124124
ConcreteTypeWitness,
125125

@@ -129,9 +129,7 @@ struct RewriteStep {
129129
///
130130
/// If inverted: the associated type symbol [P:X] is introduced.
131131
///
132-
/// The RuleID field is repurposed to store the result of calling
133-
/// RewriteSystem::recordConcreteTypeWitness(). This index is then
134-
/// passed in to RewriteSystem::getConcreteTypeWitness() when applying
132+
/// The RuleID field is a TypeWitness ID as above.
135133
/// the step.
136134
SameTypeWitness,
137135
};

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_REWRITESYSTEM_H
1515

1616
#include "llvm/ADT/DenseSet.h"
17+
#include "llvm/ADT/PointerUnion.h"
1718

1819
#include "Debug.h"
1920
#include "RewriteLoop.h"
@@ -324,28 +325,68 @@ class RewriteSystem final {
324325
//////////////////////////////////////////////////////////////////////////////
325326

326327
public:
327-
struct ConcreteTypeWitness {
328-
Symbol ConcreteConformance;
329-
Symbol AssocType;
330-
Symbol ConcreteType;
328+
/// A type witness has a subject type, stored in LHS, which takes the form:
329+
///
330+
/// T.[concrete: C : P].[P:X]
331+
///
332+
/// For some concrete type C, protocol P and associated type X.
333+
///
334+
/// The type witness of X in the conformance C : P is either a concrete type,
335+
/// or an abstract type parameter.
336+
///
337+
/// If it is a concrete type, then RHS stores the concrete type symbol.
338+
///
339+
/// If it is an abstract type parameter, then RHS stores the type term.
340+
///
341+
/// Think of these as rewrite rules which are lazily created, but always
342+
/// "there" -- they encode information about concrete conformances, which
343+
/// are solved outside of the requirement machine itself.
344+
///
345+
/// We don't want to eagerly pull in all concrete conformances and walk
346+
/// them recursively introducing rewrite rules.
347+
///
348+
/// The RewriteStep::{Concrete,Same,Abstract}TypeWitness rewrite step kinds
349+
/// reference TypeWitnesses via their RuleID field.
350+
///
351+
/// Type witnesses are recorded lazily in property map construction, in
352+
/// PropertyMap::computeConstraintTermForTypeWitness().
353+
struct TypeWitness {
354+
Term LHS;
355+
llvm::PointerUnion<Symbol, Term> RHS;
356+
357+
TypeWitness(Term lhs, llvm::PointerUnion<Symbol, Term> rhs);
358+
359+
friend bool operator==(const TypeWitness &lhs,
360+
const TypeWitness &rhs);
361+
362+
Symbol getConcreteConformance() const {
363+
return *(LHS.end() - 2);
364+
}
365+
366+
Symbol getAssocType() const {
367+
return *(LHS.end() - 1);
368+
}
369+
370+
Symbol getConcreteType() const {
371+
return RHS.get<Symbol>();
372+
}
331373

332-
ConcreteTypeWitness(Symbol concreteConformance,
333-
Symbol assocType,
334-
Symbol concreteType);
374+
Term getAbstractType() const {
375+
return RHS.get<Term>();
376+
}
335377

336-
friend bool operator==(const ConcreteTypeWitness &lhs,
337-
const ConcreteTypeWitness &rhs);
378+
void dump(llvm::raw_ostream &out) const;
338379
};
339380

340381
private:
341382
/// Cache for concrete type witnesses. The value in the map is an index
342383
/// into the vector.
343-
llvm::DenseMap<std::pair<Symbol, Symbol>, unsigned> ConcreteTypeWitnessMap;
344-
std::vector<ConcreteTypeWitness> ConcreteTypeWitnesses;
384+
llvm::DenseMap<Term, unsigned> TypeWitnessMap;
385+
std::vector<TypeWitness> TypeWitnesses;
345386

346387
public:
347-
unsigned recordConcreteTypeWitness(ConcreteTypeWitness witness);
348-
const ConcreteTypeWitness &getConcreteTypeWitness(unsigned index) const;
388+
unsigned recordTypeWitness(TypeWitness witness);
389+
const TypeWitness &getTypeWitness(unsigned index) const;
349390

350391
//////////////////////////////////////////////////////////////////////////////
351392
///

0 commit comments

Comments
 (0)