Skip to content

Commit a31edf5

Browse files
committed
Simplify the interface to Module::lookupConformance.
Rather than returning a weird PointerIntPair, return an Optional<ProtocolConformanceRef>. NFC
1 parent b051c5a commit a31edf5

File tree

15 files changed

+122
-175
lines changed

15 files changed

+122
-175
lines changed

include/swift/AST/Module.h

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,6 @@ enum ASTNameLookupFlags {
147147
NL_RemoveNonVisible | NL_RemoveOverridden
148148
};
149149

150-
/// Describes the result of looking for the conformance of a given type
151-
/// to a specific protocol.
152-
enum class ConformanceKind {
153-
/// The type does not conform to the protocol.
154-
DoesNotConform,
155-
/// The type conforms to the protocol, with the given conformance.
156-
Conforms,
157-
};
158-
159-
/// The result of looking for a specific conformance.
160-
typedef llvm::PointerIntPair<ProtocolConformance *, 2, ConformanceKind>
161-
LookupConformanceResult;
162-
163150
/// Discriminator for file-units.
164151
enum class FileUnitKind {
165152
/// For a .swift source file.
@@ -386,24 +373,18 @@ class ModuleDecl : public TypeDecl, public DeclContext {
386373
/// Look for the conformance of the given type to the given protocol.
387374
///
388375
/// This routine determines whether the given \c type conforms to the given
389-
/// \c protocol. It only looks for explicit conformances (which are
390-
/// required by the language), and will return a \c ProtocolConformance*
391-
/// describing the conformance.
392-
///
393-
/// During type-checking, it is possible that this routine will find an
394-
/// explicit declaration of conformance that has not yet been type-checked,
395-
/// in which case it will return note the presence of an unchecked
396-
/// conformance.
376+
/// \c protocol.
397377
///
398378
/// \param type The type for which we are computing conformance.
399379
///
400380
/// \param protocol The protocol to which we are computing conformance.
401381
///
402382
/// \param resolver The lazy resolver.
403383
///
404-
/// \returns The result of the conformance search, with a conformance
405-
/// structure when possible.
406-
LookupConformanceResult
384+
/// \returns The result of the conformance search, which will be
385+
/// None if the type does not conform to the protocol or contain a
386+
/// ProtocolConformanceRef if it does conform.
387+
Optional<ProtocolConformanceRef>
407388
lookupConformance(Type type, ProtocolDecl *protocol, LazyResolver *resolver);
408389

409390
/// Find a member named \p name in \p container that was declared in this

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3605,13 +3605,7 @@ ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
36053605
// Check whether the type conforms to _BridgedToObjectiveC.
36063606
auto conformance
36073607
= dc->getParentModule()->lookupConformance(type, bridgedProto, resolver);
3608-
3609-
switch (conformance.getInt()) {
3610-
case ConformanceKind::Conforms:
3611-
// The type conforms, and we know the conformance, so we can look up the
3612-
// bridged type below.
3613-
break;
3614-
case ConformanceKind::DoesNotConform:
3608+
if (!conformance) {
36153609
// If we haven't imported Foundation but this is a whitelisted type,
36163610
// behave as above.
36173611
if (knownBridgedToObjC)
@@ -3621,7 +3615,7 @@ ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
36213615

36223616
// Find the type we bridge to.
36233617
return ProtocolConformance::getTypeWitnessByName(type,
3624-
conformance.getPointer(),
3618+
conformance->getConcrete(),
36253619
getIdentifier("_ObjectiveCType"),
36263620
resolver);
36273621
}

lib/AST/ArchetypeBuilder.cpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -280,20 +280,15 @@ static ProtocolConformance *getSuperConformance(
280280
auto conformance =
281281
builder.getModule().lookupConformance(superclass, proto,
282282
builder.getLazyResolver());
283-
switch (conformance.getInt()) {
284-
case ConformanceKind::Conforms: {
285-
// Conformance to this protocol is redundant; update the requirement source
286-
// appropriately.
287-
updateRequirementSource(
288-
conformsSource,
289-
RequirementSource(RequirementSource::Protocol,
290-
pa->getSuperclassSource().getLoc()));
291-
return conformance.getPointer();
292-
}
283+
if (!conformance) return nullptr;
293284

294-
case ConformanceKind::DoesNotConform:
295-
return nullptr;
296-
}
285+
// Conformance to this protocol is redundant; update the requirement source
286+
// appropriately.
287+
updateRequirementSource(
288+
conformsSource,
289+
RequirementSource(RequirementSource::Protocol,
290+
pa->getSuperclassSource().getLoc()));
291+
return conformance->getConcrete();
297292
}
298293

299294
/// If there is a same-type requirement to be added for the given nested type
@@ -1217,15 +1212,15 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
12171212
auto protocol = conforms.first;
12181213
auto conformance = Mod.lookupConformance(Concrete, protocol,
12191214
getLazyResolver());
1220-
if (conformance.getInt() == ConformanceKind::DoesNotConform) {
1215+
if (!conformance) {
12211216
Diags.diagnose(Source.getLoc(),
12221217
diag::requires_generic_param_same_type_does_not_conform,
12231218
Concrete, protocol->getName());
12241219
return true;
12251220
}
12261221

1227-
assert(conformance.getPointer() && "No conformance pointer?");
1228-
conformances[protocol] = conformance.getPointer();
1222+
assert(conformance->isConcrete() && "Abstract conformance?");
1223+
conformances[protocol] = conformance->getConcrete();
12291224
}
12301225
}
12311226

lib/AST/ConformanceLookupTable.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,9 @@ ProtocolConformance *ConformanceLookupTable::getConformance(
815815
.getPointer();
816816

817817
// Form the inherited conformance.
818-
conformance = ctx.getInheritedConformance(type, inheritedConformance);
818+
conformance = ctx.getInheritedConformance(
819+
type,
820+
inheritedConformance->getConcrete());
819821
} else {
820822
// Create or find the normal conformance.
821823
Type conformingType = conformingDC->getDeclaredTypeInContext();

lib/AST/Module.cpp

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -739,23 +739,17 @@ ArrayRef<Substitution> BoundGenericType::getSubstitutions(
739739

740740
SmallVector<ProtocolConformanceRef, 4> conformances;
741741
for (auto proto : archetype->getConformsTo()) {
742-
// If the type is a type variable or is dependent, just fill in null
742+
// If the type is a type variable or is dependent, just fill in empty
743743
// conformances.
744744
if (type->is<TypeVariableType>() || type->isTypeParameter()) {
745745
conformances.push_back(ProtocolConformanceRef(proto));
746746

747747
// Otherwise, find the conformances.
748748
} else {
749-
auto conforms = module->lookupConformance(type, proto, resolver);
750-
switch (conforms.getInt()) {
751-
case ConformanceKind::Conforms:
752-
conformances.push_back(
753-
ProtocolConformanceRef(proto, conforms.getPointer()));
754-
break;
755-
case ConformanceKind::DoesNotConform:
749+
if (auto conforms = module->lookupConformance(type, proto, resolver))
750+
conformances.push_back(*conforms);
751+
else
756752
conformances.push_back(ProtocolConformanceRef(proto));
757-
break;
758-
}
759753
}
760754
}
761755

@@ -778,28 +772,28 @@ ArrayRef<Substitution> BoundGenericType::getSubstitutions(
778772
return permanentSubs;
779773
}
780774

781-
LookupConformanceResult Module::lookupConformance(Type type,
782-
ProtocolDecl *protocol,
783-
LazyResolver *resolver) {
775+
Optional<ProtocolConformanceRef>
776+
Module::lookupConformance(Type type, ProtocolDecl *protocol,
777+
LazyResolver *resolver) {
784778
ASTContext &ctx = getASTContext();
785779

786780
// An archetype conforms to a protocol if the protocol is listed in the
787781
// archetype's list of conformances.
788782
if (auto archetype = type->getAs<ArchetypeType>()) {
789783
if (protocol->isSpecificProtocol(KnownProtocolKind::AnyObject)) {
790784
if (archetype->requiresClass())
791-
return { nullptr, ConformanceKind::Conforms };
792-
return { nullptr, ConformanceKind::DoesNotConform };
785+
return ProtocolConformanceRef(protocol);
786+
787+
return None;
793788
}
794789

795790
for (auto ap : archetype->getConformsTo()) {
796791
if (ap == protocol || ap->inheritsFrom(protocol))
797-
return { nullptr, ConformanceKind::Conforms };
792+
return ProtocolConformanceRef(protocol);
798793
}
799794

800-
if (!archetype->getSuperclass()) {
801-
return { nullptr, ConformanceKind::DoesNotConform };
802-
}
795+
if (!archetype->getSuperclass())
796+
return None;
803797
}
804798

805799
// An existential conforms to a protocol if the protocol is listed in the
@@ -815,74 +809,68 @@ LookupConformanceResult Module::lookupConformance(Type type,
815809
for (auto proto : protocols) {
816810
if (!proto->isObjC() &&
817811
!proto->isSpecificProtocol(KnownProtocolKind::AnyObject))
818-
return { nullptr, ConformanceKind::DoesNotConform };
812+
return None;
819813
}
820814

821815
// If the existential type cannot be represented or the protocol does not
822816
// conform to itself, there's no point in looking further.
823817
if (!protocol->existentialConformsToSelf() ||
824818
!protocol->existentialTypeSupported(resolver))
825-
return { nullptr, ConformanceKind::DoesNotConform };
819+
return None;
826820

827821
// Special-case AnyObject, which may not be in the list of conformances.
828822
if (protocol->isSpecificProtocol(KnownProtocolKind::AnyObject)) {
829-
return { nullptr, type->isClassExistentialType()
830-
? ConformanceKind::Conforms
831-
: ConformanceKind::DoesNotConform };
823+
if (type->isClassExistentialType())
824+
return ProtocolConformanceRef(protocol);
825+
826+
return None;
832827
}
833828

834829
// Look for this protocol within the existential's list of conformances.
835830
for (auto proto : protocols) {
836-
if (proto == protocol || proto->inheritsFrom(protocol)) {
837-
return { nullptr, ConformanceKind::Conforms };
838-
}
831+
if (proto == protocol || proto->inheritsFrom(protocol))
832+
return ProtocolConformanceRef(protocol);
839833
}
840834

841835
// We didn't find our protocol in the existential's list; it doesn't
842836
// conform.
843-
return { nullptr, ConformanceKind::DoesNotConform };
837+
return None;
844838
}
845839

846840
// Check for protocol conformance of archetype via superclass requirement.
847841
if (auto archetype = type->getAs<ArchetypeType>()) {
848842
if (auto super = archetype->getSuperclass()) {
849-
auto inheritedConformance = lookupConformance(super, protocol, resolver);
850-
switch (inheritedConformance.getInt()) {
851-
case ConformanceKind::DoesNotConform:
852-
return { nullptr, ConformanceKind::DoesNotConform };
853-
case ConformanceKind::Conforms:
854-
auto result =
855-
ctx.getInheritedConformance(type, inheritedConformance.getPointer());
856-
return { result, ConformanceKind::Conforms };
843+
if (auto inheritedConformance = lookupConformance(super, protocol,
844+
resolver)) {
845+
return ProtocolConformanceRef(
846+
ctx.getInheritedConformance(
847+
type,
848+
inheritedConformance->getConcrete()));
857849
}
850+
851+
return None;
858852
}
859853
}
860854

861855
// UnresolvedType is a placeholder for an unknown type used when generating
862856
// diagnostics. We consider it to conform to all protocols, since the
863857
// intended type might have.
864858
if (type->is<UnresolvedType>()) {
865-
return {
866-
ctx.getConformance(type, protocol, protocol->getLoc(), this,
867-
ProtocolConformanceState::Complete),
868-
ConformanceKind::Conforms
869-
};
859+
return ProtocolConformanceRef(
860+
ctx.getConformance(type, protocol, protocol->getLoc(), this,
861+
ProtocolConformanceState::Complete));
870862
}
871863

872864

873865
auto nominal = type->getAnyNominal();
874866

875867
// If we don't have a nominal type, there are no conformances.
876-
// FIXME: We may have implicit conformances for some cases. Handle those
877-
// here.
878-
if (!nominal) {
879-
return { nullptr, ConformanceKind::DoesNotConform };
880-
}
868+
if (!nominal) return None;
881869

882870
// Find the (unspecialized) conformance.
883871
SmallVector<ProtocolConformance *, 2> conformances;
884872
if (!nominal->lookupConformance(this, protocol, conformances))
885-
return { nullptr, ConformanceKind::DoesNotConform };
873+
return None;
886874

887875
// FIXME: Ambiguity resolution.
888876
auto conformance = conformances.front();
@@ -905,19 +893,13 @@ LookupConformanceResult Module::lookupConformance(Type type,
905893
// Compute the conformance for the inherited type.
906894
auto inheritedConformance = lookupConformance(superclassTy, protocol,
907895
resolver);
908-
switch (inheritedConformance.getInt()) {
909-
case ConformanceKind::DoesNotConform:
910-
llvm_unreachable("We already found the inherited conformance");
911-
912-
case ConformanceKind::Conforms:
913-
// Create inherited conformance below.
914-
break;
915-
}
896+
assert(inheritedConformance &&
897+
"We already found the inherited conformance");
916898

917899
// Create the inherited conformance entry.
918900
conformance
919-
= ctx.getInheritedConformance(type, inheritedConformance.getPointer());
920-
return { conformance, ConformanceKind::Conforms };
901+
= ctx.getInheritedConformance(type, inheritedConformance->getConcrete());
902+
return ProtocolConformanceRef(conformance);
921903
}
922904

923905
// If the type is specialized, find the conformance for the generic type.
@@ -938,18 +920,18 @@ LookupConformanceResult Module::lookupConformance(Type type,
938920

939921
for (auto sub : substitutions) {
940922
if (sub.getReplacement()->is<ErrorType>())
941-
return { nullptr, ConformanceKind::DoesNotConform };
923+
return None;
942924
}
943925

944926
// Create the specialized conformance entry.
945927
auto result = ctx.getSpecializedConformance(type, conformance,
946928
substitutions);
947-
return { result, ConformanceKind::Conforms };
929+
return ProtocolConformanceRef(result);
948930
}
949931
}
950932

951933
// Record and return the simple conformance.
952-
return { conformance, ConformanceKind::Conforms };
934+
return ProtocolConformanceRef(conformance);
953935
}
954936

955937
namespace {

lib/AST/ProtocolConformance.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,12 +358,13 @@ SpecializedProtocolConformance::getTypeWitnessSubstAndDecl(
358358
for (auto proto : assocType->getConformingProtocols(resolver)) {
359359
auto conforms = conformingModule->lookupConformance(specializedType, proto,
360360
resolver);
361-
assert((conforms.getInt() == ConformanceKind::Conforms ||
361+
assert((conforms ||
362362
specializedType->is<TypeVariableType>() ||
363363
specializedType->isTypeParameter() ||
364364
specializedType->is<ErrorType>()) &&
365365
"Improperly checked substitution");
366-
conformances.push_back(ProtocolConformanceRef(proto, conforms.getPointer()));
366+
conformances.push_back(conforms ? *conforms
367+
: ProtocolConformanceRef(proto));
367368
}
368369

369370
// Form the substitution.

lib/AST/Type.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,24 +2407,21 @@ static Type getMemberForBaseType(Module *module,
24072407
auto proto = assocType->getProtocol();
24082408
// FIXME: Introduce substituted type node here?
24092409
auto conformance = module->lookupConformance(substBase, proto, resolver);
2410-
switch (conformance.getInt()) {
2411-
case ConformanceKind::DoesNotConform:
2410+
if (!conformance)
24122411
return Type();
24132412

2414-
case ConformanceKind::Conforms:
2415-
// If we have an unsatisfied type witness while we're checking the
2416-
// conformances we're supposed to skip this conformance's unsatisfied type
2417-
// witnesses, and we have an unsatisfied type witness, return
2418-
// "missing".
2419-
assert(conformance.getPointer());
2420-
if (conformance.getPointer()->getRootNormalConformance()->getState()
2421-
== ProtocolConformanceState::CheckingTypeWitnesses &&
2422-
!conformance.getPointer()->hasTypeWitness(assocType, nullptr))
2423-
return Type();
2413+
// If we have an unsatisfied type witness while we're checking the
2414+
// conformances we're supposed to skip this conformance's unsatisfied type
2415+
// witnesses, and we have an unsatisfied type witness, return
2416+
// "missing".
2417+
assert(conformance->isConcrete());
2418+
if (conformance->getConcrete()->getRootNormalConformance()->getState()
2419+
== ProtocolConformanceState::CheckingTypeWitnesses &&
2420+
!conformance->getConcrete()->hasTypeWitness(assocType, nullptr))
2421+
return Type();
24242422

2425-
return conformance.getPointer()->getTypeWitness(assocType, resolver)
2426-
.getReplacement();
2427-
}
2423+
return conformance->getConcrete()->getTypeWitness(assocType, resolver)
2424+
.getReplacement();
24282425
}
24292426

24302427
// FIXME: This is a fallback. We want the above, conformance-based

0 commit comments

Comments
 (0)