Skip to content

Commit a8d865a

Browse files
committed
Sema: Refactor CheckTypeWitnessResult type used in conformance checking
1 parent bd5a031 commit a8d865a

File tree

3 files changed

+67
-29
lines changed

3 files changed

+67
-29
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4613,7 +4613,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
46134613
auto &ctx = assocType->getASTContext();
46144614

46154615
if (type->hasError())
4616-
return ErrorType::get(ctx);
4616+
return CheckTypeWitnessResult::forError();
46174617

46184618
const auto proto = Conf->getProtocol();
46194619
const auto dc = Conf->getDeclContext();
@@ -4624,14 +4624,14 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
46244624
if (ctx.isRecursivelyConstructingRequirementMachine(sig.getCanonicalSignature()) ||
46254625
ctx.isRecursivelyConstructingRequirementMachine(proto) ||
46264626
proto->isComputingRequirementSignature())
4627-
return ErrorType::get(ctx);
4627+
return CheckTypeWitnessResult::forError();
46284628

46294629
// No move-only type can witness an associatedtype requirement.
46304630
if (type->isPureMoveOnly()) {
46314631
// describe the failure reason as it not conforming to Copyable
46324632
auto *copyable = ctx.getProtocol(KnownProtocolKind::Copyable);
46334633
assert(copyable && "missing _Copyable protocol!");
4634-
return CheckTypeWitnessResult(copyable->getDeclaredInterfaceType());
4634+
return CheckTypeWitnessResult::forConformance(copyable);
46354635
}
46364636

46374637
const auto depTy = DependentMemberType::get(proto->getSelfInterfaceType(),
@@ -4656,7 +4656,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
46564656
superclass = dc->mapTypeIntoContext(superclass);
46574657
}
46584658
if (!superclass->isExactSuperclassOf(contextType))
4659-
return superclass;
4659+
return CheckTypeWitnessResult::forSuperclass(superclass);
46604660
}
46614661

46624662
auto *module = dc->getParentModule();
@@ -4668,7 +4668,7 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
46684668
/*allowMissing=*/reqProto->isSpecificProtocol(
46694669
KnownProtocolKind::Sendable))
46704670
.isInvalid())
4671-
return CheckTypeWitnessResult(reqProto->getDeclaredInterfaceType());
4671+
return CheckTypeWitnessResult::forConformance(reqProto);
46724672

46734673
// FIXME: Why is conformsToProtocol() not enough? The stdlib doesn't
46744674
// build unless we fail here while inferring an associated type
@@ -4681,17 +4681,17 @@ swift::checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
46814681
decl->getGenericEnvironmentOfContext());
46824682
for (auto replacement : subMap.getReplacementTypes()) {
46834683
if (replacement->hasError())
4684-
return CheckTypeWitnessResult(reqProto->getDeclaredInterfaceType());
4684+
return CheckTypeWitnessResult::forConformance(reqProto);
46854685
}
46864686
}
46874687
}
46884688

46894689
if (sig->requiresClass(depTy) &&
46904690
!contextType->satisfiesClassConstraint())
4691-
return CheckTypeWitnessResult(module->getASTContext().getAnyObjectType());
4691+
return CheckTypeWitnessResult::forLayout(module->getASTContext().getAnyObjectType());
46924692

46934693
// Success!
4694-
return CheckTypeWitnessResult();
4694+
return CheckTypeWitnessResult::forSuccess();
46954695
}
46964696

46974697
ResolveWitnessResult
@@ -4878,15 +4878,15 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup(
48784878
auto &diags = conformance->getDeclContext()->getASTContext().Diags;
48794879
for (auto candidate : nonViable) {
48804880
if (candidate.first->getDeclaredInterfaceType()->hasError() ||
4881-
candidate.second.isError())
4881+
candidate.second.getKind() == CheckTypeWitnessResult::Error)
48824882
continue;
48834883

48844884
diags.diagnose(
48854885
candidate.first,
48864886
diag::protocol_witness_nonconform_type,
48874887
candidate.first->getDeclaredInterfaceType(),
48884888
candidate.second.getRequirement(),
4889-
candidate.second.isConformanceRequirement());
4889+
candidate.second.getKind() != CheckTypeWitnessResult::Superclass);
48904890
}
48914891
});
48924892

