Skip to content

Commit 930909f

Browse files
committed
GSB: Clean up ExplicitRequirement a bit
1 parent 35a2687 commit 930909f

File tree

1 file changed

+79
-65
lines changed

1 file changed

+79
-65
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 79 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -439,19 +439,11 @@ class GenericSignatureBuilder::ExplicitRequirement {
439439
public:
440440
ExplicitRequirement(RequirementKind kind,
441441
const RequirementSource *source,
442-
Type type)
443-
: sourceAndKind(source, kind),
444-
rhs(type ? type->getCanonicalType() : Type()) {}
445-
446-
ExplicitRequirement(RequirementKind kind,
447-
const RequirementSource *source,
448-
ProtocolDecl *proto)
449-
: sourceAndKind(source, kind), rhs(proto) {}
450-
451-
ExplicitRequirement(RequirementKind kind,
452-
const RequirementSource *source,
453-
LayoutConstraint layout)
454-
: sourceAndKind(source, kind), rhs(layout) {}
442+
RequirementRHS rhs)
443+
: sourceAndKind(source, kind), rhs(rhs) {
444+
if (auto type = rhs.dyn_cast<Type>())
445+
this->rhs = type->getCanonicalType();
446+
}
455447

456448
/// For a Constraint<T> with an explicit requirement source, we recover the
457449
/// subject type from the requirement source and the right hand side from the
@@ -468,36 +460,10 @@ class GenericSignatureBuilder::ExplicitRequirement {
468460
return ExplicitRequirement(kind, constraint.source, constraint.value);
469461
}
470462

