Make LookupConformanceFn callbacks return Optional<ProtocolConformanceRef>.

NFC yet, but this is a step toward centralizing error handling policy for failed conformance lookups instead of leaving it ad-hoc.
This commit is contained in:
Joe Groff
2016-12-14 18:04:35 -08:00
parent 55bdf5954c
commit ccfabd1118
5 changed files with 38 additions and 37 deletions

View File

@@ -129,9 +129,10 @@ public:
SubstitutionMap &subMap) const; SubstitutionMap &subMap) const;
using LookupConformanceFn = using LookupConformanceFn =
llvm::function_ref<ProtocolConformanceRef(CanType dependentType, llvm::function_ref<auto(CanType dependentType,
Type conformingReplacementType, Type conformingReplacementType,
ProtocolType *conformedProtocol)>; ProtocolType *conformedProtocol)
-> Optional<ProtocolConformanceRef>>;
/// Build an array of substitutions from an interface type substitution map, /// Build an array of substitutions from an interface type substitution map,
/// using the given function to look up conformances. /// using the given function to look up conformances.

View File

@@ -277,9 +277,9 @@ ArrayRef<Substitution>
GenericEnvironment::getForwardingSubstitutions(ModuleDecl *M) const { GenericEnvironment::getForwardingSubstitutions(ModuleDecl *M) const {
auto lookupConformanceFn = auto lookupConformanceFn =
[&](CanType original, Type replacement, ProtocolType *protoType) [&](CanType original, Type replacement, ProtocolType *protoType)
-> ProtocolConformanceRef { -> Optional<ProtocolConformanceRef> {
return ProtocolConformanceRef(protoType->getDecl()); return ProtocolConformanceRef(protoType->getDecl());
}; };
SmallVector<Substitution, 4> result; SmallVector<Substitution, 4> result;
getGenericSignature()->getSubstitutions(*M, getGenericSignature()->getSubstitutions(*M,

View File

@@ -315,9 +315,10 @@ getSubstitutions(ModuleDecl &mod,
for (auto req: reqs) { for (auto req: reqs) {
assert(req.getKind() == RequirementKind::Conformance); assert(req.getKind() == RequirementKind::Conformance);
auto protoType = req.getSecondType()->castTo<ProtocolType>(); auto protoType = req.getSecondType()->castTo<ProtocolType>();
// TODO: Error handling for failed conformance lookup.
currentConformances.push_back( currentConformances.push_back(
lookupConformance(depTy->getCanonicalType(), currentReplacement, *lookupConformance(depTy->getCanonicalType(), currentReplacement,
protoType)); protoType));
} }
// Add it to the final substitution list. // Add it to the final substitution list.
@@ -336,9 +337,9 @@ getSubstitutions(ModuleDecl &mod,
SmallVectorImpl<Substitution> &result) const { SmallVectorImpl<Substitution> &result) const {
auto lookupConformanceFn = auto lookupConformanceFn =
[&](CanType original, Type replacement, ProtocolType *protoType) [&](CanType original, Type replacement, ProtocolType *protoType)
-> ProtocolConformanceRef { -> Optional<ProtocolConformanceRef> {
return *subMap.lookupConformance(original, protoType->getDecl()); return subMap.lookupConformance(original, protoType->getDecl());
}; };
getSubstitutions(mod, subMap.getMap(), lookupConformanceFn, result); getSubstitutions(mod, subMap.getMap(), lookupConformanceFn, result);
} }

View File

@@ -628,24 +628,25 @@ TypeBase::gatherAllSubstitutions(Module *module,
auto lookupConformanceFn = auto lookupConformanceFn =
[&](CanType original, Type replacement, ProtocolType *protoType) [&](CanType original, Type replacement, ProtocolType *protoType)
-> ProtocolConformanceRef { -> Optional<ProtocolConformanceRef> {
auto *proto = protoType->getDecl();
auto *proto = protoType->getDecl();
// If the type is a type variable or is dependent, just fill in empty
// If the type is a type variable or is dependent, just fill in empty // conformances.
// conformances. if (replacement->isTypeVariableOrMember() ||
if (replacement->isTypeVariableOrMember() || replacement->isTypeParameter())
replacement->isTypeParameter()) return ProtocolConformanceRef(proto);
return ProtocolConformanceRef(proto);
// Otherwise, try to find the conformance.
// Otherwise, find the conformance. auto conforms = module->lookupConformance(replacement, proto, resolver);
auto conforms = module->lookupConformance(replacement, proto, resolver); if (conforms)
if (conforms) return *conforms;
return *conforms;
// FIXME: Should we ever end up here?
// FIXME: Should we ever end up here? // We should return None and let getSubstitutions handle the error
return ProtocolConformanceRef(proto); // if we do.
}; return ProtocolConformanceRef(proto);
};
SmallVector<Substitution, 4> result; SmallVector<Substitution, 4> result;
genericSig->getSubstitutions(*module, substitutions, genericSig->getSubstitutions(*module, substitutions,

View File

@@ -108,20 +108,18 @@ Type Solution::computeSubstitutions(
auto lookupConformanceFn = auto lookupConformanceFn =
[&](CanType original, Type replacement, ProtocolType *protoType) [&](CanType original, Type replacement, ProtocolType *protoType)
-> ProtocolConformanceRef { -> Optional<ProtocolConformanceRef> {
if (replacement->hasError() || if (replacement->hasError() ||
isOpenedAnyObject(replacement) || isOpenedAnyObject(replacement) ||
replacement->is<GenericTypeParamType>()) { replacement->is<GenericTypeParamType>()) {
return ProtocolConformanceRef(protoType->getDecl()); return ProtocolConformanceRef(protoType->getDecl());
} }
auto conformance = tc.conformsToProtocol( return tc.conformsToProtocol(replacement,
replacement, protoType->getDecl(),
protoType->getDecl(), getConstraintSystem().DC,
getConstraintSystem().DC, (ConformanceCheckFlags::InExpression|
(ConformanceCheckFlags::InExpression| ConformanceCheckFlags::Used));
ConformanceCheckFlags::Used));
return *conformance;
}; };
sig->getSubstitutions(*mod, subs, lookupConformanceFn, result); sig->getSubstitutions(*mod, subs, lookupConformanceFn, result);