lib/Sema/TypeCheckProtocol.h

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,61 @@ struct TypeWitnessConflict {
7272
///
7373
/// This class evaluates true if an error occurred.
7474
class CheckTypeWitnessResult {
75-
Type Requirement;
75+
public:
76+
enum Kind {
77+
Success,
78+
79+
/// Type witness contains an error type.
80+
Error,
81+
82+
/// Type witness does not satisfy a conformance requirement on
83+
/// the associated type.
84+
Conformance,
85+
86+
/// Type witness does not satisfy a superclass requirement on
87+
/// the associated type.
88+
Superclass,
89+
90+
/// Type witness does not satisfy a layout requirement on
91+
/// the associated type.
92+
Layout
93+
} kind;
94+
95+
private:
96+
Type reqt;
97+
98+
CheckTypeWitnessResult() : kind(Success) {}
99+
100+
CheckTypeWitnessResult(Kind kind, Type reqt)
101+
: kind(kind), reqt(reqt) {}
76102

77103
public:
78-
CheckTypeWitnessResult() { }
79-
CheckTypeWitnessResult(Type reqt) : Requirement(reqt) {}
104+
static CheckTypeWitnessResult forSuccess() {
105+
return CheckTypeWitnessResult(Success, Type());
106+
}
80107

81-
Type getRequirement() const { return Requirement; }
82-
bool isConformanceRequirement() const {
83-
return Requirement->isExistentialType();
108+
static CheckTypeWitnessResult forError() {
109+
return CheckTypeWitnessResult(Error, Type());
84110
}
85-
bool isSuperclassRequirement() const {
86-
return !isConformanceRequirement();
111+
112+
static CheckTypeWitnessResult forConformance(ProtocolDecl *proto) {
113+
auto reqt = proto->getDeclaredInterfaceType();
114+
return CheckTypeWitnessResult(Conformance, reqt);
87115
}
88-
bool isError() const {
89-
return Requirement->is<ErrorType>();
116+
117+
static CheckTypeWitnessResult forSuperclass(Type reqt) {
118+
assert(reqt->getClassOrBoundGenericClass());
119+
return CheckTypeWitnessResult(Superclass, reqt);
90120
}
91-
explicit operator bool() const { return !Requirement.isNull(); }
121+
122+
static CheckTypeWitnessResult forLayout(Type reqt) {
123+
return CheckTypeWitnessResult(Layout, reqt);
124+
}
125+
126+
Kind getKind() const { return kind; }
127+
Type getRequirement() const { return reqt; }
128+
129+
explicit operator bool() const { return kind != Success; }
92130
};
93131

94132
/// Check whether the given type witness can be used for the given
@@ -1057,7 +1095,7 @@ class AssociatedTypeInference {
10571095
/// Information about a failed, defaulted associated type.
10581096
const AssociatedTypeDecl *failedDefaultedAssocType = nullptr;
10591097
Type failedDefaultedWitness;
1060-
CheckTypeWitnessResult failedDefaultedResult;
1098+
CheckTypeWitnessResult failedDefaultedResult = CheckTypeWitnessResult::forSuccess();
10611099

10621100
/// Information about a failed, derived associated type.
10631101
AssociatedTypeDecl *failedDerivedAssocType = nullptr;

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,10 +1407,10 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
14071407
// witness failure and we haven't seen one already, write it down.
14081408
auto *defaultedAssocType = witness.getDefaultedAssocType();
14091409
if (defaultedAssocType && !failedDefaultedAssocType &&
1410-
!failed.isError()) {
1410+
failed.getKind() != CheckTypeWitnessResult::Error) {
14111411
failedDefaultedAssocType = defaultedAssocType;
14121412
failedDefaultedWitness = type;
1413-
failedDefaultedResult = std::move(failed);
1413+
failedDefaultedResult = failed;
14141414
}
14151415

14161416
return assocType;
@@ -1942,7 +1942,7 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
19421942
failedDefaultedAssocType,
19431943
proto->getDeclaredInterfaceType(),
19441944
failedDefaultedResult.getRequirement(),
1945-
failedDefaultedResult.isConformanceRequirement());
1945+
failedDefaultedResult.getKind() != CheckTypeWitnessResult::Superclass);
19461946
});
19471947

19481948
return true;
@@ -1977,12 +1977,12 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
19771977
diags.diagnose(assocType, diag::bad_associated_type_deduction,
19781978
assocType, proto);
19791979
for (const auto &failed : failedSet) {
1980-
if (failed.Result.isError())
1980+
if (failed.Result.getKind() == CheckTypeWitnessResult::Error)
19811981
continue;
19821982

19831983
if ((!failed.TypeWitness->getAnyNominal() ||
19841984
failed.TypeWitness->isExistentialType()) &&
1985-
failed.Result.isConformanceRequirement()) {
1985+
failed.Result.getKind() != CheckTypeWitnessResult::Superclass) {
19861986
Type resultType;
19871987
SourceRange typeRange;
19881988
if (auto *var = dyn_cast<VarDecl>(failed.Witness)) {
@@ -2018,7 +2018,7 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
20182018
continue;
20192019
}
20202020
if (!failed.TypeWitness->getClassOrBoundGenericClass() &&
2021-
failed.Result.isSuperclassRequirement()) {
2021+
failed.Result.getKind() == CheckTypeWitnessResult::Superclass) {
20222022
diags.diagnose(failed.Witness,
20232023
diag::associated_type_witness_inherit_impossible,
20242024
assocType, failed.TypeWitness,
@@ -2030,7 +2030,7 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
20302030
diag::associated_type_deduction_witness_failed,
20312031
assocType, failed.TypeWitness,
20322032
failed.Result.getRequirement(),
2033-
failed.Result.isConformanceRequirement());
2033+
failed.Result.getKind() != CheckTypeWitnessResult::Superclass);
20342034
}
20352035
});
20362036

0 commit comments

Comments
 (0)