471-
/// To recover the root explicit requirement from a Constraint<T>, we walk the
472-
/// requirement source up the root, and look at both the root and the next
473-
/// innermost child.
474-
/// Together, these give us the subject type (via the root) and the right hand
475-
/// side of the requirement (from the next innermost child).
476-
///
477-
/// The requirement kind must be passed in since Constraint<T>'s kind is
478-
/// implicit by virtue of which list it appears under inside its equivalence
479-
/// class, and is not stored inside the constraint.
480-
///
481-
/// The constraint's actual value is ignored; that's the right hand
482-
/// side of the derived constraint, not the right hand side of the original
483-
/// explicit requirement.
484-
template<typename T>
485-
static ExplicitRequirement fromDerivedConstraint(RequirementKind kind,
486-
Constraint<T> constraint) {
487-
assert(constraint.source->isDerivedNonRootRequirement());
488-
489-
const RequirementSource *root = constraint.source;
490-
const RequirementSource *child = nullptr;
491-
492-
while (root->parent && root->isDerivedRequirement()) {
493-
child = root;
494-
root = root->parent;
495-
}
496-
497-
assert(root != nullptr);
498-
assert(child != nullptr);
499-
500-
switch (child->kind) {
463+
static std::pair<RequirementKind, RequirementRHS>
464+
getKindAndRHS(const RequirementSource *source,
465+
ASTContext &ctx) {
466+
switch (source->kind) {
501467
// If we have a protocol requirement source whose parent is the root, then
502468
// we have an implied constraint coming from a protocol's requirement
503469
// signature:
@@ -511,8 +477,8 @@ class GenericSignatureBuilder::ExplicitRequirement {
511477
// Therefore the original constraint was 'T : Sequence'.
512478
case RequirementSource::ProtocolRequirement:
513479
case RequirementSource::InferredProtocolRequirement: {
514-
auto *proto = child->getProtocolDecl();
515-
return ExplicitRequirement(RequirementKind::Conformance, root, proto);
480+
auto *proto = source->getProtocolDecl();
481+
return std::make_pair(RequirementKind::Conformance, proto);
516482
}
517483

518484
// If we have a superclass or concrete source whose parent is the root, then
@@ -528,29 +494,28 @@ class GenericSignatureBuilder::ExplicitRequirement {
528494
// respectively.
529495
case RequirementSource::Superclass:
530496
case RequirementSource::Concrete: {
531-
Type conformingType = child->getStoredType();
497+
Type conformingType = source->getStoredType();
532498
if (conformingType) {
533499
// A concrete requirement source for a self-conforming exitential type
534500
// stores the original type, and not the conformance, because there is
535501
// no way to recover the original type from the conformance.
536502
assert(conformingType->isExistentialType());
537503
} else {
538-
auto conformance = child->getProtocolConformance();
504+
auto conformance = source->getProtocolConformance();
539505
if (conformance.isConcrete())
540506
conformingType = conformance.getConcrete()->getType();
541507
else {
542508
// If the conformance was abstract or invalid, we're dealing with
543509
// invalid code. We have no way to recover the superclass type, so
544510
// just stick an ErrorType in there.
545-
auto &ctx = constraint.getSubjectDependentType({ })->getASTContext();
546511
conformingType = ErrorType::get(ctx);
547512
}
548513
}
549514

550-
auto kind = (child->kind == RequirementSource::Superclass
515+
auto kind = (source->kind == RequirementSource::Superclass
551516
? RequirementKind::Superclass
552517
: RequirementKind::SameType);
553-
return ExplicitRequirement(kind, root, conformingType);
518+
return std::make_pair(kind, conformingType);
554519
}
555520

556521
// If we have a layout source whose parent is the root, then
@@ -563,19 +528,61 @@ class GenericSignatureBuilder::ExplicitRequirement {
563528
// by a superclass constraint, ensuring that it supercedes an explicit
564529
// 'T : AnyObject' constraint).
565530
case RequirementSource::Layout: {
566-
auto type = child->getStoredType();
567-
return ExplicitRequirement(RequirementKind::Superclass, root, type);
531+
auto type = source->getStoredType();
532+
return std::make_pair(RequirementKind::Superclass, type);
568533
}
569534

570535
default: {
571-
auto &SM = constraint.getSubjectDependentType({ })->getASTContext().SourceMgr;
572-
constraint.source->dump(llvm::errs(), &SM, 0);
536+
source->dump(llvm::errs(), &ctx.SourceMgr, 0);
573537
llvm::errs() << "\n";
574-
llvm_unreachable("Unknown root kind");
538+
llvm_unreachable("Unhandled source kind");
575539
}
576540
}
577541
}
578542

543+
static ExplicitRequirement fromRequirementSource(const RequirementSource *source,
544+
ASTContext &ctx) {
545+
auto *parent = source->parent;
546+
547+
RequirementKind kind;
548+
RequirementRHS rhs;
549+
std::tie(kind, rhs) = getKindAndRHS(source, ctx);
550+
551+
return ExplicitRequirement(kind, parent, rhs);
552+
}
553+
554+
/// To recover the root explicit requirement from a Constraint<T>, we walk the
555+
/// requirement source up the root, and look at both the root and the next
556+
/// innermost child.
557+
/// Together, these give us the subject type (via the root) and the right hand
558+
/// side of the requirement (from the next innermost child).
559+
///
560+
/// The requirement kind must be passed in since Constraint<T>'s kind is
561+
/// implicit by virtue of which list it appears under inside its equivalence
562+
/// class, and is not stored inside the constraint.
563+
///
564+
/// The constraint's actual value is ignored; that's the right hand
565+
/// side of the derived constraint, not the right hand side of the original
566+
/// explicit requirement.
567+
template<typename T>
568+
static ExplicitRequirement fromDerivedConstraint(Constraint<T> constraint,
569+
ASTContext &ctx) {
570+
assert(constraint.source->isDerivedNonRootRequirement());
571+
572+
const RequirementSource *root = constraint.source;
573+
const RequirementSource *child = nullptr;
574+
575+
while (root->parent && root->isDerivedRequirement()) {
576+
child = root;
577+
root = root->parent;
578+
}
579+
580+
assert(child != nullptr);
581+
assert(root != nullptr);
582+
583+
return fromRequirementSource(child, ctx);
584+
}
585+
579586
RequirementKind getKind() const {
580587
return sourceAndKind.getInt();
581588
}
@@ -5818,7 +5825,8 @@ class RedundantRequirementGraph {
58185825
addConstraintsFromEquivClass(
58195826
RequirementKind kind,
58205827
const SmallVectorImpl<Constraint<T>> &exact,
5821-
const SmallVectorImpl<Constraint<T>> &lessSpecific) {
5828+
const SmallVectorImpl<Constraint<T>> &lessSpecific,
5829+
ASTContext &ctx) {
58225830
// The set of 'redundant explicit requirements', which are known to be less
58235831
// specific than some other explicit requirements. An example is a type
58245832
// parameter with multiple superclass constraints:
@@ -5848,11 +5856,13 @@ class RedundantRequirementGraph {
58485856

58495857
for (auto constraint : exact) {
58505858
if (constraint.source->isDerivedNonRootRequirement()) {
5851-
auto req = ExplicitRequirement::fromDerivedConstraint(kind, constraint);
5859+
auto req = ExplicitRequirement::fromDerivedConstraint(
5860+
constraint, ctx);
58525861

58535862
rootReqs.push_back(req);
58545863
} else {
5855-
auto req = ExplicitRequirement::fromExplicitConstraint(kind, constraint);
5864+
auto req = ExplicitRequirement::fromExplicitConstraint(
5865+
kind, constraint);
58565866

58575867
VertexID v = addVertex(req);
58585868
#ifndef NDEBUG
@@ -6241,14 +6251,17 @@ void GenericSignatureBuilder::ExplicitRequirement::dump(
62416251
break;
62426252
}
62436253

6244-
getSource()->dump(out, SM, 0);
6245-
out << " : ";
6254+
out << getSubjectType() << " : ";
62466255
if (auto type = rhs.dyn_cast<Type>())
62476256
out << type;
62486257
else if (auto *proto = rhs.dyn_cast<ProtocolDecl *>())
62496258
out << proto->getName();
62506259
else
62516260
out << rhs.get<LayoutConstraint>();
6261+
6262+
out << "(source: ";
6263+
getSource()->dump(out, SM, 0);
6264+
out << ")";
62526265
}
62536266

62546267
static bool typeImpliesLayoutConstraint(Type t, LayoutConstraint layout) {
@@ -6324,7 +6337,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
63246337
}
63256338

63266339
graph.addConstraintsFromEquivClass(RequirementKind::Conformance,
6327-
exact, lessSpecific);
6340+
exact, lessSpecific, Context);
63286341
}
63296342

63306343
Type resolvedConcreteType;
@@ -6376,7 +6389,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
63766389

63776390
concreteTypeRequirement =
63786391
graph.addConstraintsFromEquivClass(RequirementKind::SameType,
6379-
exact, lessSpecific);
6392+
exact, lessSpecific, Context);
63806393
}
63816394

63826395
Type resolvedSuperclass;
@@ -6438,7 +6451,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
64386451

64396452
superclassRequirement =
64406453
graph.addConstraintsFromEquivClass(RequirementKind::Superclass,
6441-
exact, lessSpecific);
6454+
exact, lessSpecific, Context);
64426455

64436456
graph.handleConstraintsImpliedByConcrete(RequirementKind::Superclass,
64446457
impliedByConcrete,
@@ -6499,7 +6512,7 @@ void GenericSignatureBuilder::computeRedundantRequirements(
64996512

65006513
layoutRequirement =
65016514
graph.addConstraintsFromEquivClass(RequirementKind::Layout,
6502-
exact, lessSpecific);
6515+
exact, lessSpecific, Context);
65036516

65046517
graph.handleConstraintsImpliedByConcrete(RequirementKind::Layout,
65056518
impliedByConcrete,
@@ -8641,7 +8654,8 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
86418654
const ProtocolDecl *requirementSignatureSelfProto,
86428655
bool rebuildingWithoutRedundantConformances) && {
86438656
// Finalize the builder, producing any necessary diagnostics.
8644-
finalize(getGenericParams(), allowConcreteGenericParams,
8657+
finalize(getGenericParams(),
8658+
allowConcreteGenericParams,
86458659
requirementSignatureSelfProto);
86468660

86478661
if (rebuildingWithoutRedundantConformances) {

0 commit comments

Comments
 (0)