diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 08b7e6877e0d4..414f9707ebb44 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -4380,9 +4380,9 @@ class ProtocolDecl final : public NominalTypeDecl { /// Returns the default associated conformance witness for an associated /// type, or \c None if there is no default. - Optional getDefaultAssociatedConformanceWitness( - CanType association, - ProtocolDecl *requirement) const; + ProtocolConformanceRef + getDefaultAssociatedConformanceWitness(CanType association, + ProtocolDecl *requirement) const; /// Set the default associated conformance witness for the given /// associated conformance. diff --git a/include/swift/AST/GenericSignature.h b/include/swift/AST/GenericSignature.h index 57d6f51d85f61..73752529da278 100644 --- a/include/swift/AST/GenericSignature.h +++ b/include/swift/AST/GenericSignature.h @@ -269,8 +269,8 @@ class alignas(1 << TypeAlignInBits) GenericSignatureImpl final /// Look up a stored conformance in the generic signature. These are formed /// from same-type constraints placed on associated types of generic /// parameters which have conformance constraints on them. - Optional - lookupConformance(CanType depTy, ProtocolDecl *proto) const; + ProtocolConformanceRef lookupConformance(CanType depTy, + ProtocolDecl *proto) const; /// Iterate over all generic parameters, passing a flag to the callback /// indicating if the generic parameter is canonical or not. diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h index ba6a43eeb3b09..046cd24d1ffe8 100644 --- a/include/swift/AST/GenericSignatureBuilder.h +++ b/include/swift/AST/GenericSignatureBuilder.h @@ -519,10 +519,9 @@ class GenericSignatureBuilder { explicit LookUpConformanceInBuilder(GenericSignatureBuilder *builder) : builder(builder) {} - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { return builder->lookupConformance(dependentType, conformingReplacementType, conformedProtocol); @@ -534,10 +533,9 @@ class GenericSignatureBuilder { LookUpConformanceInBuilder getLookupConformanceFn(); /// Lookup a protocol conformance in a module-agnostic manner. - Optional - lookupConformance(CanType dependentType, Type conformingReplacementType, - ProtocolDecl *conformedProtocol); - + ProtocolConformanceRef lookupConformance(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol); /// Retrieve the lazy resolver, if there is one. LazyResolver *getLazyResolver() const; diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index e74e344c20f31..84bd5df460a24 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -409,19 +409,18 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// \returns The result of the conformance search, which will be /// None if the type does not conform to the protocol or contain a /// ProtocolConformanceRef if it does conform. - Optional - lookupConformance(Type type, ProtocolDecl *protocol); + ProtocolConformanceRef lookupConformance(Type type, ProtocolDecl *protocol); /// Look for the conformance of the given existential type to the given /// protocol. - Optional - lookupExistentialConformance(Type type, ProtocolDecl *protocol); + ProtocolConformanceRef lookupExistentialConformance(Type type, + ProtocolDecl *protocol); /// Exposes TypeChecker functionality for querying protocol conformance. /// Returns a valid ProtocolConformanceRef only if all conditional /// requirements are successfully resolved. - Optional - conformsToProtocol(Type sourceTy, ProtocolDecl *targetProtocol); + ProtocolConformanceRef conformsToProtocol(Type sourceTy, + ProtocolDecl *targetProtocol); /// Find a member named \p name in \p container that was declared in this /// module. diff --git a/include/swift/AST/ProtocolConformanceRef.h b/include/swift/AST/ProtocolConformanceRef.h index 9a706a27802ad..92efcaa3600e3 100644 --- a/include/swift/AST/ProtocolConformanceRef.h +++ b/include/swift/AST/ProtocolConformanceRef.h @@ -63,14 +63,19 @@ class ProtocolConformanceRef { "cannot construct ProtocolConformanceRef with null"); } + ProtocolConformanceRef(std::nullptr_t = nullptr) + : Union((ProtocolDecl *)nullptr) {} + static ProtocolConformanceRef forInvalid() { - return ProtocolConformanceRef(UnionType((ProtocolDecl *)nullptr)); + return ProtocolConformanceRef(); } bool isInvalid() const { return !Union; } + explicit operator bool() const { return !isInvalid(); } + /// Create either a concrete or an abstract protocol conformance reference, /// depending on whether ProtocolConformance is null. explicit ProtocolConformanceRef(ProtocolDecl *protocol, diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h index 049cb549accb0..13a17e1c557a6 100644 --- a/include/swift/AST/Stmt.h +++ b/include/swift/AST/Stmt.h @@ -805,7 +805,7 @@ class ForEachStmt : public LabeledStmt { BraceStmt *Body; // Set by Sema: - Optional sequenceConformance; + ProtocolConformanceRef sequenceConformance = ProtocolConformanceRef(); ConcreteDeclRef makeIterator; ConcreteDeclRef iteratorNext; VarDecl *iteratorVar = nullptr; @@ -842,10 +842,10 @@ class ForEachStmt : public LabeledStmt { void setIteratorNext(ConcreteDeclRef declRef) { iteratorNext = declRef; } ConcreteDeclRef getIteratorNext() const { return iteratorNext; } - void setSequenceConformance(Optional conformance) { + void setSequenceConformance(ProtocolConformanceRef conformance) { sequenceConformance = conformance; } - Optional getSequenceConformance() const { + ProtocolConformanceRef getSequenceConformance() const { return sequenceConformance; } diff --git a/include/swift/AST/SubstitutionMap.h b/include/swift/AST/SubstitutionMap.h index e01edc3409a08..893838213445a 100644 --- a/include/swift/AST/SubstitutionMap.h +++ b/include/swift/AST/SubstitutionMap.h @@ -128,8 +128,8 @@ class SubstitutionMap { ArrayRef getConformances() const; /// Look up a conformance for the given type to the given protocol. - Optional - lookupConformance(CanType type, ProtocolDecl *proto) const; + ProtocolConformanceRef lookupConformance(CanType type, + ProtocolDecl *proto) const; /// Whether the substitution map is empty. bool empty() const; @@ -290,11 +290,10 @@ class LookUpConformanceInSubstitutionMap { public: explicit LookUpConformanceInSubstitutionMap(SubstitutionMap Subs) : Subs(Subs) {} - - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const; + + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const; }; } // end namespace swift diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h index 9e0422b9eb5d0..f597d87e188eb 100644 --- a/include/swift/AST/Type.h +++ b/include/swift/AST/Type.h @@ -93,7 +93,7 @@ struct QueryTypeSubstitutionMapOrIdentity { using GenericFunction = auto(CanType dependentType, Type conformingReplacementType, ProtocolDecl *conformedProtocol) - -> Optional; + -> ProtocolConformanceRef; using LookupConformanceFn = llvm::function_ref; /// Functor class suitable for use as a \c LookupConformanceFn to look up a @@ -103,11 +103,10 @@ class LookUpConformanceInModule { public: explicit LookUpConformanceInModule(ModuleDecl *M) : M(M) {} - - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const; + + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const; }; /// Functor class suitable for use as a \c LookupConformanceFn that provides @@ -115,10 +114,9 @@ class LookUpConformanceInModule { /// type is an opaque generic type. class MakeAbstractConformanceForGenericType { public: - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const; + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const; }; /// Functor class suitable for use as a \c LookupConformanceFn that fetches @@ -130,11 +128,10 @@ class LookUpConformanceInSignature { : Sig(Sig) { assert(Sig && "Cannot lookup conformance in null signature!"); } - - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const; + + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const; }; /// Flags that can be passed when substituting into a type. diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 84d47f4b63bf5..739bd98d19fe1 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -3826,7 +3826,7 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, // CanType? // if !isCoro && NumAnyResults > 1, all result cache llvm::PointerIntPair GenericSigAndIsImplied; - Optional WitnessMethodConformance; + ProtocolConformanceRef WitnessMethodConformance; SubstitutionMap Substitutions; MutableArrayRef getMutableParameters() { @@ -3888,25 +3888,22 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, ArrayRef yieldResults, ArrayRef normalResults, Optional errorResult, - SubstitutionMap substitutions, - bool genericSigIsImplied, - const ASTContext &ctx, - RecursiveTypeProperties properties, - Optional witnessMethodConformance); + SubstitutionMap substitutions, bool genericSigIsImplied, + const ASTContext &ctx, RecursiveTypeProperties properties, + ProtocolConformanceRef witnessMethodConformance); public: - static CanSILFunctionType get(GenericSignature genericSig, - ExtInfo ext, - SILCoroutineKind coroutineKind, - ParameterConvention calleeConvention, - ArrayRef interfaceParams, - ArrayRef interfaceYields, - ArrayRef interfaceResults, - Optional interfaceErrorResult, - SubstitutionMap substitutions, - bool genericSigIsImplied, - const ASTContext &ctx, - Optional witnessMethodConformance = None); + static CanSILFunctionType + get(GenericSignature genericSig, ExtInfo ext, SILCoroutineKind coroutineKind, + ParameterConvention calleeConvention, + ArrayRef interfaceParams, + ArrayRef interfaceYields, + ArrayRef interfaceResults, + Optional interfaceErrorResult, + SubstitutionMap substitutions, bool genericSigIsImplied, + const ASTContext &ctx, + ProtocolConformanceRef witnessMethodConformance = + ProtocolConformanceRef()); /// Return a structurally-identical function type with a slightly tweaked /// ExtInfo. @@ -4105,16 +4102,9 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, ClassDecl *getWitnessMethodClass(SILModule &M) const; /// If this is a @convention(witness_method) function, return the conformance - /// for which the method is a witness. - ProtocolConformanceRef getWitnessMethodConformance() const { - assert(getRepresentation() == Representation::WitnessMethod); - return *WitnessMethodConformance; - } - - /// If this is a @convention(witness_method) function, return the conformance - /// for which the method is a witness, if it isn't that convention, return - /// None. - Optional getWitnessMethodConformanceOrNone() const { + /// for which the method is a witness. If it isn't that convention, return + /// an invalid conformance. + ProtocolConformanceRef getWitnessMethodConformanceOrInvalid() const { return WitnessMethodConformance; } @@ -4209,24 +4199,17 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getSubstGenericSignature(), getExtInfo(), getCoroutineKind(), - getCalleeConvention(), getParameters(), getYields(), - getResults(), getOptionalErrorResult(), - getWitnessMethodConformanceOrNone(), - isGenericSignatureImplied(), - getSubstitutions()); - } - static void Profile(llvm::FoldingSetNodeID &ID, - GenericSignature genericSig, - ExtInfo info, - SILCoroutineKind coroutineKind, - ParameterConvention calleeConvention, - ArrayRef params, - ArrayRef yields, - ArrayRef results, - Optional errorResult, - Optional conformance, - bool isGenericSigImplied, - SubstitutionMap substitutions); + getCalleeConvention(), getParameters(), getYields(), getResults(), + getOptionalErrorResult(), getWitnessMethodConformanceOrInvalid(), + isGenericSignatureImplied(), getSubstitutions()); + } + static void + Profile(llvm::FoldingSetNodeID &ID, GenericSignature genericSig, ExtInfo info, + SILCoroutineKind coroutineKind, ParameterConvention calleeConvention, + ArrayRef params, ArrayRef yields, + ArrayRef results, Optional errorResult, + ProtocolConformanceRef conformance, bool isGenericSigImplied, + SubstitutionMap substitutions); // Implement isa/cast/dyncast/etc. static bool classof(const TypeBase *T) { @@ -4972,9 +4955,9 @@ class ReplaceOpaqueTypesWithUnderlyingTypes { Type operator()(SubstitutableType *maybeOpaqueType) const; /// LookupConformanceFn - Optional operator()(CanType maybeOpaqueType, - Type replacementType, - ProtocolDecl *protocol) const; + ProtocolConformanceRef operator()(CanType maybeOpaqueType, + Type replacementType, + ProtocolDecl *protocol) const; OpaqueSubstitutionKind shouldPerformSubstitution(OpaqueTypeDecl *opaque) const; diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 02a62dc355ce3..e2f4daa7eab46 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -587,11 +587,10 @@ NON_SIL_TYPE(LValue) CanSILFunctionType getNativeSILFunctionType( Lowering::TypeConverter &TC, Lowering::AbstractionPattern origType, - CanAnyFunctionType substType, - Optional origConstant = None, + CanAnyFunctionType substType, Optional origConstant = None, Optional constant = None, Optional reqtSubs = None, - Optional witnessMethodConformance = None); + ProtocolConformanceRef witnessMethodConformance = ProtocolConformanceRef()); inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILType T) { T.print(OS); diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 705c29a215bb9..874c4d5f34d30 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -72,16 +72,16 @@ inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t, CanSILFunctionType adjustFunctionType(CanSILFunctionType type, SILFunctionType::ExtInfo extInfo, ParameterConvention calleeConv, - Optional witnessMethodConformance); + ProtocolConformanceRef witnessMethodConformance); inline CanSILFunctionType adjustFunctionType(CanSILFunctionType type, SILFunctionType::ExtInfo extInfo, - Optional witnessMethodConformance) { + ProtocolConformanceRef witnessMethodConformance) { return adjustFunctionType(type, extInfo, type->getCalleeConvention(), witnessMethodConformance); } inline CanSILFunctionType adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep, - Optional witnessMethodConformance) { + ProtocolConformanceRef witnessMethodConformance) { if (t->getRepresentation() == rep) return t; auto extInfo = t->getExtInfo().withRepresentation(rep); auto contextConvention = DefaultThickCalleeConvention; diff --git a/include/swift/SILOptimizer/Utils/Existential.h b/include/swift/SILOptimizer/Utils/Existential.h index 39cb1beb302ae..75c88cf388f0a 100644 --- a/include/swift/SILOptimizer/Utils/Existential.h +++ b/include/swift/SILOptimizer/Utils/Existential.h @@ -98,8 +98,7 @@ struct ConcreteExistentialInfo { // Do a conformance lookup on ConcreteType with the given requirement, P. If P // is satisfiable based on the existential's conformance, return the new // conformance on P. Otherwise return None. - Optional - lookupExistentialConformance(ProtocolDecl *P) const { + ProtocolConformanceRef lookupExistentialConformance(ProtocolDecl *P) const { CanType selfTy = P->getSelfInterfaceType()->getCanonicalType(); return ExistentialSubs.lookupConformance(selfTy, P); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a294d093c715e..6802807a37942 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1060,14 +1060,14 @@ ASTContext::getBuiltinInitDecl(NominalTypeDecl *decl, auto builtinProtocol = getProtocol(builtinProtocolKind); auto builtinConformance = getStdlibModule()->lookupConformance( type, builtinProtocol); - if (!builtinConformance) { + if (builtinConformance.isInvalid()) { assert(false && "Missing required conformance"); witness = ConcreteDeclRef(); return witness; } auto *ctx = const_cast(this); - witness = builtinConformance->getWitnessByName(type, initName(*ctx)); + witness = builtinConformance.getWitnessByName(type, initName(*ctx)); if (!witness) { assert(false && "Missing required witness"); witness = ConcreteDeclRef(); @@ -1711,16 +1711,14 @@ void ProtocolDecl::setDefaultTypeWitness(AssociatedTypeDecl *assocType, (void)pair; } -Optional -ProtocolDecl::getDefaultAssociatedConformanceWitness( - CanType association, - ProtocolDecl *requirement) const { +ProtocolConformanceRef ProtocolDecl::getDefaultAssociatedConformanceWitness( + CanType association, ProtocolDecl *requirement) const { auto &ctx = getASTContext(); auto found = ctx.getImpl().DefaultAssociatedConformanceWitnesses.find( std::make_tuple(this, association, requirement)); if (found == ctx.getImpl().DefaultAssociatedConformanceWitnesses.end()) - return None; + return ProtocolConformanceRef::forInvalid(); return found->second; } @@ -3138,18 +3136,19 @@ ArrayRef GenericFunctionType::getRequirements() const { return Signature->getRequirements(); } -void SILFunctionType::Profile(llvm::FoldingSetNodeID &id, - GenericSignature genericParams, - ExtInfo info, - SILCoroutineKind coroutineKind, - ParameterConvention calleeConvention, - ArrayRef params, - ArrayRef yields, - ArrayRef results, - Optional errorResult, - Optional conformance, - bool isGenericSignatureImplied, - SubstitutionMap substitutions) { +void SILFunctionType::Profile( + llvm::FoldingSetNodeID &id, + GenericSignature genericParams, + ExtInfo info, + SILCoroutineKind coroutineKind, + ParameterConvention calleeConvention, + ArrayRef params, + ArrayRef yields, + ArrayRef results, + Optional errorResult, + ProtocolConformanceRef conformance, + bool isGenericSignatureImplied, + SubstitutionMap substitutions) { id.AddPointer(genericParams.getPointer()); id.AddInteger(info.getFuncAttrKey()); id.AddInteger(unsigned(coroutineKind)); @@ -3171,21 +3170,23 @@ void SILFunctionType::Profile(llvm::FoldingSetNodeID &id, substitutions.profile(id); id.AddBoolean((bool)conformance); if (conformance) - id.AddPointer(conformance->getRequirement()); -} - -SILFunctionType::SILFunctionType(GenericSignature genericSig, ExtInfo ext, - SILCoroutineKind coroutineKind, - ParameterConvention calleeConvention, - ArrayRef params, - ArrayRef yields, - ArrayRef normalResults, - Optional errorResult, - SubstitutionMap substitutions, - bool genericSigIsImplied, - const ASTContext &ctx, - RecursiveTypeProperties properties, - Optional witnessMethodConformance) + id.AddPointer(conformance.getRequirement()); +} + +SILFunctionType::SILFunctionType( + GenericSignature genericSig, + ExtInfo ext, + SILCoroutineKind coroutineKind, + ParameterConvention calleeConvention, + ArrayRef params, + ArrayRef yields, + ArrayRef normalResults, + Optional errorResult, + SubstitutionMap substitutions, + bool genericSigIsImplied, + const ASTContext &ctx, + RecursiveTypeProperties properties, + ProtocolConformanceRef witnessMethodConformance) : TypeBase(TypeKind::SILFunction, &ctx, properties), GenericSigAndIsImplied(CanGenericSignature(genericSig), genericSigIsImplied), @@ -3232,10 +3233,10 @@ SILFunctionType::SILFunctionType(GenericSignature genericSig, ExtInfo ext, } #ifndef NDEBUG if (ext.getRepresentation() == Representation::WitnessMethod) - assert(WitnessMethodConformance && + assert(!WitnessMethodConformance.isInvalid() && "witness_method SIL function without a conformance"); else - assert(!WitnessMethodConformance && + assert(WitnessMethodConformance.isInvalid() && "non-witness_method SIL function with a conformance"); // Make sure the type follows invariants. @@ -3313,18 +3314,18 @@ CanSILBlockStorageType SILBlockStorageType::get(CanType captureType) { return CanSILBlockStorageType(storageTy); } -CanSILFunctionType SILFunctionType::get(GenericSignature genericSig, - ExtInfo ext, - SILCoroutineKind coroutineKind, - ParameterConvention callee, - ArrayRef params, - ArrayRef yields, - ArrayRef normalResults, - Optional errorResult, - SubstitutionMap substitutions, - bool genericSigIsImplied, - const ASTContext &ctx, - Optional witnessMethodConformance) { +CanSILFunctionType SILFunctionType::get( + GenericSignature genericSig, + ExtInfo ext, SILCoroutineKind coroutineKind, + ParameterConvention callee, + ArrayRef params, + ArrayRef yields, + ArrayRef normalResults, + Optional errorResult, + SubstitutionMap substitutions, + bool genericSigIsImplied, + const ASTContext &ctx, + ProtocolConformanceRef witnessMethodConformance) { assert(coroutineKind == SILCoroutineKind::None || normalResults.empty()); assert(coroutineKind != SILCoroutineKind::None || yields.empty()); assert(!ext.isPseudogeneric() || genericSig); @@ -3384,7 +3385,6 @@ CanSILFunctionType SILFunctionType::get(GenericSignature genericSig, return CanSILFunctionType(fnType); } - ArraySliceType *ArraySliceType::get(Type base) { auto properties = base->getRecursiveProperties(); auto arena = getArena(properties); @@ -4165,11 +4165,11 @@ ASTContext::getForeignRepresentationInfo(NominalTypeDecl *nominal, if (nominal != dc->getASTContext().getOptionalDecl()) { if (auto objcBridgeable = getProtocol(KnownProtocolKind::ObjectiveCBridgeable)) { - if (auto conformance - = dc->getParentModule()->lookupConformance( - nominal->getDeclaredType(), objcBridgeable)) { + auto conformance = dc->getParentModule()->lookupConformance( + nominal->getDeclaredType(), objcBridgeable); + if (conformance) { result = - ForeignRepresentationInfo::forBridged(conformance->getConcrete()); + ForeignRepresentationInfo::forBridged(conformance.getConcrete()); } } } @@ -4305,28 +4305,29 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, // Try to find a conformance that will enable bridging. auto findConformance = - [&](KnownProtocolKind known) -> Optional { - // Don't ascribe any behavior to Optional other than what we explicitly - // give it. We don't want things like AnyObject?? to work. - if (type->getAnyNominal() == getOptionalDecl()) - return None; - - // Find the protocol. - auto proto = getProtocol(known); - if (!proto) return None; - - return dc->getParentModule()->lookupConformance(type, proto); - }; + [&](KnownProtocolKind known) -> ProtocolConformanceRef { + // Don't ascribe any behavior to Optional other than what we explicitly + // give it. We don't want things like AnyObject?? to work. + if (type->getAnyNominal() == getOptionalDecl()) + return ProtocolConformanceRef::forInvalid(); + + // Find the protocol. + auto proto = getProtocol(known); + if (!proto) + return ProtocolConformanceRef::forInvalid(); + + return dc->getParentModule()->lookupConformance(type, proto); + }; // Do we conform to _ObjectiveCBridgeable? - if (auto conformance - = findConformance(KnownProtocolKind::ObjectiveCBridgeable)) { + if (auto conformance = + findConformance(KnownProtocolKind::ObjectiveCBridgeable)) { // The corresponding value type is... the type. if (bridgedValueType) *bridgedValueType = type; // Find the Objective-C class type we bridge to. - return conformance->getTypeWitnessByName(type, Id_ObjectiveCType); + return conformance.getTypeWitnessByName(type, Id_ObjectiveCType); } // Do we conform to Error? @@ -4463,7 +4464,7 @@ ASTContext::getOverrideGenericSignature(const ValueDecl *base, auto lookupConformanceFn = [&](CanType depTy, Type substTy, - ProtocolDecl *proto) -> Optional { + ProtocolDecl *proto) -> ProtocolConformanceRef { if (auto conf = subMap.lookupConformance(depTy, proto)) return conf; diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp index 3dd9581b37548..fc81ee3a8faf4 100644 --- a/lib/AST/ASTMangler.cpp +++ b/lib/AST/ASTMangler.cpp @@ -1334,16 +1334,15 @@ static bool containsRetroactiveConformance( continue; ProtocolDecl *proto = requirement.getSecondType()->castTo()->getDecl(); - Optional conformance = - subMap.lookupConformance(requirement.getFirstType()->getCanonicalType(), - proto); - if (!conformance) { + auto conformance = subMap.lookupConformance( + requirement.getFirstType()->getCanonicalType(), proto); + if (conformance.isInvalid()) { // This should only happen when mangling invalid ASTs, but that happens // for indexing purposes. continue; } - if (conformance->isConcrete() && - containsRetroactiveConformance(conformance->getConcrete(), module)) { + if (conformance.isConcrete() && + containsRetroactiveConformance(conformance.getConcrete(), module)) { return true; } } @@ -2707,7 +2706,7 @@ void ASTMangler::appendConcreteProtocolConformance( appendOperator("HO"); } else { auto conditionalConf = module->lookupConformance(canType, proto); - appendConcreteProtocolConformance(conditionalConf->getConcrete()); + appendConcreteProtocolConformance(conditionalConf.getConcrete()); } appendListSeparator(firstRequirement); break; diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index aaa9f90086c84..30b39552c30e8 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -3818,9 +3818,8 @@ class TypePrinter : public TypeVisitor { } } - void printFunctionExtInfo( - SILFunctionType::ExtInfo info, - Optional witnessMethodConformance) { + void printFunctionExtInfo(SILFunctionType::ExtInfo info, + ProtocolConformanceRef witnessMethodConformance) { if (Options.SkipAttributes) return; @@ -3851,7 +3850,7 @@ class TypePrinter : public TypeVisitor { case SILFunctionType::Representation::WitnessMethod: Printer << "witness_method: "; printTypeDeclName( - witnessMethodConformance->getRequirement()->getDeclaredType()); + witnessMethodConformance.getRequirement()->getDeclaredType()); break; case SILFunctionType::Representation::Closure: Printer << "closure"; @@ -4001,7 +4000,7 @@ class TypePrinter : public TypeVisitor { void visitSILFunctionType(SILFunctionType *T) { printSILCoroutineKind(T->getCoroutineKind()); printFunctionExtInfo(T->getExtInfo(), - T->getWitnessMethodConformanceOrNone()); + T->getWitnessMethodConformanceOrInvalid()); printCalleeConvention(T->getCalleeConvention()); if (auto sig = T->getSubstGenericSignature()) { printGenericSignature(sig, diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index dbe519d83907a..7e68b7c235351 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -819,7 +819,7 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal, // Form the inherited conformance. entry->Conformance = - ctx.getInheritedConformance(type, inheritedConformance->getConcrete()); + ctx.getInheritedConformance(type, inheritedConformance.getConcrete()); } else { // Create or find the normal conformance. Type conformingType = conformingDC->getDeclaredInterfaceType(); diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp index 845b177cd1497..6f3b16e9237a0 100644 --- a/lib/AST/GenericSignature.cpp +++ b/lib/AST/GenericSignature.cpp @@ -358,8 +358,9 @@ ASTContext &GenericSignatureImpl::getASTContext() const { return GenericSignature::getASTContext(getGenericParams(), getRequirements()); } -Optional -GenericSignatureImpl::lookupConformance(CanType type, ProtocolDecl *proto) const { +ProtocolConformanceRef +GenericSignatureImpl::lookupConformance(CanType type, + ProtocolDecl *proto) const { // FIXME: Actually implement this properly. auto *M = proto->getParentModule(); diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index 5bdbe15989622..836930553ad00 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -2316,7 +2316,7 @@ GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type, auto conformance = lookupConformance(type.getDependentType(*this)->getCanonicalType(), concrete, proto); - if (!conformance) { + if (conformance.isInvalid()) { if (!concrete->hasError() && concreteSource->getLoc().isValid()) { Impl->HadAnyError = true; @@ -2330,9 +2330,9 @@ GenericSignatureBuilder::resolveConcreteConformance(ResolvedType type, return nullptr; } - concreteSource = concreteSource->viaConcrete(*this, *conformance); + concreteSource = concreteSource->viaConcrete(*this, conformance); equivClass->recordConformanceConstraint(*this, type, proto, concreteSource); - if (addConditionalRequirements(*conformance, /*inferForModule=*/nullptr, + if (addConditionalRequirements(conformance, /*inferForModule=*/nullptr, concreteSource->getLoc())) return nullptr; @@ -2350,7 +2350,8 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance( auto conformance = lookupConformance(type.getDependentType(*this)->getCanonicalType(), superclass, proto); - if (!conformance) return nullptr; + if (conformance.isInvalid()) + return nullptr; // Conformance to this protocol is redundant; update the requirement source // appropriately. @@ -2361,10 +2362,9 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance( else superclassSource = equivClass->superclassConstraints.front().source; - superclassSource = - superclassSource->viaSuperclass(*this, *conformance); + superclassSource = superclassSource->viaSuperclass(*this, conformance); equivClass->recordConformanceConstraint(*this, type, proto, superclassSource); - if (addConditionalRequirements(*conformance, /*inferForModule=*/nullptr, + if (addConditionalRequirements(conformance, /*inferForModule=*/nullptr, superclassSource->getLoc())) return nullptr; @@ -3501,7 +3501,7 @@ GenericSignatureBuilder::getLookupConformanceFn() return LookUpConformanceInBuilder(this); } -Optional +ProtocolConformanceRef GenericSignatureBuilder::lookupConformance(CanType dependentType, Type conformingReplacementType, ProtocolDecl *conformedProtocol) { @@ -4418,7 +4418,7 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement( // FIXME: diagnose if there's no conformance. if (conformance) { - if (addConditionalRequirements(*conformance, inferForModule, + if (addConditionalRequirements(conformance, inferForModule, source.getLoc())) return ConstraintResult::Conflicting; } diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 85291e744737f..164c7e9bcffdb 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -716,7 +716,7 @@ void ModuleDecl::getDisplayDecls(SmallVectorImpl &Results) const { FORWARD(getDisplayDecls, (Results)); } -Optional +ProtocolConformanceRef ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { ASTContext &ctx = getASTContext(); @@ -725,7 +725,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { // If the existential type cannot be represented or the protocol does not // conform to itself, there's no point in looking further. if (!protocol->existentialConformsToSelf()) - return None; + return ProtocolConformanceRef::forInvalid(); auto layout = type->getExistentialLayout(); @@ -742,7 +742,7 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { type->castTo()->getDecl() == protocol) return ProtocolConformanceRef(ctx.getSelfConformance(protocol)); - return None; + return ProtocolConformanceRef::forInvalid(); } // If the existential is class-constrained, the class might conform @@ -775,11 +775,11 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) { // We didn't find our protocol in the existential's list; it doesn't // conform. - return None; + return ProtocolConformanceRef::forInvalid(); } -Optional -ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) { +ProtocolConformanceRef ModuleDecl::lookupConformance(Type type, + ProtocolDecl *protocol) { ASTContext &ctx = getASTContext(); // A dynamic Self type conforms to whatever its underlying type @@ -799,10 +799,8 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) { // concrete. if (auto super = archetype->getSuperclass()) { if (auto inheritedConformance = lookupConformance(super, protocol)) { - return ProtocolConformanceRef( - ctx.getInheritedConformance( - type, - inheritedConformance->getConcrete())); + return ProtocolConformanceRef(ctx.getInheritedConformance( + type, inheritedConformance.getConcrete())); } } @@ -811,7 +809,7 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) { return ProtocolConformanceRef(protocol); } - return None; + return ProtocolConformanceRef::forInvalid(); } // An existential conforms to a protocol if the protocol is listed in the @@ -833,12 +831,13 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) { auto nominal = type->getAnyNominal(); // If we don't have a nominal type, there are no conformances. - if (!nominal || isa(nominal)) return None; + if (!nominal || isa(nominal)) + return ProtocolConformanceRef::forInvalid(); // Find the (unspecialized) conformance. SmallVector conformances; if (!nominal->lookupConformance(this, protocol, conformances)) - return None; + return ProtocolConformanceRef::forInvalid(); // FIXME: Ambiguity resolution. auto conformance = conformances.front(); @@ -862,8 +861,8 @@ ModuleDecl::lookupConformance(Type type, ProtocolDecl *protocol) { "We already found the inherited conformance"); // Create the inherited conformance entry. - conformance - = ctx.getInheritedConformance(type, inheritedConformance->getConcrete()); + conformance = + ctx.getInheritedConformance(type, inheritedConformance.getConcrete()); return ProtocolConformanceRef(conformance); } diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index c1516f4373c6a..0be256d858729 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -128,21 +128,17 @@ ProtocolConformanceRef::subst(Type origType, // If the type is an existential, it must be self-conforming. if (substType->isExistentialType()) { - if (auto optConformance = - proto->getModuleContext()->lookupExistentialConformance( - substType, proto)) - return *optConformance; + auto optConformance = + proto->getModuleContext()->lookupExistentialConformance(substType, + proto); + if (optConformance) + return optConformance; return ProtocolConformanceRef::forInvalid(); } // Check the conformance map. - if (auto result = conformances(origType->getCanonicalType(), - substType, proto)) { - return *result; - } - - return ProtocolConformanceRef::forInvalid(); + return conformances(origType->getCanonicalType(), substType, proto); } ProtocolConformanceRef ProtocolConformanceRef::mapConformanceOutOfContext() const { @@ -841,8 +837,8 @@ recursivelySubstituteBaseType(ModuleDecl *module, // If we have an inherited protocol just look up the conformance. if (reqProto != conformance->getProtocol()) { - reqConformance = module->lookupConformance( - conformance->getType(), reqProto)->getConcrete(); + reqConformance = module->lookupConformance(conformance->getType(), reqProto) + .getConcrete(); } return reqConformance->getTypeWitness(depMemTy->getAssocType()); @@ -894,12 +890,8 @@ void NormalProtocolConformance::finishSignatureConformances() { if (substTy->hasTypeParameter()) substTy = getDeclContext()->mapTypeIntoContext(substTy); - auto reqConformance = module->lookupConformance(substTy, reqProto); - if (!reqConformance) - reqConformance = ProtocolConformanceRef::forInvalid(); - - reqConformance = reqConformance->mapConformanceOutOfContext(); - reqConformances.push_back(*reqConformance); + reqConformances.push_back(module->lookupConformance(substTy, reqProto) + .mapConformanceOutOfContext()); } setSignatureConformances(reqConformances); } diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp index e84797f3f78da..58c831018c086 100644 --- a/lib/AST/RequirementEnvironment.cpp +++ b/lib/AST/RequirementEnvironment.cpp @@ -111,7 +111,7 @@ RequirementEnvironment::RequirementEnvironment( }, [selfType, substConcreteType, conformance, conformanceDC, &ctx]( CanType type, Type replacement, ProtocolDecl *proto) - -> Optional { + -> ProtocolConformanceRef { // The protocol 'Self' conforms concretely to the conforming type. if (type->isEqual(selfType)) { ProtocolConformance *specialized = conformance; diff --git a/lib/AST/SubstitutionMap.cpp b/lib/AST/SubstitutionMap.cpp index e60cee1395e11..682ea0cc29e1d 100644 --- a/lib/AST/SubstitutionMap.cpp +++ b/lib/AST/SubstitutionMap.cpp @@ -222,8 +222,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig, auto replacement = depTy.subst(subs, lookupConformance); auto protoType = req.getSecondType()->castTo(); auto proto = protoType->getDecl(); - auto conformance = lookupConformance(depTy, replacement, proto) - .getValueOr(ProtocolConformanceRef::forInvalid()); + auto conformance = lookupConformance(depTy, replacement, proto); conformances.push_back(conformance); } @@ -301,9 +300,10 @@ Type SubstitutionMap::lookupSubstitution(CanSubstitutableType type) const { return replacementType; } -Optional +ProtocolConformanceRef SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { - if (empty()) return None; + if (empty()) + return ProtocolConformanceRef::forInvalid(); // If we have an archetype, map out of the context so we can compute a // conformance access path. @@ -316,7 +316,7 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { // Error path: if we don't have a type parameter, there is no conformance. // FIXME: Query concrete conformances in the generic signature? if (!type->isTypeParameter()) - return None; + return ProtocolConformanceRef::forInvalid(); auto genericSig = getGenericSignature(); @@ -334,23 +334,23 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { // Retrieve the starting conformance from the conformance map. auto getInitialConformance = - [&](Type type, ProtocolDecl *proto) -> Optional { - unsigned conformanceIndex = 0; - for (const auto &req : getGenericSignature()->getRequirements()) { - if (req.getKind() != RequirementKind::Conformance) - continue; - - // Is this the conformance we're looking for? - if (req.getFirstType()->isEqual(type) && - req.getSecondType()->castTo()->getDecl() == proto) { - return getConformances()[conformanceIndex]; - } - - ++conformanceIndex; + [&](Type type, ProtocolDecl *proto) -> ProtocolConformanceRef { + unsigned conformanceIndex = 0; + for (const auto &req : getGenericSignature()->getRequirements()) { + if (req.getKind() != RequirementKind::Conformance) + continue; + + // Is this the conformance we're looking for? + if (req.getFirstType()->isEqual(type) && + req.getSecondType()->castTo()->getDecl() == proto) { + return getConformances()[conformanceIndex]; } - return None; - }; + ++conformanceIndex; + } + + return ProtocolConformanceRef::forInvalid(); + }; // Check whether the superclass conforms. if (auto superclass = genericSig->getSuperclassBound(type)) { @@ -362,30 +362,30 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { // If the type doesn't conform to this protocol, the result isn't formed // from these requirements. if (!genericSig->conformsToProtocol(type, proto)) - return None; + return ProtocolConformanceRef::forInvalid(); auto accessPath = genericSig->getConformanceAccessPath(type, proto); // Fall through because we cannot yet evaluate an access path. - Optional conformance; + ProtocolConformanceRef conformance; for (const auto &step : accessPath) { // For the first step, grab the initial conformance. - if (!conformance) { + if (conformance.isInvalid()) { conformance = getInitialConformance(step.first, step.second); - if (!conformance) - return None; + if (conformance.isInvalid()) + return ProtocolConformanceRef::forInvalid(); continue; } - if (conformance->isInvalid()) + if (conformance.isInvalid()) return conformance; // If we've hit an abstract conformance, everything from here on out is // abstract. // FIXME: This may not always be true, but it holds for now. - if (conformance->isAbstract()) { + if (conformance.isAbstract()) { // FIXME: Rip this out once we can get a concrete conformance from // an archetype. auto substType = type.subst(*this); @@ -405,7 +405,7 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { // For the second step, we're looking into the requirement signature for // this protocol. - auto concrete = conformance->getConcrete(); + auto concrete = conformance.getConcrete(); auto normal = concrete->getRootNormalConformance(); // If we haven't set the signature conformances yet, force the issue now. @@ -415,7 +415,7 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const { // FIXME: Seems like we should be able to get at the intermediate state // to use that. if (normal->getState() == ProtocolConformanceState::CheckingTypeWitnesses) - return None; + return ProtocolConformanceRef::forInvalid(); } // Get the associated conformance. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1c91ecebe4eb0..a88092b4a9b2c 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1754,8 +1754,8 @@ bool TypeBase::isBindableTo(Type b) { auto canTy = req.getFirstType()->getCanonicalType(); auto *proto = req.getSecondType()->castTo()->getDecl(); - auto origConf = *origSubMap.lookupConformance(canTy, proto); - auto substConf = *substSubMap.lookupConformance(canTy, proto); + auto origConf = origSubMap.lookupConformance(canTy, proto); + auto substConf = substSubMap.lookupConformance(canTy, proto); if (origConf.isConcrete()) { if (!substConf.isConcrete()) @@ -2762,7 +2762,7 @@ substOpaqueTypesWithUnderlyingTypes(ProtocolConformanceRef ref, Type origType, SubstFlags::SubstituteOpaqueArchetypes); } -Optional ReplaceOpaqueTypesWithUnderlyingTypes:: +ProtocolConformanceRef ReplaceOpaqueTypesWithUnderlyingTypes:: operator()(CanType maybeOpaqueType, Type replacementType, ProtocolDecl *protocol) const { auto abstractRef = ProtocolConformanceRef(protocol); @@ -3178,16 +3178,17 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, // If we know the associated type, look in the witness table. if (assocType) { auto proto = assocType->getProtocol(); - Optional conformance - = lookupConformances(origBase->getCanonicalType(), - substBase, proto); + ProtocolConformanceRef conformance = + lookupConformances(origBase->getCanonicalType(), substBase, proto); - if (!conformance) return failed(); - if (!conformance->isConcrete()) return failed(); + if (conformance.isInvalid()) + return failed(); + if (!conformance.isConcrete()) + return failed(); // Retrieve the type witness. auto witness = - conformance->getConcrete()->getTypeWitness(assocType, options); + conformance.getConcrete()->getTypeWitness(assocType, options); if (!witness || witness->hasError()) return failed(); @@ -3210,10 +3211,9 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, return failed(); } -Optional -LookUpConformanceInModule::operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { +ProtocolConformanceRef LookUpConformanceInModule:: +operator()(CanType dependentType, Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { if (conformingReplacementType->isTypeParameter()) return ProtocolConformanceRef(conformedProtocol); @@ -3221,17 +3221,15 @@ LookUpConformanceInModule::operator()(CanType dependentType, conformedProtocol); } -Optional -LookUpConformanceInSubstitutionMap::operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { +ProtocolConformanceRef LookUpConformanceInSubstitutionMap:: +operator()(CanType dependentType, Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { return Subs.lookupConformance(dependentType, conformedProtocol); } -Optional -MakeAbstractConformanceForGenericType::operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { +ProtocolConformanceRef MakeAbstractConformanceForGenericType:: +operator()(CanType dependentType, Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { assert((conformingReplacementType->is() || conformingReplacementType->is() || conformingReplacementType->is()) @@ -3239,10 +3237,9 @@ MakeAbstractConformanceForGenericType::operator()(CanType dependentType, return ProtocolConformanceRef(conformedProtocol); } -Optional -LookUpConformanceInSignature::operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { +ProtocolConformanceRef LookUpConformanceInSignature:: +operator()(CanType dependentType, Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { // FIXME: Should pass dependentType instead, once // GenericSignature::lookupConformance() does the right thing return Sig->lookupConformance(conformingReplacementType->getCanonicalType(), @@ -3949,18 +3946,19 @@ case TypeKind::Id: if (!changed) return *this; - return SILFunctionType::get(fnTy->getSubstGenericSignature(), - fnTy->getExtInfo(), - fnTy->getCoroutineKind(), - fnTy->getCalleeConvention(), - transInterfaceParams, - transInterfaceYields, - transInterfaceResults, - transErrorResult, - SubstitutionMap(), - false, - Ptr->getASTContext(), - fnTy->getWitnessMethodConformanceOrNone()); + return SILFunctionType::get( + fnTy->getSubstGenericSignature(), + fnTy->getExtInfo(), + fnTy->getCoroutineKind(), + fnTy->getCalleeConvention(), + transInterfaceParams, + transInterfaceYields, + transInterfaceResults, + transErrorResult, + SubstitutionMap(), + /*genericSigIsImplied*/ false, + Ptr->getASTContext(), + fnTy->getWitnessMethodConformanceOrInvalid()); } #define REF_STORAGE(Name, ...) \ diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 2a0892fbb8c13..26d303b897642 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2107,9 +2107,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { auto *Module = NTD->getParentModule(); auto Conformance = Module->lookupConformance( BaseTy, ATD->getProtocol()); - if (Conformance && Conformance->isConcrete()) { - return Conformance->getConcrete() - ->getTypeWitness(const_cast(ATD)); + if (Conformance.isConcrete()) { + return Conformance.getConcrete()->getTypeWitness( + const_cast(ATD)); } } } diff --git a/lib/IDE/IDETypeChecking.cpp b/lib/IDE/IDETypeChecking.cpp index bb79fb94b2f07..6fbca817e42ad 100644 --- a/lib/IDE/IDETypeChecking.cpp +++ b/lib/IDE/IDETypeChecking.cpp @@ -307,11 +307,10 @@ struct SynthesizedExtensionAnalyzer::Implementation { case RequirementKind::Conformance: { auto *M = DC->getParentModule(); auto *Proto = Second->castTo()->getDecl(); - if (!First->isTypeParameter() && - !First->is() && - !M->conformsToProtocol(First, Proto)) + if (!First->isTypeParameter() && !First->is() && + M->conformsToProtocol(First, Proto).isInvalid()) return true; - if (!M->conformsToProtocol(First, Proto)) + if (M->conformsToProtocol(First, Proto).isInvalid()) MergeInfo.addRequirement(GenericSig, First, Second, Kind); break; } diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp index 52fcc5b4f50eb..065aa8cd7e931 100644 --- a/lib/IRGen/Fulfillment.cpp +++ b/lib/IRGen/Fulfillment.cpp @@ -267,36 +267,35 @@ bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM, GenericTypeRequirements requirements(IGM, nominal); requirements.enumerateFulfillments( IGM, type->getContextSubstitutionMap(IGM.getSwiftModule(), nominal), - [&](unsigned reqtIndex, CanType arg, - Optional conf) { - // Skip uninteresting type arguments. - if (!keys.hasInterestingType(arg)) - return; - - // If the fulfilled value is type metadata, refine the path. - if (!conf) { - auto argState = getPresumedMetadataStateForTypeArgument(metadataState); - MetadataPath argPath = path; - argPath.addNominalTypeArgumentComponent(reqtIndex); - hadFulfillment |= - searchTypeMetadata(IGM, arg, IsExact, argState, source, - std::move(argPath), keys); - return; - } - - // Otherwise, it's a conformance. - - // Ignore it unless the type itself is interesting. - if (!keys.isInterestingType(arg)) - return; - - // Refine the path. - MetadataPath argPath = path; - argPath.addNominalTypeArgumentConformanceComponent(reqtIndex); - - hadFulfillment |= searchWitnessTable(IGM, arg, conf->getRequirement(), - source, std::move(argPath), keys); - }); + [&](unsigned reqtIndex, CanType arg, ProtocolConformanceRef conf) { + // Skip uninteresting type arguments. + if (!keys.hasInterestingType(arg)) + return; + + // If the fulfilled value is type metadata, refine the path. + if (conf.isInvalid()) { + auto argState = + getPresumedMetadataStateForTypeArgument(metadataState); + MetadataPath argPath = path; + argPath.addNominalTypeArgumentComponent(reqtIndex); + hadFulfillment |= searchTypeMetadata( + IGM, arg, IsExact, argState, source, std::move(argPath), keys); + return; + } + + // Otherwise, it's a conformance. + + // Ignore it unless the type itself is interesting. + if (!keys.isInterestingType(arg)) + return; + + // Refine the path. + MetadataPath argPath = path; + argPath.addNominalTypeArgumentConformanceComponent(reqtIndex); + + hadFulfillment |= searchWitnessTable(IGM, arg, conf.getRequirement(), + source, std::move(argPath), keys); + }); return hadFulfillment; } diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp index e014f91a0137a..51b30b5c00c11 100644 --- a/lib/IRGen/GenKeyPath.cpp +++ b/lib/IRGen/GenKeyPath.cpp @@ -857,10 +857,10 @@ emitKeyPathComponent(IRGenModule &IGM, // Protocol requirement. auto conformance = subs.lookupConformance( reqt.TypeParameter->getCanonicalType(), reqt.Protocol); - externalSubArgs.push_back( - IGM.emitWitnessTableRefString(substType, *conformance, - genericEnv ? genericEnv->getGenericSignature() : nullptr, - /*shouldSetLowBit*/ true)); + externalSubArgs.push_back(IGM.emitWitnessTableRefString( + substType, conformance, + genericEnv ? genericEnv->getGenericSignature() : nullptr, + /*shouldSetLowBit*/ true)); } }); } diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp index d7038ee4cbdeb..278ef516daa69 100644 --- a/lib/IRGen/GenProto.cpp +++ b/lib/IRGen/GenProto.cpp @@ -323,7 +323,7 @@ bool PolymorphicConvention::considerType(CanType type, IsExact_t isExact, void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) { CanType selfTy = fnType->getSelfInstanceType(IGM.getSILModule()); - auto conformance = fnType->getWitnessMethodConformance(); + auto conformance = fnType->getWitnessMethodConformanceOrInvalid(); // First, bind type metadata for Self. Sources.emplace_back(MetadataSource::Kind::SelfMetadata, @@ -564,7 +564,7 @@ void EmitPolymorphicParameters::bindExtraSource(const MetadataSource &source, assert(selfTable && "no Self witness table for witness method"); // Mark this as the cached witness table for Self. - auto conformance = FnType->getWitnessMethodConformance(); + auto conformance = FnType->getWitnessMethodConformanceOrInvalid(); auto selfProto = conformance.getRequirement(); auto selfTy = FnType->getSelfInstanceType(IGM.getSILModule()); @@ -956,9 +956,9 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF, rootConformance, [&](unsigned, CanType type, ProtocolDecl *proto) { auto substType = type.subst(subMap)->getCanonicalType(); auto reqConformance = subMap.lookupConformance(type, proto); - assert(reqConformance && "conditional conformance must exist"); + assert(reqConformance && "conditional conformance must be valid"); - tables.push_back(emitWitnessTableRef(IGF, substType, *reqConformance)); + tables.push_back(emitWitnessTableRef(IGF, substType, reqConformance)); return /*finished?*/ false; }); @@ -2417,8 +2417,8 @@ MetadataResponse MetadataPath::followComponent(IRGenFunction &IGF, // conformance kind. } else { assert(requirement.Protocol && "index mismatch!"); - auto conformance = *subs.lookupConformance(requirement.TypeParameter, - requirement.Protocol); + auto conformance = subs.lookupConformance(requirement.TypeParameter, + requirement.Protocol); assert(conformance.getRequirement() == requirement.Protocol); sourceKey.Kind = LocalTypeDataKind::forProtocolWitnessTable(conformance); @@ -2924,8 +2924,8 @@ NecessaryBindings::forFunctionInvocations(IRGenModule &IGM, CanType type = requirement.TypeParameter.subst(subs)->getCanonicalType(); if (requirement.Protocol) { - auto conf = *subs.lookupConformance(requirement.TypeParameter, - requirement.Protocol); + auto conf = subs.lookupConformance(requirement.TypeParameter, + requirement.Protocol); bindings.addProtocolConformance(type, conf); } else { bindings.addTypeMetadata(type); @@ -2999,11 +2999,11 @@ GenericTypeRequirements::enumerateFulfillments(IRGenModule &IGM, auto &reqt = getRequirements()[reqtIndex]; CanType type = reqt.TypeParameter.subst(subs)->getCanonicalType(); if (reqt.Protocol) { - auto conformance = *subs.lookupConformance(reqt.TypeParameter, - reqt.Protocol); + auto conformance = + subs.lookupConformance(reqt.TypeParameter, reqt.Protocol); callback(reqtIndex, type, conformance); } else { - callback(reqtIndex, type, None); + callback(reqtIndex, type, ProtocolConformanceRef::forInvalid()); } } } @@ -3063,7 +3063,7 @@ irgen::emitGenericRequirementFromSubstitutions(IRGenFunction &IGF, } auto proto = requirement.Protocol; - auto conformance = *subs.lookupConformance(depTy, proto); + auto conformance = subs.lookupConformance(depTy, proto); assert(conformance.getRequirement() == proto); llvm::Value *metadata = nullptr; auto wtable = emitWitnessTableRef(IGF, argType, &metadata, conformance); diff --git a/lib/IRGen/GenericRequirement.h b/lib/IRGen/GenericRequirement.h index 68057942bd449..5076da261c9a4 100644 --- a/lib/IRGen/GenericRequirement.h +++ b/lib/IRGen/GenericRequirement.h @@ -137,10 +137,8 @@ class GenericTypeRequirements { bool empty() const { return Requirements.empty(); } - using FulfillmentCallback = - llvm::function_ref conf)>; + using FulfillmentCallback = llvm::function_ref; void enumerateFulfillments(IRGenModule &IGM, SubstitutionMap subs, FulfillmentCallback callback); diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 73366da17eb99..fff4350ae9349 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -2123,7 +2123,8 @@ emitWitnessTableForLoweredCallee(IRGenSILFunction &IGF, // This use of getSelfInstanceType() assumes that the instance type is // always a meaningful formal type. auto substSelfType = substCalleeType->getSelfInstanceType(IGF.IGM.getSILModule()); - auto substConformance = substCalleeType->getWitnessMethodConformance(); + auto substConformance = + substCalleeType->getWitnessMethodConformanceOrInvalid(); llvm::Value *argMetadata = IGF.emitTypeMetadataRef(substSelfType); llvm::Value *wtable = diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index 72252da964f51..52d893f2cf315 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -286,7 +286,7 @@ LargeSILTypeMapper::getNewSILFunctionType(GenericEnvironment *env, fnType->getSubstitutions(), fnType->isGenericSignatureImplied(), fnType->getASTContext(), - fnType->getWitnessMethodConformanceOrNone()); + fnType->getWitnessMethodConformanceOrInvalid()); return newFnType; } @@ -2317,7 +2317,7 @@ static bool rewriteFunctionReturn(StructLoweringState &pass) { newSILResultInfo, loweredTy->getOptionalErrorResult(), loweredTy->getSubstitutions(), loweredTy->isGenericSignatureImplied(), F->getModule().getASTContext(), - loweredTy->getWitnessMethodConformanceOrNone()); + loweredTy->getWitnessMethodConformanceOrInvalid()); F->rewriteLoweredTypeUnsafe(NewTy); return true; } diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 3627f493cf16a..ed9c5bdfff275 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -470,15 +470,15 @@ namespace { auto subs = type->getContextSubstitutionMap(IGF.IGM.getSwiftModule(), decl); - requirements.enumerateFulfillments(IGF.IGM, subs, - [&](unsigned reqtIndex, CanType type, - Optional conf) { - if (conf) { - Values.push_back(emitWitnessTableRef(IGF, type, *conf)); - } else { - Values.push_back(IGF.emitAbstractTypeMetadataRef(type)); - } - }); + requirements.enumerateFulfillments( + IGF.IGM, subs, + [&](unsigned reqtIndex, CanType type, ProtocolConformanceRef conf) { + if (conf) { + Values.push_back(emitWitnessTableRef(IGF, type, conf)); + } else { + Values.push_back(IGF.emitAbstractTypeMetadataRef(type)); + } + }); collectTypes(IGF.IGM, decl); assert(Types.size() == Values.size()); diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp index 2f0cf3c2d9c18..5edd681ff85fe 100644 --- a/lib/ParseSIL/ParseSIL.cpp +++ b/lib/ParseSIL/ParseSIL.cpp @@ -243,11 +243,10 @@ namespace { void convertRequirements(SILFunction *F, ArrayRef From, SmallVectorImpl &To); - Optional - parseProtocolConformanceHelper(ProtocolDecl *&proto, - GenericEnvironment *GenericEnv, - ConformanceContext context, - ProtocolDecl *defaultForProto); + ProtocolConformanceRef parseProtocolConformanceHelper( + ProtocolDecl *&proto, GenericEnvironment *GenericEnv, + ConformanceContext context, ProtocolDecl *defaultForProto); + public: SILParser(Parser &P) : P(P), SILMod(static_cast(P.SIL)->M), @@ -477,12 +476,10 @@ namespace { GenericEnvironment *GenericEnv=nullptr, ProtocolDecl *defaultForProto = nullptr); - Optional - parseProtocolConformance(ProtocolDecl *&proto, - GenericEnvironment *&genericEnv, - ConformanceContext context, - ProtocolDecl *defaultForProto); - Optional + ProtocolConformanceRef parseProtocolConformance( + ProtocolDecl *&proto, GenericEnvironment *&genericEnv, + ConformanceContext context, ProtocolDecl *defaultForProto); + ProtocolConformanceRef parseProtocolConformance(ProtocolDecl *defaultForProto, ConformanceContext context) { ProtocolDecl *dummy; @@ -1769,14 +1766,11 @@ static bool getConformancesForSubstitution(Parser &P, for (auto protoTy : protocols) { auto conformance = M->lookupConformance(subReplacement, protoTy->getDecl()); - if (conformance) { - conformances.push_back(*conformance); - continue; + if (conformance.isInvalid()) { + P.diagnose(loc, diag::sil_substitution_mismatch, subReplacement, protoTy); + return true; } - - P.diagnose(loc, diag::sil_substitution_mismatch, subReplacement, - protoTy); - return true; + conformances.push_back(conformance); } return false; @@ -1808,30 +1802,31 @@ SubstitutionMap getApplySubstitutionsFromParsed( bool failed = false; auto subMap = SubstitutionMap::get( - genericSig, - [&](SubstitutableType *type) -> Type { - auto genericParam = dyn_cast(type); - if (!genericParam) return nullptr; - - auto index = genericSig->getGenericParamOrdinal(genericParam); - assert(index < genericSig->getGenericParams().size()); - assert(index < parses.size()); - - // Provide the replacement type. - return parses[index].replacement; - }, - [&](CanType dependentType, Type replacementType, - ProtocolDecl *proto) ->Optional { - auto M = SP.P.SF.getParentModule(); - auto conformance = M->lookupConformance(replacementType, proto); - if (conformance) return conformance; - - SP.P.diagnose(loc, diag::sil_substitution_mismatch, replacementType, - proto->getDeclaredType()); - failed = true; - - return ProtocolConformanceRef(proto); - }); + genericSig, + [&](SubstitutableType *type) -> Type { + auto genericParam = dyn_cast(type); + if (!genericParam) + return nullptr; + + auto index = genericSig->getGenericParamOrdinal(genericParam); + assert(index < genericSig->getGenericParams().size()); + assert(index < parses.size()); + + // Provide the replacement type. + return parses[index].replacement; + }, + [&](CanType dependentType, Type replacementType, + ProtocolDecl *proto) -> ProtocolConformanceRef { + auto M = SP.P.SF.getParentModule(); + if (auto conformance = M->lookupConformance(replacementType, proto)) + return conformance; + + SP.P.diagnose(loc, diag::sil_substitution_mismatch, replacementType, + proto->getDeclaredType()); + failed = true; + + return ProtocolConformanceRef(proto); + }); return failed ? SubstitutionMap() : subMap; } @@ -2133,14 +2128,14 @@ SILParser::parseKeyPathPatternComponent(KeyPathPatternComponent &component, contextFormalTy = patternEnv->mapTypeIntoContext(formalTy); auto lookup = P.SF.getParentModule()->lookupConformance( contextFormalTy, proto); - if (!lookup) { + if (lookup.isInvalid()) { P.diagnose(formalTyLoc, diag::sil_keypath_index_not_hashable, formalTy); return true; } - auto conformance = ProtocolConformanceRef(*lookup); - + auto conformance = ProtocolConformanceRef(lookup); + indexes.push_back({index, formalTy, loweredTy, conformance}); if (operandTypes.size() <= index) @@ -4325,13 +4320,13 @@ bool SILParser::parseSILInstruction(SILBuilder &B) { return true; } auto conformance = P.SF.getParentModule()->lookupConformance(LookupTy, proto); - if (!conformance) { + if (conformance.isInvalid()) { P.diagnose(TyLoc, diag::sil_witness_method_type_does_not_conform); return true; } - ResultVal = B.createWitnessMethod(InstLoc, LookupTy, *conformance, Member, - MethodTy); + ResultVal = + B.createWitnessMethod(InstLoc, LookupTy, conformance, Member, MethodTy); break; } case SILInstructionKind::CopyAddrInst: { @@ -5967,24 +5962,24 @@ static bool isSelfConformance(Type conformingType, ProtocolDecl *protocol) { return false; } -static Optional parseRootProtocolConformance(Parser &P, - SILParser &SP, Type ConformingTy, ProtocolDecl *&proto, - ConformanceContext context) { +static ProtocolConformanceRef +parseRootProtocolConformance(Parser &P, SILParser &SP, Type ConformingTy, + ProtocolDecl *&proto, ConformanceContext context) { Identifier ModuleKeyword, ModuleName; SourceLoc Loc, KeywordLoc; proto = parseProtocolDecl(P, SP); if (!proto) - return None; - + return ProtocolConformanceRef(); + if (P.parseIdentifier(ModuleKeyword, KeywordLoc, diag::expected_tok_in_sil_instr, "module") || SP.parseSILIdentifier(ModuleName, Loc, diag::expected_sil_value_name)) - return None; + return ProtocolConformanceRef(); if (ModuleKeyword.str() != "module") { P.diagnose(KeywordLoc, diag::expected_tok_in_sil_instr, "module"); - return None; + return ProtocolConformanceRef(); } // Calling lookupConformance on a BoundGenericType will return a specialized @@ -5993,14 +5988,13 @@ static Optional parseRootProtocolConformance(Parser &P, if (auto bound = lookupTy->getAs()) lookupTy = bound->getDecl()->getDeclaredType(); auto lookup = P.SF.getParentModule()->lookupConformance(lookupTy, proto); - if (!lookup) { + if (lookup.isInvalid()) { P.diagnose(KeywordLoc, diag::sil_witness_protocol_conformance_not_found); - return None; + return ProtocolConformanceRef(); } // Use a concrete self-conformance if we're parsing this for a witness table. - if (context == ConformanceContext::WitnessTable && - !lookup->isConcrete() && + if (context == ConformanceContext::WitnessTable && !lookup.isConcrete() && isSelfConformance(ConformingTy, proto)) { lookup = ProtocolConformanceRef(P.Context.getSelfConformance(proto)); } @@ -6017,11 +6011,9 @@ static Optional parseRootProtocolConformance(Parser &P, /// normal-protocol-conformance ::= /// generic-parameter-list? type: protocolName module ModuleName /// Note that generic-parameter-list is already parsed before calling this. -Optional SILParser::parseProtocolConformance( - ProtocolDecl *&proto, - GenericEnvironment *&genericEnv, - ConformanceContext context, - ProtocolDecl *defaultForProto) { +ProtocolConformanceRef SILParser::parseProtocolConformance( + ProtocolDecl *&proto, GenericEnvironment *&genericEnv, + ConformanceContext context, ProtocolDecl *defaultForProto) { // Parse generic params for the protocol conformance. We need to make sure // they have the right scope. Optional GenericsScope; @@ -6045,15 +6037,13 @@ Optional SILParser::parseProtocolConformance( return retVal; } -Optional SILParser::parseProtocolConformanceHelper( - ProtocolDecl *&proto, - GenericEnvironment *witnessEnv, - ConformanceContext context, - ProtocolDecl *defaultForProto) { +ProtocolConformanceRef SILParser::parseProtocolConformanceHelper( + ProtocolDecl *&proto, GenericEnvironment *witnessEnv, + ConformanceContext context, ProtocolDecl *defaultForProto) { // Parse AST type. ParserResult TyR = P.parseType(); if (TyR.isNull()) - return None; + return ProtocolConformanceRef(); TypeLoc Ty = TyR.get(); if (defaultForProto) { bindProtocolSelfInTypeRepr(Ty, defaultForProto); @@ -6061,11 +6051,11 @@ Optional SILParser::parseProtocolConformanceHelper( if (performTypeLocChecking(Ty, /*IsSILType=*/ false, witnessEnv, defaultForProto)) - return None; + return ProtocolConformanceRef(); auto ConformingTy = Ty.getType(); if (P.parseToken(tok::colon, diag::expected_sil_witness_colon)) - return None; + return ProtocolConformanceRef(); if (P.Tok.is(tok::identifier) && P.Tok.getText() == "specialize") { P.consumeToken(); @@ -6073,28 +6063,28 @@ Optional SILParser::parseProtocolConformanceHelper( // Parse substitutions for specialized conformance. SmallVector parsedSubs; if (parseSubstitutions(parsedSubs, witnessEnv, defaultForProto)) - return None; + return ProtocolConformanceRef(); if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen)) - return None; + return ProtocolConformanceRef(); ProtocolDecl *dummy; GenericEnvironment *specializedEnv; auto genericConform = parseProtocolConformance(dummy, specializedEnv, ConformanceContext::Ordinary, defaultForProto); - if (!genericConform || !genericConform->isConcrete()) - return None; + if (genericConform.isInvalid() || !genericConform.isConcrete()) + return ProtocolConformanceRef(); if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen)) - return None; + return ProtocolConformanceRef(); SubstitutionMap subMap = getApplySubstitutionsFromParsed(*this, specializedEnv, parsedSubs); if (!subMap) - return None; + return ProtocolConformanceRef(); auto result = P.Context.getSpecializedConformance( - ConformingTy, genericConform->getConcrete(), subMap); + ConformingTy, genericConform.getConcrete(), subMap); return ProtocolConformanceRef(result); } @@ -6102,16 +6092,16 @@ Optional SILParser::parseProtocolConformanceHelper( P.consumeToken(); if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen)) - return None; + return ProtocolConformanceRef(); auto baseConform = parseProtocolConformance(defaultForProto, ConformanceContext::Ordinary); - if (!baseConform || !baseConform->isConcrete()) - return None; + if (baseConform.isInvalid() || !baseConform.isConcrete()) + return ProtocolConformanceRef(); if (P.parseToken(tok::r_paren, diag::expected_sil_witness_rparen)) - return None; + return ProtocolConformanceRef(); auto result = P.Context.getInheritedConformance(ConformingTy, - baseConform->getConcrete()); + baseConform.getConcrete()); return ProtocolConformanceRef(result); } @@ -6155,12 +6145,12 @@ static bool parseSILVTableEntry( auto conform = witnessState.parseProtocolConformance(defaultForProto, ConformanceContext::Ordinary); - if (!conform || !conform->isConcrete()) // Ignore this witness entry for now. + // Ignore invalid and abstract witness entries. + if (conform.isInvalid() || !conform.isConcrete()) return false; - witnessEntries.push_back(SILWitnessTable::BaseProtocolWitness{ - proto, conform->getConcrete() - }); + witnessEntries.push_back( + SILWitnessTable::BaseProtocolWitness{proto, conform.getConcrete()}); return false; } @@ -6204,9 +6194,10 @@ static bool parseSILVTableEntry( auto concrete = witnessState.parseProtocolConformance(defaultForProto, ConformanceContext::Ordinary); - if (!concrete && !concrete->isConcrete()) // Ignore this for now. + // Ignore invalid and abstract witness entries. + if (concrete.isInvalid() || !concrete.isConcrete()) return false; - conformance = *concrete; + conformance = concrete; } else { P.consumeToken(); } @@ -6330,10 +6321,9 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) { WitnessState.ContextGenericEnv = witnessEnv; // FIXME: should we really allow a specialized or inherited conformance here? - auto theConformance = - (conf && conf->isConcrete()) - ? conf->getConcrete()->getRootConformance() - : nullptr; + RootProtocolConformance *theConformance = nullptr; + if (conf.isConcrete()) + theConformance = conf.getConcrete()->getRootConformance(); SILWitnessTable *wt = nullptr; if (theConformance) { diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp index 6ebe7611d16ca..3f83785d1bbbb 100644 --- a/lib/SIL/DynamicCasts.cpp +++ b/lib/SIL/DynamicCasts.cpp @@ -135,7 +135,7 @@ classifyDynamicCastToProtocol(ModuleDecl *M, CanType source, CanType target, // the implementation, including checkGenericArguments, needs to be taught to // recognize that types with archetypes may potentially succeed. if (auto conformance = M->lookupConformance(source, TargetProtocol)) { - assert(!conformance->getConditionalRequirements().empty()); + assert(!conformance.getConditionalRequirements().empty()); return DynamicCastFeasibility::MaySucceed; } @@ -217,8 +217,7 @@ bool swift::isObjectiveCBridgeable(ModuleDecl *M, CanType Ty) { if (bridgedProto) { // Find the conformance of the value type to _BridgedToObjectiveC. // Check whether the type conforms to _BridgedToObjectiveC. - auto conformance = M->lookupConformance(Ty, bridgedProto); - return conformance.hasValue(); + return (bool)M->lookupConformance(Ty, bridgedProto); } return false; } @@ -232,8 +231,7 @@ bool swift::isError(ModuleDecl *M, CanType Ty) { if (errorTypeProto) { // Find the conformance of the value type to Error. // Check whether the type conforms to Error. - auto conformance = M->lookupConformance(Ty, errorTypeProto); - return conformance.hasValue(); + return (bool)M->lookupConformance(Ty, errorTypeProto); } return false; } diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index b7946ebd93014..2da0c35e5cac6 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -208,12 +208,13 @@ Lowering::adjustFunctionType(CanAnyFunctionType t, } /// Adjust a function type to have a slightly different type. -CanSILFunctionType Lowering::adjustFunctionType( - CanSILFunctionType type, SILFunctionType::ExtInfo extInfo, - ParameterConvention callee, - Optional witnessMethodConformance) { +CanSILFunctionType +Lowering::adjustFunctionType(CanSILFunctionType type, + SILFunctionType::ExtInfo extInfo, + ParameterConvention callee, + ProtocolConformanceRef witnessMethodConformance) { if (type->getExtInfo() == extInfo && type->getCalleeConvention() == callee && - type->getWitnessMethodConformanceOrNone() == witnessMethodConformance) + type->getWitnessMethodConformanceOrInvalid() == witnessMethodConformance) return type; return SILFunctionType::get(type->getSubstGenericSignature(), @@ -245,11 +246,10 @@ CanSILFunctionType SILFunctionType::getWithExtInfo(ExtInfo newExt) { : ParameterConvention::Direct_Unowned); return get(getSubstGenericSignature(), newExt, getCoroutineKind(), - calleeConvention, getParameters(), getYields(), - getResults(), getOptionalErrorResult(), - getSubstitutions(), isGenericSignatureImplied(), - getASTContext(), - getWitnessMethodConformanceOrNone()); + calleeConvention, getParameters(), getYields(), getResults(), + getOptionalErrorResult(), getSubstitutions(), + isGenericSignatureImplied(), getASTContext(), + getWitnessMethodConformanceOrInvalid()); } namespace { @@ -969,7 +969,7 @@ static CanSILFunctionType getSILFunctionType( const Conventions &conventions, const ForeignInfo &foreignInfo, Optional origConstant, Optional constant, Optional reqtSubs, - Optional witnessMethodConformance) { + ProtocolConformanceRef witnessMethodConformance) { // Per above, only fully honor opaqueness in the abstraction pattern // for thick or polymorphic functions. We don't need to worry about // non-opaque patterns because the type-checker forbids non-thick @@ -1284,10 +1284,9 @@ getSILFunctionTypeForAbstractCFunction(TypeConverter &TC, static CanSILFunctionType getNativeSILFunctionType( TypeConverter &TC, AbstractionPattern origType, CanAnyFunctionType substInterfaceType, AnyFunctionType::ExtInfo extInfo, - Optional origConstant, - Optional constant, + Optional origConstant, Optional constant, Optional reqtSubs, - Optional witnessMethodConformance) { + ProtocolConformanceRef witnessMethodConformance) { assert(bool(origConstant) == bool(constant)); switch (extInfo.getSILRepresentation()) { case SILFunctionType::Representation::Block: @@ -1349,11 +1348,10 @@ static CanSILFunctionType getNativeSILFunctionType( } CanSILFunctionType swift::getNativeSILFunctionType( - TypeConverter &TC, AbstractionPattern origType, CanAnyFunctionType substType, - Optional origConstant, - Optional substConstant, - Optional reqtSubs, - Optional witnessMethodConformance) { + TypeConverter &TC, AbstractionPattern origType, + CanAnyFunctionType substType, Optional origConstant, + Optional substConstant, Optional reqtSubs, + ProtocolConformanceRef witnessMethodConformance) { AnyFunctionType::ExtInfo extInfo; // Preserve type information from the original type if possible. @@ -1715,7 +1713,7 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, ObjCMethodConventions(method), foreignInfo, constant, constant, None, - /*witnessMethodConformance=*/None); + ProtocolConformanceRef()); } if (auto method = dyn_cast(clangDecl)) { @@ -1724,8 +1722,7 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, auto conventions = CXXMethodConventions(method); return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, conventions, foreignInfo, constant, constant, - None, - /*witnessMethodConformance=*/None); + None, ProtocolConformanceRef()); } if (auto func = dyn_cast(clangDecl)) { @@ -1736,9 +1733,8 @@ getSILFunctionTypeForClangDecl(TypeConverter &TC, const clang::Decl *clangDecl, foreignInfo.Self) : AbstractionPattern(origType, clangType); return getSILFunctionType(TC, origPattern, substInterfaceType, extInfo, - CFunctionConventions(func), foreignInfo, - constant, constant, None, - /*witnessMethodConformance=*/None); + CFunctionConventions(func), foreignInfo, constant, + constant, None, ProtocolConformanceRef()); } llvm_unreachable("call to unknown kind of C function"); @@ -1765,18 +1761,16 @@ getSILFunctionTypeForAbstractCFunction(TypeConverter &TC, llvm_unreachable("unexpected type imported as a function type"); } if (fnType) { - return getSILFunctionType(TC, origType, substType, extInfo, - CFunctionTypeConventions(fnType), ForeignInfo(), - constant, constant, None, - /*witnessMethodConformance=*/None); + return getSILFunctionType( + TC, origType, substType, extInfo, CFunctionTypeConventions(fnType), + ForeignInfo(), constant, constant, None, ProtocolConformanceRef()); } } // TODO: Ought to support captures in block funcs. return getSILFunctionType(TC, origType, substType, extInfo, - DefaultBlockConventions(), ForeignInfo(), - constant, constant, None, - /*witnessMethodConformance=*/None); + DefaultBlockConventions(), ForeignInfo(), constant, + constant, None, ProtocolConformanceRef()); } /// Try to find a clang method declaration for the given function. @@ -1940,11 +1934,10 @@ getSILFunctionTypeForObjCSelectorFamily(TypeConverter &TC, ObjCSelectorFamily fa AnyFunctionType::ExtInfo extInfo, const ForeignInfo &foreignInfo, Optional constant) { - return getSILFunctionType(TC, AbstractionPattern(origType), substInterfaceType, - extInfo, ObjCSelectorFamilyConventions(family), - foreignInfo, constant, constant, - /*requirement subs*/None, - /*witnessMethodConformance=*/None); + return getSILFunctionType( + TC, AbstractionPattern(origType), substInterfaceType, extInfo, + ObjCSelectorFamilyConventions(family), foreignInfo, constant, constant, + /*requirement subs*/ None, ProtocolConformanceRef()); } static bool isImporterGeneratedAccessor(const clang::Decl *clangDecl, @@ -1977,7 +1970,7 @@ getUncachedSILFunctionTypeForConstant(TypeConverter &TC, auto extInfo = origLoweredInterfaceType->getExtInfo(); if (!constant.isForeign) { - Optional witnessMethodConformance; + ProtocolConformanceRef witnessMethodConformance; if (extInfo.getSILRepresentation() == SILFunctionTypeRepresentation::WitnessMethod) { @@ -2332,7 +2325,7 @@ TypeConverter::getConstantOverrideInfo(SILDeclRef derived, SILDeclRef base) { // Build the SILFunctionType for the vtable thunk. CanSILFunctionType fnTy = getNativeSILFunctionType( *this, basePattern, overrideLoweredInterfaceTy, base, derived, - /*reqt subs*/None, /*witnessMethodConformance=*/None); + /*reqt subs*/ None, ProtocolConformanceRef()); // Build the SILConstantInfo and cache it. auto resultBuf = Context.Allocate(sizeof(SILConstantInfo), @@ -2426,8 +2419,8 @@ class SILTypeSubstituter : substYields.push_back(substInterface(origYield)); } - Optional witnessMethodConformance; - if (auto conformance = origType->getWitnessMethodConformanceOrNone()) { + ProtocolConformanceRef witnessMethodConformance; + if (auto conformance = origType->getWitnessMethodConformanceOrInvalid()) { assert(origType->getExtInfo().hasSelfParam()); auto selfType = origType->getSelfParameter().getInterfaceType(); // The Self type can be nested in a few layers of metatypes (etc.). @@ -2438,9 +2431,9 @@ class SILTypeSubstituter : selfType = next; } witnessMethodConformance = - conformance->subst(selfType, Subst, Conformances); + conformance.subst(selfType, Subst, Conformances); } - + // The substituted type is no longer generic, so it'd never be // pseudogeneric. auto extInfo = origType->getExtInfo().withIsPseudogeneric(false); diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 0444bb61b5c96..3fb60ee16c409 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -284,8 +284,10 @@ SILGenModule::getConformanceToObjectiveCBridgeable(SILLocation loc, Type type) { // Find the conformance to _ObjectiveCBridgeable. auto result = SwiftModule->lookupConformance(type, proto); - if (result) return result->getConcrete(); - return nullptr; + if (result.isInvalid()) + return nullptr; + + return result.getConcrete(); } ProtocolDecl *SILGenModule::getBridgedStoredNSError(SILLocation loc) { @@ -319,10 +321,11 @@ VarDecl *SILGenModule::getNSErrorRequirement(SILLocation loc) { return found; } -Optional +ProtocolConformanceRef SILGenModule::getConformanceToBridgedStoredNSError(SILLocation loc, Type type) { auto proto = getBridgedStoredNSError(loc); - if (!proto) return None; + if (!proto) + return ProtocolConformanceRef::forInvalid(); // Find the conformance to _BridgedStoredNSError. return SwiftModule->lookupConformance(type, proto); @@ -349,8 +352,8 @@ ProtocolConformance *SILGenModule::getNSErrorConformanceToError() { SwiftModule->lookupConformance(nsError->getDeclaredInterfaceType(), cast(error)); - if (conformance && conformance->isConcrete()) - NSErrorConformanceToError = conformance->getConcrete(); + if (conformance.isConcrete()) + NSErrorConformanceToError = conformance.getConcrete(); else NSErrorConformanceToError = nullptr; return *NSErrorConformanceToError; diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h index 981e3b4c9d8a1..021a16e5de469 100644 --- a/lib/SILGen/SILGen.h +++ b/lib/SILGen/SILGen.h @@ -393,8 +393,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { /// Find the conformance of the given Swift type to the /// _BridgedStoredNSError protocol. - Optional - getConformanceToBridgedStoredNSError(SILLocation loc, Type type); + ProtocolConformanceRef getConformanceToBridgedStoredNSError(SILLocation loc, + Type type); /// Retrieve the conformance of NSError to the Error protocol. ProtocolConformance *getNSErrorConformanceToError(); diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 459c9439008d3..00be4b4e930fa 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -55,10 +55,8 @@ SubstitutionMap SILGenModule::mapSubstitutionsForWitnessOverride( Type origProtoSelfType = origProto->getSelfInterfaceType(); auto baseProto = cast(overridden->getDeclContext()); return SubstitutionMap::getProtocolSubstitutions( - baseProto, - origProtoSelfType.subst(subs), - *subs.lookupConformance(origProtoSelfType->getCanonicalType(), - baseProto)); + baseProto, origProtoSelfType.subst(subs), + subs.lookupConformance(origProtoSelfType->getCanonicalType(), baseProto)); } /// Return the abstraction pattern to use when calling a function value. @@ -648,7 +646,7 @@ class Callee { auto proto = cast(Constant.getDecl()->getDeclContext()); auto selfType = proto->getSelfInterfaceType()->getCanonicalType(); auto lookupType = selfType.subst(Substitutions)->getCanonicalType(); - auto conformance = *Substitutions.lookupConformance(selfType, proto); + auto conformance = Substitutions.lookupConformance(selfType, proto); ArgumentScope S(SGF, Loc); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index bcf62f18ce9ff..5520e6f15536f 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -77,8 +77,7 @@ static bool shouldBridgeThroughError(SILGenModule &SGM, CanType type, } } - auto optConf = SGM.SwiftModule->lookupConformance(type, errorProtocol); - return optConf.hasValue(); + return (bool)SGM.SwiftModule->lookupConformance(type, errorProtocol); } /// Bridge the given Swift value to its corresponding Objective-C @@ -928,7 +927,7 @@ SILGenFunction::emitBlockToFunc(SILLocation loc, auto loweredFuncTyWithoutNoEscape = adjustFunctionType( loweredFuncTy, loweredFuncTy->getExtInfo().withNoEscape(false), - loweredFuncTy->getWitnessMethodConformanceOrNone()); + loweredFuncTy->getWitnessMethodConformanceOrInvalid()); CanType dynamicSelfType; auto thunkTy = buildThunkType(loweredBlockTy, loweredFuncTyWithoutNoEscape, @@ -1133,7 +1132,8 @@ ManagedValue SILGenFunction::emitBridgedToNativeError(SILLocation loc, auto nativeErrorTy = SILType::getExceptionType(getASTContext()); auto conformance = SGM.getNSErrorConformanceToError(); - if (!conformance) return emitUndef(nativeErrorTy); + if (!conformance) + return emitUndef(nativeErrorTy); ProtocolConformanceRef conformanceArray[] = { ProtocolConformanceRef(conformance) }; diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp index 7e45a01b5d444..d5cef2357495e 100644 --- a/lib/SILGen/SILGenConvert.cpp +++ b/lib/SILGen/SILGenConvert.cpp @@ -641,8 +641,9 @@ ManagedValue SILGenFunction::emitExistentialErasure( // If the concrete type is known to conform to _BridgedStoredNSError, // call the _nsError witness getter to extract the NSError directly, // then just erase the NSError. - if (auto storedNSErrorConformance = - SGM.getConformanceToBridgedStoredNSError(loc, concreteFormalType)) { + auto storedNSErrorConformance = + SGM.getConformanceToBridgedStoredNSError(loc, concreteFormalType); + if (storedNSErrorConformance) { auto nsErrorVar = SGM.getNSErrorRequirement(loc); if (!nsErrorVar) return emitUndef(existentialTL.getLoweredType()); @@ -650,9 +651,9 @@ ManagedValue SILGenFunction::emitExistentialErasure( // Devirtualize. Maybe this should be done implicitly by // emitPropertyLValue? - if (storedNSErrorConformance->isConcrete()) { + if (storedNSErrorConformance.isConcrete()) { if (auto normal = dyn_cast( - storedNSErrorConformance->getConcrete())) { + storedNSErrorConformance.getConcrete())) { if (auto witnessVar = normal->getWitness(nsErrorVar)) { nsErrorVar = cast(witnessVar.getDecl()); nsErrorVarSubstitutions = witnessVar.getSubstitutions(); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 7bba5ac38291b..65f4e81ffc9a7 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3226,10 +3226,8 @@ getOrCreateKeyPathEqualsAndHash(SILGenModule &SGM, SubstitutionMap hashableSubsMap = SubstitutionMap::get( hashGenericSig, [&](SubstitutableType *type) -> Type { return formalTy; }, - [&](CanType dependentType, Type replacementType, - ProtocolDecl *proto)->Optional { - return hashable; - }); + [&](CanType dependentType, Type replacementType, ProtocolDecl *proto) + -> ProtocolConformanceRef { return hashable; }); // Read the storage. ManagedValue base = ManagedValue::forBorrowedAddressRValue(indexAddr); diff --git a/lib/SILGen/SILGenLazyConformance.cpp b/lib/SILGen/SILGenLazyConformance.cpp index fdf8f8892631e..808098333f520 100644 --- a/lib/SILGen/SILGenLazyConformance.cpp +++ b/lib/SILGen/SILGenLazyConformance.cpp @@ -109,17 +109,15 @@ void SILGenModule::useConformancesFromObjectiveCType(CanType type) { return; if (objectiveCBridgeable) { - auto subConformance = SwiftModule->lookupConformance( - t, objectiveCBridgeable); - if (subConformance) - useConformance(*subConformance); + if (auto subConformance = + SwiftModule->lookupConformance(t, objectiveCBridgeable)) + useConformance(subConformance); } if (bridgedStoredNSError) { - auto subConformance = SwiftModule->lookupConformance( - t, bridgedStoredNSError); - if (subConformance) - useConformance(*subConformance); + if (auto subConformance = + SwiftModule->lookupConformance(t, bridgedStoredNSError)) + useConformance(subConformance); } }); } diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index d496bbe7357f8..a62315dc41e03 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -177,7 +177,8 @@ collectExistentialConformances(ModuleDecl *M, CanType fromType, CanType toType) for (auto proto : protocols) { auto conformance = M->lookupConformance(fromType, proto->getDecl()); - conformances.push_back(*conformance); + assert(conformance); + conformances.push_back(conformance); } return M->getASTContext().AllocateCopy(conformances); @@ -596,9 +597,8 @@ ManagedValue Transform::transform(ManagedValue v, auto conformance = SGF.SGM.M.getSwiftModule()->lookupConformance( inputSubstType, protocol); auto addr = v.getType().isAddress() ? v : v.materialize(SGF, Loc); - auto result = SGF.emitAnyHashableErasure(Loc, addr, - inputSubstType, *conformance, - ctxt); + auto result = SGF.emitAnyHashableErasure(Loc, addr, inputSubstType, + conformance, ctxt); if (result.isInContext()) return ManagedValue::forInContext(); return std::move(result).getAsSingleValue(SGF, Loc); @@ -3385,7 +3385,7 @@ ManagedValue Transform::transformFunction(ManagedValue fn, : expectedFnType->isNoEscape()); auto newFnType = adjustFunctionType(expectedFnType, newEI, fnType->getCalleeConvention(), - fnType->getWitnessMethodConformanceOrNone()); + fnType->getWitnessMethodConformanceOrInvalid()); // Apply any ABI-compatible conversions before doing thin-to-thick or // escaping->noescape conversion. @@ -3764,7 +3764,7 @@ getSelfTypeAndConformanceForWitness(SILDeclRef witness, SubstitutionMap subs) { auto protocol = cast(witness.getDecl()->getDeclContext()); auto selfParam = protocol->getProtocolSelfType()->getCanonicalType(); auto type = subs.getReplacementTypes()[0]; - auto conf = *subs.lookupConformance(selfParam, protocol); + auto conf = subs.lookupConformance(selfParam, protocol); return {type->getCanonicalType(), conf}; } diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp index 28cb57d81dfd3..78dfdba0cfb85 100644 --- a/lib/SILGen/SILGenStmt.cpp +++ b/lib/SILGen/SILGenStmt.cpp @@ -931,7 +931,7 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) { if (S->getConvertElementExpr()) { optTy = S->getConvertElementExpr()->getType()->getCanonicalType(); } else { - optTy = OptionalType::get(S->getSequenceConformance()->getTypeWitnessByName( + optTy = OptionalType::get(S->getSequenceConformance().getTypeWitnessByName( S->getSequence()->getType(), SGF.getASTContext().Id_Element)) ->getCanonicalType(); diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp index d3eb9b061d2b3..37f9557a8ce53 100644 --- a/lib/SILGen/SILGenThunk.cpp +++ b/lib/SILGen/SILGenThunk.cpp @@ -133,7 +133,7 @@ getNextUncurryLevelRef(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk, auto origSelfType = protocol->getSelfInterfaceType()->getCanonicalType(); auto substSelfType = origSelfType.subst(curriedSubs)->getCanonicalType(); auto conformance = curriedSubs.lookupConformance(origSelfType, protocol); - auto result = SGF.B.createWitnessMethod(loc, substSelfType, *conformance, + auto result = SGF.B.createWitnessMethod(loc, substSelfType, conformance, next, constantInfo.getSILType()); return {ManagedValue::forUnmanaged(result), next}; } diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp index ada9e7a6e0dca..9e634105d3594 100644 --- a/lib/SILGen/SILGenType.cpp +++ b/lib/SILGen/SILGenType.cpp @@ -562,7 +562,7 @@ class SILGenConformance : public SILGenWitnessTable { "unable to find conformance that should be known"); ConditionalConformances.push_back( - SILWitnessTable::ConditionalConformance{type, *conformance}); + SILWitnessTable::ConditionalConformance{type, conformance}); return /*finished?*/ false; }); @@ -627,7 +627,7 @@ SILFunction *SILGenModule::emitProtocolWitness( auto requirement = conformance.getRequirement(); auto self = requirement->getSelfInterfaceType()->getCanonicalType(); - conformance = *reqtSubMap.lookupConformance(self, requirement); + conformance = reqtSubMap.lookupConformance(self, requirement); } reqtSubstTy = @@ -901,14 +901,11 @@ class SILGenDefaultWitnessTable Proto->getDefaultAssociatedConformanceWitness( req.getAssociation(), req.getAssociatedRequirement()); - if (!witness) + if (witness.isInvalid()) return addMissingDefault(); - auto entry = - SILWitnessTable::AssociatedTypeProtocolWitness{ - req.getAssociation(), - req.getAssociatedRequirement(), - *witness}; + auto entry = SILWitnessTable::AssociatedTypeProtocolWitness{ + req.getAssociation(), req.getAssociatedRequirement(), witness}; DefaultWitnesses.push_back(entry); } }; diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index e6791d0f99fab..b4d3be9dbda36 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -362,7 +362,7 @@ ExistentialTransform::createExistentialSpecializedFunctionType() { /// Finally the ExtInfo. auto ExtInfo = FTy->getExtInfo(); ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin); - auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrNone(); + auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrInvalid(); /// Return the new signature. return SILFunctionType::get( diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp index 8571ddbc0c939..8e298f9a6b70c 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp @@ -378,10 +378,10 @@ FunctionSignatureTransformDescriptor::createOptimizedSILFunctionType() { // Don't use a method representation if we modified self. auto ExtInfo = FTy->getExtInfo(); - auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrNone(); + auto witnessMethodConformance = FTy->getWitnessMethodConformanceOrInvalid(); if (shouldModifySelfArgument) { ExtInfo = ExtInfo.withRepresentation(SILFunctionTypeRepresentation::Thin); - witnessMethodConformance = None; + witnessMethodConformance = ProtocolConformanceRef::forInvalid(); } Optional InterfaceErrorResult; diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp index 8c1a29af10529..409b397142d17 100644 --- a/lib/SILOptimizer/IPO/CapturePromotion.cpp +++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp @@ -427,10 +427,9 @@ ClosureCloner::initCloned(SILOptFunctionBuilder &FunctionBuilder, auto ClonedTy = SILFunctionType::get( OrigFTI->getInvocationGenericSignature(), OrigFTI->getExtInfo(), OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(), - ClonedInterfaceArgTys, OrigFTI->getYields(), - OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(), - SubstitutionMap(), false, - M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone()); + ClonedInterfaceArgTys, OrigFTI->getYields(), OrigFTI->getResults(), + OrigFTI->getOptionalErrorResult(), SubstitutionMap(), false, + M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrInvalid()); assert((Orig->isTransparent() || Orig->isBare() || Orig->getLocation()) && "SILFunction missing location"); diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index de18d28ede237..42bd42c43c75d 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -1258,7 +1258,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType( return type; }, [&](CanType origTy, Type substTy, - ProtocolDecl *proto) -> Optional { + ProtocolDecl *proto) -> ProtocolConformanceRef { if (origTy->isEqual(OAI.OpenedArchetype)) { assert(substTy->isEqual(CEI.ConcreteType)); // Do a conformance lookup on this witness requirement using the @@ -1376,7 +1376,7 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite Apply, // Get the conformance of the init_existential type, which is passed as the // self argument, on the witness' protocol. ProtocolConformanceRef SelfConformance = - *SelfCEI.lookupExistentialConformance(WMI->getLookupProtocol()); + SelfCEI.lookupExistentialConformance(WMI->getLookupProtocol()); // Propagate the concrete type into a callee-operand, which is a // witness_method instruction. It's ok to rewrite the witness method in terms diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp index 33e07d8340a78..42752a6acda1e 100644 --- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp +++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp @@ -601,10 +601,10 @@ SILFunction *PromotedParamCloner::initCloned(SILOptFunctionBuilder &FuncBuilder, auto ClonedTy = SILFunctionType::get( OrigFTI->getSubstGenericSignature(), OrigFTI->getExtInfo(), OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(), - ClonedInterfaceArgTys, OrigFTI->getYields(), - OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(), - OrigFTI->getSubstitutions(), OrigFTI->isGenericSignatureImplied(), - M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone()); + ClonedInterfaceArgTys, OrigFTI->getYields(), OrigFTI->getResults(), + OrigFTI->getOptionalErrorResult(), OrigFTI->getSubstitutions(), + OrigFTI->isGenericSignatureImplied(), M.getASTContext(), + OrigFTI->getWitnessMethodConformanceOrInvalid()); assert((Orig->isTransparent() || Orig->isBare() || Orig->getLocation()) && "SILFunction missing location"); diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp index 39dccba57604c..f3b4432454460 100644 --- a/lib/SILOptimizer/Transforms/Outliner.cpp +++ b/lib/SILOptimizer/Transforms/Outliner.cpp @@ -138,10 +138,10 @@ static SILDeclRef getBridgeToObjectiveC(CanType NativeType, return SILDeclRef(); auto ConformanceRef = SwiftModule->lookupConformance(NativeType, Proto); - if (!ConformanceRef) + if (ConformanceRef.isInvalid()) return SILDeclRef(); - auto Conformance = ConformanceRef->getConcrete(); + auto Conformance = ConformanceRef.getConcrete(); // bridgeToObjectiveC DeclName Name(Ctx, Ctx.Id_bridgeToObjectiveC, llvm::ArrayRef()); auto *Requirement = dyn_cast_or_null( @@ -162,9 +162,9 @@ SILDeclRef getBridgeFromObjectiveC(CanType NativeType, return SILDeclRef(); auto ConformanceRef = SwiftModule->lookupConformance(NativeType, Proto); - if (!ConformanceRef) + if (ConformanceRef.isInvalid()) return SILDeclRef(); - auto Conformance = ConformanceRef->getConcrete(); + auto Conformance = ConformanceRef.getConcrete(); // _unconditionallyBridgeFromObjectiveC DeclName Name(Ctx, Ctx.getIdentifier("_unconditionallyBridgeFromObjectiveC"), llvm::makeArrayRef(Identifier())); diff --git a/lib/SILOptimizer/Utils/CastOptimizer.cpp b/lib/SILOptimizer/Utils/CastOptimizer.cpp index f6d6c687646b8..1ff70ac1ea143 100644 --- a/lib/SILOptimizer/Utils/CastOptimizer.cpp +++ b/lib/SILOptimizer/Utils/CastOptimizer.cpp @@ -74,7 +74,7 @@ static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod, CanType target) { auto bridgedProto = mod.getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable); - auto conf = *mod.getSwiftModule()->lookupConformance(target, bridgedProto); + auto conf = mod.getSwiftModule()->lookupConformance(target, bridgedProto); return SubstitutionMap::getProtocolSubstitutions(conf.getRequirement(), target, conf); } @@ -1522,12 +1522,12 @@ static bool optimizeStaticallyKnownProtocolConformance( // everything is completely static (`X() as? P`), in which case a // valid conformance will be returned. auto Conformance = SM->conformsToProtocol(SourceType, Proto); - if (!Conformance) + if (Conformance.isInvalid()) return false; SILBuilderWithScope B(Inst); SmallVector NewConformances; - NewConformances.push_back(Conformance.getValue()); + NewConformances.push_back(Conformance); ArrayRef Conformances = Ctx.AllocateCopy(NewConformances); diff --git a/lib/SILOptimizer/Utils/ConstExpr.cpp b/lib/SILOptimizer/Utils/ConstExpr.cpp index c55b77d1c4dfd..7fbbec373f3cb 100644 --- a/lib/SILOptimizer/Utils/ConstExpr.cpp +++ b/lib/SILOptimizer/Utils/ConstExpr.cpp @@ -380,12 +380,11 @@ SymbolicValue ConstExprFunctionState::computeConstantValue(SILValue value) { // Try to resolve a witness method against our known conformances. if (auto *wmi = dyn_cast(value)) { - auto confResult = substitutionMap.lookupConformance( + auto conf = substitutionMap.lookupConformance( wmi->getLookupType(), wmi->getConformance().getRequirement()); - if (!confResult) + if (conf.isInvalid()) return getUnknown(evaluator, value, UnknownReason::UnknownWitnessMethodConformance); - auto conf = confResult.getValue(); auto &module = wmi->getModule(); SILFunction *fn = module.lookUpFunctionInWitnessTable(conf, wmi->getMember()).first; @@ -1134,7 +1133,7 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) { if (calleeFnType->getRepresentation() == SILFunctionType::Representation::WitnessMethod) { auto protocol = - calleeFnType->getWitnessMethodConformance().getRequirement(); + calleeFnType->getWitnessMethodConformanceOrInvalid().getRequirement(); // Compute a mapping that maps the Self type of the protocol given by // 'requirement' to the concrete type available in the substitutionMap. auto protoSelfToConcreteType = @@ -1143,12 +1142,12 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) { // Self type of the requirement. auto conf = protoSelfToConcreteType.lookupConformance( protocol->getSelfInterfaceType()->getCanonicalType(), protocol); - if (!conf.hasValue()) + if (conf.isInvalid()) return getUnknown(evaluator, (SILInstruction *)apply, UnknownReason::UnknownWitnessMethodConformance); callSubMap = getWitnessMethodSubstitutions( - apply->getModule(), ApplySite(apply), callee, conf.getValue()); + apply->getModule(), ApplySite(apply), callee, conf); /// Remark: If we ever start to care about evaluating classes, /// getSubstitutionsForCallee() is the analogous mapping function we diff --git a/lib/SILOptimizer/Utils/Existential.cpp b/lib/SILOptimizer/Utils/Existential.cpp index 07a78d2747972..012f8aa3f9e32 100644 --- a/lib/SILOptimizer/Utils/Existential.cpp +++ b/lib/SILOptimizer/Utils/Existential.cpp @@ -362,11 +362,11 @@ ConcreteExistentialInfo::ConcreteExistentialInfo(SILValue existential, // We have the open_existential; we still need the conformance. auto ConformanceRef = M->getSwiftModule()->conformsToProtocol(ConcreteTypeCandidate, Protocol); - if (!ConformanceRef) + if (ConformanceRef.isInvalid()) return; // Assert that the conformance is complete. - auto *ConcreteConformance = ConformanceRef.getValue().getConcrete(); + auto *ConcreteConformance = ConformanceRef.getConcrete(); assert(ConcreteConformance->isComplete()); ConcreteType = ConcreteTypeCandidate; diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp index 44c9c3ff0097d..4ce7a0b3d5d4b 100644 --- a/lib/SILOptimizer/Utils/Generics.cpp +++ b/lib/SILOptimizer/Utils/Generics.cpp @@ -772,12 +772,10 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF, // Use the new specialized generic signature. auto NewFnTy = SILFunctionType::get( - CanSpecializedGenericSig, FnTy->getExtInfo(), - FnTy->getCoroutineKind(), FnTy->getCalleeConvention(), - FnTy->getParameters(), FnTy->getYields(), - FnTy->getResults(), FnTy->getOptionalErrorResult(), - SubstitutionMap(), false, - M.getASTContext(), FnTy->getWitnessMethodConformanceOrNone()); + CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCoroutineKind(), + FnTy->getCalleeConvention(), FnTy->getParameters(), FnTy->getYields(), + FnTy->getResults(), FnTy->getOptionalErrorResult(), SubstitutionMap(), + false, M.getASTContext(), FnTy->getWitnessMethodConformanceOrInvalid()); // This is an interface type. It should not have any archetypes. assert(!NewFnTy->hasArchetype()); @@ -846,13 +844,11 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const { SpecializedYields.push_back(YI); } return SILFunctionType::get( - SubstFTy->getInvocationGenericSignature(), - SubstFTy->getExtInfo(), SubstFTy->getCoroutineKind(), - SubstFTy->getCalleeConvention(), + SubstFTy->getInvocationGenericSignature(), SubstFTy->getExtInfo(), + SubstFTy->getCoroutineKind(), SubstFTy->getCalleeConvention(), SpecializedParams, SpecializedYields, SpecializedResults, - SubstFTy->getOptionalErrorResult(), - SubstitutionMap(), false, M.getASTContext(), - SubstFTy->getWitnessMethodConformanceOrNone()); + SubstFTy->getOptionalErrorResult(), SubstitutionMap(), false, + M.getASTContext(), SubstFTy->getWitnessMethodConformanceOrInvalid()); } /// Create a new generic signature from an existing one by adding diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index d8330e70bbdee..4736d3637466f 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -77,8 +77,8 @@ Solution::computeSubstitutions(GenericSignature sig, subs[opened.first] = getFixedType(opened.second); auto lookupConformanceFn = - [&](CanType original, Type replacement, ProtocolDecl *protoType) - -> Optional { + [&](CanType original, Type replacement, + ProtocolDecl *protoType) -> ProtocolConformanceRef { if (replacement->hasError() || isOpenedAnyObject(replacement) || replacement->is()) { @@ -436,9 +436,9 @@ namespace { TypeChecker::conformsToProtocol( baseTy, proto, cs.DC, ConformanceCheckFlags::InExpression); - if (conformance && conformance->isConcrete()) { + if (conformance.isConcrete()) { if (auto witness = - conformance->getConcrete()->getWitnessDecl(decl)) { + conformance.getConcrete()->getWitnessDecl(decl)) { // Hack up an AST that we can type-check (independently) to get // it into the right form. // FIXME: the hop through 'getDecl()' is because @@ -1739,7 +1739,7 @@ namespace { FuncDecl *fn = nullptr; if (bridgedToObjectiveCConformance) { - assert(bridgedToObjectiveCConformance->getConditionalRequirements() + assert(bridgedToObjectiveCConformance.getConditionalRequirements() .empty() && "cannot conditionally conform to _BridgedToObjectiveC"); // The conformance to _BridgedToObjectiveC is statically known. @@ -1766,16 +1766,16 @@ namespace { auto genericSig = fn->getGenericSignature(); auto subMap = SubstitutionMap::get( - genericSig, - [&](SubstitutableType *type) -> Type { - assert(type->isEqual(genericSig->getGenericParams()[0])); - return valueType; - }, - [&](CanType origType, Type replacementType, ProtocolDecl *protoType) - -> ProtocolConformanceRef { - assert(bridgedToObjectiveCConformance); - return *bridgedToObjectiveCConformance; - }); + genericSig, + [&](SubstitutableType *type) -> Type { + assert(type->isEqual(genericSig->getGenericParams()[0])); + return valueType; + }, + [&](CanType origType, Type replacementType, + ProtocolDecl *protoType) -> ProtocolConformanceRef { + assert(bridgedToObjectiveCConformance); + return bridgedToObjectiveCConformance; + }); ConcreteDeclRef fnSpecRef(fn, subMap); @@ -2004,8 +2004,8 @@ namespace { ProtocolDecl *protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral); - if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol( + type, protocol, cs.DC, ConformanceCheckFlags::InExpression)) { // If the type does not conform to ExpressibleByStringLiteral, it should // be ExpressibleByExtendedGraphemeClusterLiteral. protocol = tc.getProtocol( @@ -2014,8 +2014,8 @@ namespace { isStringLiteral = false; isGraphemeClusterLiteral = true; } - if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol( + type, protocol, cs.DC, ConformanceCheckFlags::InExpression)) { // ... or it should be ExpressibleByUnicodeScalarLiteral. protocol = tc.getProtocol( expr->getLoc(), @@ -2139,7 +2139,7 @@ namespace { DeclName constrName(tc.Context, DeclBaseName::createConstructor(), argLabels); ConcreteDeclRef witness = - conformance->getWitnessByName(type->getRValueType(), constrName); + conformance.getWitnessByName(type->getRValueType(), constrName); if (!witness || !isa(witness.getDecl())) return nullptr; return witness; @@ -2244,9 +2244,8 @@ namespace { DeclName constrName(tc.getObjectLiteralConstructorName(expr)); - ConcreteDeclRef witness = - conformance->getWitnessByName(conformingType->getRValueType(), - constrName); + ConcreteDeclRef witness = conformance.getWitnessByName( + conformingType->getRValueType(), constrName); if (!witness || !isa(witness.getDecl())) return nullptr; expr->setInitializer(witness); @@ -2906,7 +2905,7 @@ namespace { DeclName name(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_arrayLiteral }); ConcreteDeclRef witness = - conformance->getWitnessByName(arrayTy->getRValueType(), name); + conformance.getWitnessByName(arrayTy->getRValueType(), name); if (!witness || !isa(witness.getDecl())) return nullptr; expr->setInitializer(witness); @@ -2946,13 +2945,13 @@ namespace { auto conformance = TypeChecker::conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, ConformanceCheckFlags::InExpression); - if (!conformance) + if (conformance.isInvalid()) return nullptr; DeclName name(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_dictionaryLiteral }); ConcreteDeclRef witness = - conformance->getWitnessByName(dictionaryTy->getRValueType(), name); + conformance.getWitnessByName(dictionaryTy->getRValueType(), name); if (!witness || !isa(witness.getDecl())) return nullptr; expr->setInitializer(witness); @@ -4652,9 +4651,9 @@ namespace { auto hashableConformance = TypeChecker::conformsToProtocol(indexType, hashable, cs.DC, ConformanceCheckFlags::InExpression); - assert(hashableConformance.hasValue()); + assert(hashableConformance); - conformances.push_back(*hashableConformance); + conformances.push_back(hashableConformance); } component.setSubscriptIndexHashableConformances(conformances); @@ -5022,9 +5021,8 @@ collectExistentialConformances(TypeChecker &tc, Type fromType, Type toType, SmallVector conformances; for (auto proto : layout.getProtocols()) { - conformances.push_back( - *tc.containsProtocol(fromType, proto->getDecl(), DC, - ConformanceCheckFlags::InExpression)); + conformances.push_back(tc.containsProtocol( + fromType, proto->getDecl(), DC, ConformanceCheckFlags::InExpression)); } return tc.Context.AllocateCopy(conformances); @@ -6120,7 +6118,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, assert(conformance && "must conform to Hashable"); return cs.cacheType( - new (tc.Context) AnyHashableErasureExpr(expr, toType, *conformance)); + new (tc.Context) AnyHashableErasureExpr(expr, toType, conformance)); } case ConversionRestrictionKind::DictionaryUpcast: { @@ -6600,37 +6598,36 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, // Check whether this literal type conforms to the builtin protocol. If so, // initialize via the builtin protocol. - Optional builtinConformance; - if (builtinProtocol && - (builtinConformance = - TypeChecker::conformsToProtocol(type, builtinProtocol, cs.DC, - ConformanceCheckFlags::InExpression))) { - - // Find the witness that we'll use to initialize the type via a builtin - // literal. - auto witness = builtinConformance->getWitnessByName(type->getRValueType(), - builtinLiteralFuncName); - if (!witness || !isa(witness.getDecl())) - return nullptr; + if (builtinProtocol) { + auto builtinConformance = TypeChecker::conformsToProtocol( + type, builtinProtocol, cs.DC, ConformanceCheckFlags::InExpression); + if (builtinConformance) { + // Find the witness that we'll use to initialize the type via a builtin + // literal. + auto witness = builtinConformance.getWitnessByName( + type->getRValueType(), builtinLiteralFuncName); + if (!witness || !isa(witness.getDecl())) + return nullptr; - // Form a reference to the builtin conversion function. + // Form a reference to the builtin conversion function. - // Set the builtin initializer. - if (auto stringLiteral = dyn_cast(literal)) - stringLiteral->setBuiltinInitializer(witness); - else if (auto booleanLiteral = dyn_cast(literal)) - booleanLiteral->setBuiltinInitializer(witness); - else if (auto numberLiteral = dyn_cast(literal)) - numberLiteral->setBuiltinInitializer(witness); - else { - cast(literal) - ->setBuiltinInitializer(witness); - } + // Set the builtin initializer. + if (auto stringLiteral = dyn_cast(literal)) + stringLiteral->setBuiltinInitializer(witness); + else if (auto booleanLiteral = dyn_cast(literal)) + booleanLiteral->setBuiltinInitializer(witness); + else if (auto numberLiteral = dyn_cast(literal)) + numberLiteral->setBuiltinInitializer(witness); + else { + cast(literal)->setBuiltinInitializer( + witness); + } - // The literal expression has this type. - cs.setType(literal, type); + // The literal expression has this type. + cs.setType(literal, type); - return literal; + return literal; + } } // This literal type must conform to the (non-builtin) protocol. @@ -6643,7 +6640,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, if (!literalType.empty()) { // Extract the literal type. Type builtinLiteralType = - conformance->getTypeWitnessByName(type, literalType); + conformance.getTypeWitnessByName(type, literalType); if (builtinLiteralType->hasError()) return nullptr; @@ -6656,8 +6653,8 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, } // Find the witness that we'll use to initialize the literal value. - auto witness = conformance->getWitnessByName(type->getRValueType(), - literalFuncName); + auto witness = + conformance.getWitnessByName(type->getRValueType(), literalFuncName); if (!witness || !isa(witness.getDecl())) return nullptr; @@ -6778,9 +6775,9 @@ ExprRewriter::finishApplyDynamicCallable(ApplyExpr *apply, auto conformance = cs.TC.conformsToProtocol(argumentType, dictLitProto, cs.DC, ConformanceCheckFlags::InExpression); - auto keyType = conformance->getTypeWitnessByName(argumentType, ctx.Id_Key); - auto valueType = conformance->getTypeWitnessByName(argumentType, - ctx.Id_Value); + auto keyType = conformance.getTypeWitnessByName(argumentType, ctx.Id_Key); + auto valueType = + conformance.getTypeWitnessByName(argumentType, ctx.Id_Value); SmallVector names; SmallVector dictElements; for (unsigned i = 0, n = arg->getNumElements(); i < n; i++) { diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index d3c385542b25a..596a3ee5f1d5d 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -795,11 +795,11 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){ } // Emit a conformance error through conformsToProtocol. - if (auto conformance = TypeChecker::conformsToProtocol( - fromType, PT->getDecl(), CS.DC, ConformanceCheckFlags::InExpression, - expr->getLoc())) { - if (conformance->isAbstract() || - !conformance->getConcrete()->isInvalid()) + auto conformance = TypeChecker::conformsToProtocol( + fromType, PT->getDecl(), CS.DC, ConformanceCheckFlags::InExpression, + expr->getLoc()); + if (conformance) { + if (conformance.isAbstract() || !conformance.getConcrete()->isInvalid()) return false; } @@ -3668,12 +3668,13 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) { return visitExpr(E); // Check to see if the contextual type conforms. - if (auto Conformance - = TypeChecker::conformsToProtocol(contextualType, ALC, CS.DC, - ConformanceCheckFlags::InExpression)) { + auto Conformance = TypeChecker::conformsToProtocol( + contextualType, ALC, CS.DC, ConformanceCheckFlags::InExpression); + if (Conformance) { Type contextualElementType = - Conformance->getTypeWitnessByName( - contextualType, CS.getASTContext().Id_ArrayLiteralElement) + Conformance + .getTypeWitnessByName(contextualType, + CS.getASTContext().Id_ArrayLiteralElement) ->getDesugaredType(); // Type check each of the subexpressions in place, passing down the contextual @@ -3719,20 +3720,20 @@ bool FailureDiagnosis::visitDictionaryExpr(DictionaryExpr *E) { // and figure out what the contextual Key/Value types are in place. auto Conformance = TypeChecker::conformsToProtocol( contextualType, DLC, CS.DC, ConformanceCheckFlags::InExpression); - if (!Conformance) { + if (Conformance.isInvalid()) { diagnose(E->getStartLoc(), diag::type_is_not_dictionary, contextualType) .highlight(E->getSourceRange()); return true; } contextualKeyType = - Conformance->getTypeWitnessByName( - contextualType, CS.getASTContext().Id_Key) + Conformance + .getTypeWitnessByName(contextualType, CS.getASTContext().Id_Key) ->getDesugaredType(); contextualValueType = - Conformance->getTypeWitnessByName( - contextualType, CS.getASTContext().Id_Value) + Conformance + .getTypeWitnessByName(contextualType, CS.getASTContext().Id_Value) ->getDesugaredType(); assert(contextualKeyType && contextualValueType && diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index f1b6b4468f833..f6fdb91a29db4 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2291,13 +2291,14 @@ bool ContextualFailure::diagnoseThrowsTypeMismatch() const { if (auto errorCodeProtocol = TC.Context.getProtocol(KnownProtocolKind::ErrorCodeProtocol)) { Type errorCodeType = getFromType(); - if (auto conformance = TypeChecker::conformsToProtocol( - errorCodeType, errorCodeProtocol, getDC(), - ConformanceCheckFlags::InExpression)) { - Type errorType = conformance - ->getTypeWitnessByName(errorCodeType, - getASTContext().Id_ErrorType) - ->getCanonicalType(); + auto conformance = TypeChecker::conformsToProtocol( + errorCodeType, errorCodeProtocol, getDC(), + ConformanceCheckFlags::InExpression); + if (conformance) { + Type errorType = + conformance + .getTypeWitnessByName(errorCodeType, getASTContext().Id_ErrorType) + ->getCanonicalType(); if (errorType) { auto diagnostic = emitDiagnostic(anchor->getLoc(), diag::cannot_throw_error_code, @@ -2612,9 +2613,10 @@ bool ContextualFailure::tryProtocolConformanceFixIt( // Let's build a list of protocols that the context does not conform to. SmallVector missingProtoTypeStrings; for (auto protocol : layout.getProtocols()) { - if (!getTypeChecker().conformsToProtocol( - FromType, protocol->getDecl(), getDC(), - ConformanceCheckFlags::InExpression)) { + if (getTypeChecker() + .conformsToProtocol(FromType, protocol->getDecl(), getDC(), + ConformanceCheckFlags::InExpression) + .isInvalid()) { missingProtoTypeStrings.push_back(protocol->getString()); } } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index d3d4cb4f90296..a29da57a2f42f 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -558,8 +558,9 @@ namespace { // the literal. if (otherArgTy && otherArgTy->getAnyNominal()) { if (otherArgTy->isEqual(paramTy) && - TypeChecker::conformsToProtocol(otherArgTy, literalProto, CS.DC, - ConformanceCheckFlags::InExpression)) + TypeChecker::conformsToProtocol( + otherArgTy, literalProto, CS.DC, + ConformanceCheckFlags::InExpression)) return true; } else if (Type defaultType = tc.getDefaultType(literalProto, CS.DC)) { // If there is a default type for the literal protocol, check whether diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index 5da63bd21c75a..21bd990d365d5 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -200,13 +200,13 @@ static bool isNominallySuperclassOf(Type type1, Type type2) { /// Determine the relationship between the self types of the given declaration /// contexts.. -static std::pair> +static std::pair computeSelfTypeRelationship(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, ValueDecl *decl2) { // If both declarations are operators, even through they // might have Self such types are unrelated. if (decl1->isOperator() && decl2->isOperator()) - return {SelfTypeRelationship::Unrelated, None}; + return {SelfTypeRelationship::Unrelated, ProtocolConformanceRef()}; auto *dc1 = decl1->getDeclContext(); auto *dc2 = decl2->getDeclContext(); @@ -214,32 +214,32 @@ computeSelfTypeRelationship(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, // If at least one of the contexts is a non-type context, the two are // unrelated. if (!dc1->isTypeContext() || !dc2->isTypeContext()) - return {SelfTypeRelationship::Unrelated, None}; + return {SelfTypeRelationship::Unrelated, ProtocolConformanceRef()}; Type type1 = dc1->getDeclaredInterfaceType(); Type type2 = dc2->getDeclaredInterfaceType(); // If the types are equal, the answer is simple. if (type1->isEqual(type2)) - return {SelfTypeRelationship::Equivalent, None}; + return {SelfTypeRelationship::Equivalent, ProtocolConformanceRef()}; // If both types can have superclasses, which whether one is a superclass // of the other. The subclass is the common base type. if (type1->mayHaveSuperclass() && type2->mayHaveSuperclass()) { if (isNominallySuperclassOf(type1, type2)) - return {SelfTypeRelationship::Superclass, None}; + return {SelfTypeRelationship::Superclass, ProtocolConformanceRef()}; if (isNominallySuperclassOf(type2, type1)) - return {SelfTypeRelationship::Subclass, None}; + return {SelfTypeRelationship::Subclass, ProtocolConformanceRef()}; - return {SelfTypeRelationship::Unrelated, None}; + return {SelfTypeRelationship::Unrelated, ProtocolConformanceRef()}; } // If neither or both are protocol types, consider the bases unrelated. bool isProtocol1 = isa(dc1); bool isProtocol2 = isa(dc2); if (isProtocol1 == isProtocol2) - return {SelfTypeRelationship::Unrelated, None}; + return {SelfTypeRelationship::Unrelated, ProtocolConformanceRef()}; // Just one of the two is a protocol. Check whether the other conforms to // that protocol. @@ -253,8 +253,8 @@ computeSelfTypeRelationship(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, modelTy, proto, dc, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements)); - if (!conformance) - return {SelfTypeRelationship::Unrelated, None}; + if (conformance.isInvalid()) + return {SelfTypeRelationship::Unrelated, conformance}; if (isProtocol1) return {SelfTypeRelationship::ConformedToBy, conformance}; diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index dae06c0c23aed..bed8d3bfbd65a 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4344,26 +4344,26 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( // conform -- they only need to contain the protocol, so check that // separately. switch (kind) { - case ConstraintKind::SelfObjectOfProtocol: - if (auto conformance = - TC.containsProtocol(type, protocol, DC, - (ConformanceCheckFlags::InExpression| - ConformanceCheckFlags::SkipConditionalRequirements))) { - return recordConformance(*conformance); - } - break; + case ConstraintKind::SelfObjectOfProtocol: { + auto conformance = TC.containsProtocol( + type, protocol, DC, + (ConformanceCheckFlags::InExpression | + ConformanceCheckFlags::SkipConditionalRequirements)); + if (conformance) { + return recordConformance(conformance); + } + } break; case ConstraintKind::ConformsTo: case ConstraintKind::LiteralConformsTo: { // Check whether this type conforms to the protocol. - if (auto conformance = - TypeChecker::conformsToProtocol( - type, protocol, DC, - (ConformanceCheckFlags::InExpression| - ConformanceCheckFlags::SkipConditionalRequirements))) { - return recordConformance(*conformance); - } - break; - } + auto conformance = TypeChecker::conformsToProtocol( + type, protocol, DC, + (ConformanceCheckFlags::InExpression | + ConformanceCheckFlags::SkipConditionalRequirements)); + if (conformance) { + return recordConformance(conformance); + } + } break; default: llvm_unreachable("bad constraint kind"); diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index 91b82eaf0f6ac..7b52fee211d14 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1709,10 +1709,10 @@ void ConstraintSystem::ArgumentInfoCollector::minimizeLiteralProtocols() { auto second = TypeChecker::conformsToProtocol(candidates[result].second, candidate.first, CS.DC, ConformanceCheckFlags::InExpression); - if ((first && second) || (!first && !second)) + if (first.isInvalid() == second.isInvalid()) return; - if (first) + if (!first.isInvalid()) result = i; } @@ -1909,8 +1909,8 @@ void ConstraintSystem::sortDesignatedTypes( ++nextType; break; } else if (auto *protoDecl = dyn_cast(nominalTypes[i])) { - if (TypeChecker::conformsToProtocol(argType, protoDecl, DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol( + argType, protoDecl, DC, ConformanceCheckFlags::InExpression)) { std::swap(nominalTypes[nextType], nominalTypes[i]); ++nextType; break; diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp index dd9c794d2650d..5fae0509d147c 100644 --- a/lib/Sema/CalleeCandidateInfo.cpp +++ b/lib/Sema/CalleeCandidateInfo.cpp @@ -49,8 +49,7 @@ static bool isSubstitutableFor(Type type, ArchetypeType *archetype, } for (auto proto : archetype->getConformsTo()) { - if (!dc->getParentModule()->lookupConformance( - type, proto)) + if (dc->getParentModule()->lookupConformance(type, proto).isInvalid()) return false; } diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 8e574d8a5d83c..1eccad9bfe96e 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -427,8 +427,8 @@ configureGenericDesignatedInitOverride(ASTContext &ctx, }; auto lookupConformanceFn = - [&](CanType depTy, Type substTy, ProtocolDecl *proto) - -> Optional { + [&](CanType depTy, Type substTy, + ProtocolDecl *proto) -> ProtocolConformanceRef { if (auto conf = subMap.lookupConformance(depTy, proto)) return conf; @@ -1075,20 +1075,22 @@ void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target, return false; auto targetType = target->getDeclaredInterfaceType(); - if (auto ref = conformsToProtocol( - targetType, protocol, target, - ConformanceCheckFlags::SkipConditionalRequirements)) { - if (auto *conformance = dyn_cast( - ref->getConcrete()->getRootConformance())) { - if (conformance->getState() == ProtocolConformanceState::Incomplete) { - checkConformance(conformance); - } - } + auto ref = + conformsToProtocol(targetType, protocol, target, + ConformanceCheckFlags::SkipConditionalRequirements); - return true; + if (ref.isInvalid()) { + return false; } - return false; + if (auto *conformance = dyn_cast( + ref.getConcrete()->getRootConformance())) { + if (conformance->getState() == ProtocolConformanceState::Incomplete) { + checkConformance(conformance); + } + } + + return true; }; if (member.isSimpleName() && !baseName.isSpecial()) { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index b50db6a2e92a1..d365518dfd5f5 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -2292,7 +2292,7 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) { return DependentMemberType::get(lookupBaseType, assocType); auto subs = SubstitutionMap::getProtocolSubstitutions( - proto, lookupBaseType, *conformance); + proto, lookupBaseType, conformance); auto result = assocType->getDeclaredInterfaceType().subst(subs); if (!result->hasError()) return result; @@ -3079,8 +3079,8 @@ bool constraints::hasAppliedSelf(ConstraintSystem &cs, bool constraints::conformsToKnownProtocol(ConstraintSystem &cs, Type type, KnownProtocolKind protocol) { if (auto *proto = cs.TC.getProtocol(SourceLoc(), protocol)) - return bool(TypeChecker::conformsToProtocol( - type, proto, cs.DC, ConformanceCheckFlags::InExpression)); + return (bool)TypeChecker::conformsToProtocol( + type, proto, cs.DC, ConformanceCheckFlags::InExpression); return false; } @@ -3097,10 +3097,10 @@ Type constraints::isRawRepresentable(ConstraintSystem &cs, Type type) { auto conformance = TypeChecker::conformsToProtocol( type, rawReprType, DC, ConformanceCheckFlags::InExpression); - if (!conformance) + if (conformance.isInvalid()) return Type(); - return conformance->getTypeWitnessByName(type, TC.Context.Id_RawValue); + return conformance.getTypeWitnessByName(type, TC.Context.Id_RawValue); } Type constraints::isRawRepresentable( diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index f7a839af082fa..35d72af5bbcc1 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -86,9 +86,8 @@ static CodableConformanceType typeConformsToCodable(DeclContext *context, return typeConformsToCodable(context, target->getOptionalObjectType(), false, proto); - return (TypeChecker::conformsToProtocol(target, proto, context, None) - ? Conforms - : DoesNotConform); + auto conf = TypeChecker::conformsToProtocol(target, proto, context, None); + return conf.isInvalid() ? DoesNotConform : Conforms; } /// Returns whether the given variable conforms to the given {En,De}codable @@ -271,8 +270,7 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) { // Ensure that the type we found conforms to the CodingKey protocol. auto *codingKeyProto = C.getProtocol(KnownProtocolKind::CodingKey); if (!TypeChecker::conformsToProtocol(codingKeysType, codingKeyProto, - derived.getConformanceContext(), - None)) { + derived.getConformanceContext(), None)) { // If CodingKeys is a typealias which doesn't point to a valid nominal type, // codingKeysTypeDecl will be nullptr here. In that case, we need to warn on // the location of the usage, since there isn't an underlying type to diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 07e85ebdc442e..500a37c58f8a9 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -53,8 +53,9 @@ associatedValuesNotConformingToProtocol(DeclContext *DC, EnumDecl *theEnum, for (auto param : *PL) { auto type = param->getInterfaceType(); - if (!TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), - protocol, DC, None)) { + if (TypeChecker::conformsToProtocol(DC->mapTypeIntoContext(type), + protocol, DC, None) + .isInvalid()) { nonconformingAssociatedValues.push_back(param); } } @@ -1205,17 +1206,17 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) { // We can't form a Hashable conformance if Int isn't Hashable or // ExpressibleByIntegerLiteral. - if (!TypeChecker::conformsToProtocol(intType, - C.getProtocol(KnownProtocolKind::Hashable), - parentDC, None)) { + if (TypeChecker::conformsToProtocol( + intType, C.getProtocol(KnownProtocolKind::Hashable), parentDC, None) + .isInvalid()) { derived.ConformanceDecl->diagnose(diag::broken_int_hashable_conformance); return nullptr; } ProtocolDecl *intLiteralProto = C.getProtocol(KnownProtocolKind::ExpressibleByIntegerLiteral); - if (!TypeChecker::conformsToProtocol(intType, intLiteralProto, - parentDC, None)) { + if (TypeChecker::conformsToProtocol(intType, intLiteralProto, parentDC, None) + .isInvalid()) { derived.ConformanceDecl->diagnose( diag::broken_int_integer_literal_convertible_conformance); return nullptr; diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index 2b71b8f2cb762..760c697e01da4 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -404,8 +404,8 @@ deriveRawRepresentable_init(DerivedConformance &derived) { auto equatableProto = tc.getProtocol(enumDecl->getLoc(), KnownProtocolKind::Equatable); assert(equatableProto); - assert(TypeChecker::conformsToProtocol(rawType, equatableProto, - enumDecl, None)); + assert( + TypeChecker::conformsToProtocol(rawType, equatableProto, enumDecl, None)); (void)equatableProto; (void)rawType; @@ -466,8 +466,8 @@ static bool canSynthesizeRawRepresentable(DerivedConformance &derived) { if (!equatableProto) return false; - if (!TypeChecker::conformsToProtocol(rawType, equatableProto, - enumDecl, None)) + if (TypeChecker::conformsToProtocol(rawType, equatableProto, enumDecl, None) + .isInvalid()) return false; // There must be enum elements. diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index 31e4b0de98ead..23c7a79916185 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -167,10 +167,11 @@ ValueDecl *DerivedConformance::getDerivableRequirement(NominalTypeDecl *nominal, auto proto = ctx.getProtocol(kind); if (!proto) return nullptr; - if (auto conformance = TypeChecker::conformsToProtocol( - nominal->getDeclaredInterfaceType(), proto, nominal, - ConformanceCheckFlags::SkipConditionalRequirements)) { - auto DC = conformance->getConcrete()->getDeclContext(); + auto conformance = TypeChecker::conformsToProtocol( + nominal->getDeclaredInterfaceType(), proto, nominal, + ConformanceCheckFlags::SkipConditionalRequirements); + if (conformance) { + auto DC = conformance.getConcrete()->getDeclContext(); // Check whether this nominal type derives conformances to the protocol. if (!DerivedConformance::derivesProtocolConformance(DC, nominal, proto)) return nullptr; diff --git a/lib/Sema/LookupVisibleDecls.cpp b/lib/Sema/LookupVisibleDecls.cpp index a56570fe61631..bc79d3ea5acdf 100644 --- a/lib/Sema/LookupVisibleDecls.cpp +++ b/lib/Sema/LookupVisibleDecls.cpp @@ -697,8 +697,10 @@ static Type getBaseTypeForMember(ModuleDecl *M, ValueDecl *OtherVD, Type BaseTy) if (auto *Proto = OtherVD->getDeclContext()->getSelfProtocolDecl()) { if (BaseTy->getClassOrBoundGenericClass()) { if (auto Conformance = M->lookupConformance(BaseTy, Proto)) { - auto *Superclass = Conformance->getConcrete()->getRootConformance() - ->getType()->getClassOrBoundGenericClass(); + auto *Superclass = Conformance.getConcrete() + ->getRootConformance() + ->getType() + ->getClassOrBoundGenericClass(); return BaseTy->getSuperclassForDecl(Superclass); } } diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 31daacaee3e74..bf9ea01fcae79 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1082,8 +1082,8 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, if (!hasKeywordArguments) { auto arrayLitProto = ctx.getProtocol(KnownProtocolKind::ExpressibleByArrayLiteral); - return TypeChecker::conformsToProtocol(argType, arrayLitProto, DC, - ConformanceCheckOptions()).hasValue(); + return (bool)TypeChecker::conformsToProtocol(argType, arrayLitProto, DC, + ConformanceCheckOptions()); } // If keyword arguments, check that argument type conforms to // `ExpressibleByDictionaryLiteral` and that the `Key` associated type @@ -1094,10 +1094,11 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, ctx.getProtocol(KnownProtocolKind::ExpressibleByDictionaryLiteral); auto dictConf = TypeChecker::conformsToProtocol(argType, dictLitProto, DC, ConformanceCheckOptions()); - if (!dictConf) return false; - auto keyType = dictConf.getValue().getTypeWitnessByName(argType, ctx.Id_Key); - return TypeChecker::conformsToProtocol(keyType, stringLitProtocol, DC, - ConformanceCheckOptions()).hasValue(); + if (dictConf.isInvalid()) + return false; + auto keyType = dictConf.getTypeWitnessByName(argType, ctx.Id_Key); + return (bool)TypeChecker::conformsToProtocol(keyType, stringLitProtocol, DC, + ConformanceCheckOptions()); } /// Returns true if the given nominal type has a valid implementation of a @@ -1191,8 +1192,8 @@ bool swift::isValidStringDynamicMemberLookup(SubscriptDecl *decl, ctx.getProtocol(KnownProtocolKind::ExpressibleByStringLiteral); // If this is `subscript(dynamicMember: String*)` - return bool(TypeChecker::conformsToProtocol(paramType, stringLitProto, DC, - ConformanceCheckOptions())); + return (bool)TypeChecker::conformsToProtocol(paramType, stringLitProto, DC, + ConformanceCheckOptions()); } bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl, @@ -1558,7 +1559,7 @@ void AttributeChecker::visitNSCopyingAttr(NSCopyingAttr *attr) { } if (VD->hasInterfaceType()) { - if (!TC.checkConformanceToNSCopying(VD)) { + if (TC.checkConformanceToNSCopying(VD).isInvalid()) { attr->setInvalid(); return; } @@ -1625,8 +1626,7 @@ void AttributeChecker::checkApplicationMainAttribute(DeclAttribute *attr, if (!ApplicationDelegateProto || !TypeChecker::conformsToProtocol(CD->getDeclaredType(), - ApplicationDelegateProto, - CD, None)) { + ApplicationDelegateProto, CD, None)) { TC.diagnose(attr->getLocation(), diag::attr_ApplicationMain_not_ApplicationDelegate, applicationMainKind); diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 891a92380d104..c5f009164f556 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -2644,11 +2644,10 @@ static bool isIntegerOrFloatingPointType(Type ty, DeclContext *DC, Context.getProtocol(KnownProtocolKind::ExpressibleByFloatLiteral); if (!integerType || !floatingType) return false; - return - TypeChecker::conformsToProtocol(ty, integerType, DC, - ConformanceCheckFlags::InExpression) || - TypeChecker::conformsToProtocol(ty, floatingType, DC, - ConformanceCheckFlags::InExpression); + return TypeChecker::conformsToProtocol(ty, integerType, DC, + ConformanceCheckFlags::InExpression) || + TypeChecker::conformsToProtocol(ty, floatingType, DC, + ConformanceCheckFlags::InExpression); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 652184a139c8c..0a3ebd7782856 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -734,7 +734,8 @@ resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *DC) { ConformanceCheckFlags::InExpression | ConformanceCheckFlags::SkipConditionalRequirements); - if (!conformance || conformance->getConditionalRequirements().empty()) { + if (conformance.isInvalid() || + conformance.getConditionalRequirements().empty()) { AllConditionalConformances = false; } } @@ -4416,8 +4417,9 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, // kind. if (Context.LangOpts.EnableObjCInterop) { if (auto errorTypeProto = Context.getProtocol(KnownProtocolKind::Error)) { - if (conformsToProtocol(toType, errorTypeProto, dc, - ConformanceCheckFlags::InExpression)) { + if (!conformsToProtocol(toType, errorTypeProto, dc, + ConformanceCheckFlags::InExpression) + .isInvalid()) { auto nsError = Context.getNSErrorDecl(); if (nsError) { Type NSErrorTy = nsError->getDeclaredInterfaceType(); diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 4e2157e8c62e9..0626ebafb67a7 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1543,10 +1543,10 @@ computeAutomaticEnumValueKind(EnumDecl *ED) { // primitive literal protocols. auto conformsToProtocol = [&](KnownProtocolKind protoKind) { ProtocolDecl *proto = ED->getASTContext().getProtocol(protoKind); - return TypeChecker::conformsToProtocol(rawTy, proto, - ED->getDeclContext(), None); + return TypeChecker::conformsToProtocol(rawTy, proto, ED->getDeclContext(), + None); }; - + static auto otherLiteralProtocolKinds = { KnownProtocolKind::ExpressibleByFloatLiteral, KnownProtocolKind::ExpressibleByUnicodeScalarLiteral, @@ -4408,15 +4408,18 @@ EmittedMembersRequest::evaluate(Evaluator &evaluator, TypeChecker::addImplicitConstructors(CD); auto forceConformance = [&](ProtocolDecl *protocol) { - if (auto ref = TypeChecker::conformsToProtocol( - CD->getDeclaredInterfaceType(), protocol, CD, - ConformanceCheckFlags::SkipConditionalRequirements, - SourceLoc())) { - auto conformance = ref->getConcrete(); - if (conformance->getDeclContext() == CD && - conformance->getState() == ProtocolConformanceState::Incomplete) { - TC.checkConformance(conformance->getRootNormalConformance()); - } + auto ref = TypeChecker::conformsToProtocol( + CD->getDeclaredInterfaceType(), protocol, CD, + ConformanceCheckFlags::SkipConditionalRequirements, SourceLoc()); + + if (ref.isInvalid()) { + return; + } + + auto conformance = ref.getConcrete(); + if (conformance->getDeclContext() == CD && + conformance->getState() == ProtocolConformanceState::Incomplete) { + TC.checkConformance(conformance->getRootNormalConformance()); } }; @@ -4589,12 +4592,12 @@ static Optional buildDefaultInitializerString(TypeChecker &tc, auto type = pattern->getType(); // For literal-convertible types, form the corresponding literal. -#define CHECK_LITERAL_PROTOCOL(Kind, String) \ - if (auto proto = tc.getProtocol(SourceLoc(), KnownProtocolKind::Kind)) { \ - if (tc.conformsToProtocol(type, proto, dc, \ - ConformanceCheckFlags::InExpression)) \ - return std::string(String); \ - } +#define CHECK_LITERAL_PROTOCOL(Kind, String) \ + if (auto proto = tc.getProtocol(SourceLoc(), KnownProtocolKind::Kind)) { \ + if (tc.conformsToProtocol(type, proto, dc, \ + ConformanceCheckFlags::InExpression)) \ + return std::string(String); \ + } CHECK_LITERAL_PROTOCOL(ExpressibleByArrayLiteral, "[]") CHECK_LITERAL_PROTOCOL(ExpressibleByDictionaryLiteral, "[:]") CHECK_LITERAL_PROTOCOL(ExpressibleByUnicodeScalarLiteral, "\"\"") @@ -4675,10 +4678,10 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc, ASTContext &C = tc.Context; auto *decodableProto = C.getProtocol(KnownProtocolKind::Decodable); auto superclassType = superclassDecl->getDeclaredInterfaceType(); - if (auto ref = TypeChecker::conformsToProtocol(superclassType, decodableProto, - superclassDecl, - ConformanceCheckOptions(), - SourceLoc())) { + auto ref = TypeChecker::conformsToProtocol( + superclassType, decodableProto, superclassDecl, + ConformanceCheckOptions(), SourceLoc()); + if (ref) { // super conforms to Decodable, so we've failed to inherit init(from:). // Let's suggest overriding it here. // @@ -4702,10 +4705,10 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc, // likely that the user forgot to override its encode(to:). In this case, // we can produce a slightly different diagnostic to suggest doing so. auto *encodableProto = C.getProtocol(KnownProtocolKind::Encodable); - if ((ref = tc.conformsToProtocol(superclassType, encodableProto, - superclassDecl, - ConformanceCheckOptions(), - SourceLoc()))) { + auto ref = + tc.conformsToProtocol(superclassType, encodableProto, superclassDecl, + ConformanceCheckOptions(), SourceLoc()); + if (ref) { // We only want to produce this version of the diagnostic if the // subclass doesn't directly implement encode(to:). // The direct lookup here won't see an encode(to:) if it is inherited diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp index cfd442c89044c..7ddcfadedfbb0 100644 --- a/lib/Sema/TypeCheckGeneric.cpp +++ b/lib/Sema/TypeCheckGeneric.cpp @@ -803,12 +803,10 @@ RequirementCheckResult TypeChecker::checkGenericArguments( // FIXME: Poor location information. How much better can we do here? // FIXME: This call should support listener to be able to properly // diagnose problems with conformances. - auto result = - conformsToProtocol(firstType, proto->getDecl(), dc, - conformanceOptions, loc); + auto conformance = conformsToProtocol(firstType, proto->getDecl(), dc, + conformanceOptions, loc); - if (result) { - auto conformance = *result; + if (conformance) { // Report the conformance. if (listener && valid && current.Parents.empty()) { listener->satisfiedConformance(rawFirstType, firstType, diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 87aef4be6e06c..001b8eb8f66b8 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -200,7 +200,7 @@ namespace { auto conformance = TypeChecker::conformsToProtocol(conformingType, foundProto, DC, conformanceOptions); - if (!conformance) { + if (conformance.isInvalid()) { // If there's no conformance, we have an existential // and we found a member from one of the protocols, and // not a class constraint if any. @@ -210,7 +210,7 @@ namespace { return; } - if (conformance->isAbstract()) { + if (conformance.isAbstract()) { assert(foundInType->is() || foundInType->isExistentialType()); addResult(found); @@ -219,7 +219,7 @@ namespace { // Dig out the witness. ValueDecl *witness = nullptr; - auto concrete = conformance->getConcrete(); + auto concrete = conformance.getConcrete(); if (auto assocType = dyn_cast(found)) { witness = concrete->getTypeWitnessAndDecl(assocType) .second; @@ -512,7 +512,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc, } // Use the type witness. - auto concrete = conformance->getConcrete(); + auto concrete = conformance.getConcrete(); // This is the only case where NormalProtocolConformance:: // getTypeWitnessAndDecl() returns a null type. diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index 7f2c844ba5e87..17da1d97f949b 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1691,7 +1691,8 @@ checkIndividualConformance(NormalProtocolConformance *conformance, T, InheritedProto, DC, ConformanceCheckFlags::SkipConditionalRequirements, ComplainLoc); - if (!InheritedConformance || !InheritedConformance->isConcrete()) { + if (InheritedConformance.isInvalid() || + !InheritedConformance.isConcrete()) { // Recursive call already diagnosed this problem, but tack on a note // to establish the relationship. if (ComplainLoc.isValid()) { @@ -2555,12 +2556,12 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType, auto overriddenConformance = DC->getParentModule()->lookupConformance(Adoptee, overridden->getProtocol()); - if (!overriddenConformance || - !overriddenConformance->isConcrete()) + if (overriddenConformance.isInvalid() || + !overriddenConformance.isConcrete()) continue; auto overriddenRootConformance = - overriddenConformance->getConcrete()->getRootNormalConformance(); + overriddenConformance.getConcrete()->getRootNormalConformance(); ConformanceChecker(TC, overriddenRootConformance, GlobalMissingWitnesses) .recordTypeWitness(overridden, type, typeDecl); } @@ -3040,11 +3041,10 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { // Otherwise, go satisfy the derivable requirement, which can introduce // a member that could in turn satisfy *this* requirement. auto derivableProto = cast(derivable->getDeclContext()); - if (auto conformance = - TypeChecker::conformsToProtocol(Adoptee, derivableProto, - DC, None)) { - if (conformance->isConcrete()) - (void)conformance->getConcrete()->getWitnessDecl(derivable); + auto conformance = + TypeChecker::conformsToProtocol(Adoptee, derivableProto, DC, None); + if (conformance.isConcrete()) { + (void)conformance.getConcrete()->getWitnessDecl(derivable); } } } @@ -3427,9 +3427,10 @@ CheckTypeWitnessResult swift::checkTypeWitness(TypeChecker &tc, DeclContext *dc, // Check protocol conformances. for (auto reqProto : genericSig->getConformsTo(depTy)) { - if (!TypeChecker::conformsToProtocol( - contextType, reqProto, dc, - ConformanceCheckFlags::SkipConditionalRequirements)) + if (TypeChecker::conformsToProtocol( + contextType, reqProto, dc, + ConformanceCheckFlags::SkipConditionalRequirements) + .isInvalid()) return CheckTypeWitnessResult(reqProto->getDeclaredType()); // FIXME: Why is conformsToProtocol() not enough? The stdlib doesn't @@ -4022,8 +4023,9 @@ static void diagnoseConformanceFailure(Type T, if (!equatableProto) return; - if (!TypeChecker::conformsToProtocol(rawType, equatableProto, enumDecl, - None)) { + if (TypeChecker::conformsToProtocol(rawType, equatableProto, enumDecl, + None) + .isInvalid()) { SourceLoc loc = enumDecl->getInherited()[0].getSourceRange().Start; diags.diagnose(loc, diag::enum_raw_type_not_equatable, rawType); return; @@ -4076,10 +4078,9 @@ void ConformanceChecker::emitDelayedDiags() { } } -Optional TypeChecker::containsProtocol( - Type T, ProtocolDecl *Proto, - DeclContext *DC, - ConformanceCheckOptions options) { +ProtocolConformanceRef +TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, + ConformanceCheckOptions options) { // Existential types don't need to conform, i.e., they only need to // contain the protocol. if (T->isExistentialType()) { @@ -4088,7 +4089,9 @@ Optional TypeChecker::containsProtocol( // First, if we have a superclass constraint, the class may conform // concretely. if (auto superclass = layout.getSuperclass()) { - if (auto result = conformsToProtocol(superclass, Proto, DC, options)) { + auto result = + TypeChecker::conformsToProtocol(superclass, Proto, DC, options); + if (result) { return result; } } @@ -4107,18 +4110,17 @@ Optional TypeChecker::containsProtocol( return ProtocolConformanceRef(Proto); } - return None; + return ProtocolConformanceRef::forInvalid(); } // For non-existential types, this is equivalent to checking conformance. - return conformsToProtocol(T, Proto, DC, options); + return TypeChecker::conformsToProtocol(T, Proto, DC, options); } -Optional TypeChecker::conformsToProtocol( - Type T, ProtocolDecl *Proto, - DeclContext *DC, - ConformanceCheckOptions options, - SourceLoc ComplainLoc) { +ProtocolConformanceRef +TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, + ConformanceCheckOptions options, + SourceLoc ComplainLoc) { bool InExpression = options.contains(ConformanceCheckFlags::InExpression); auto recordDependency = [=](ProtocolConformance *conformance = nullptr) { @@ -4130,18 +4132,18 @@ Optional TypeChecker::conformsToProtocol( // Look up conformance in the module. ModuleDecl *M = DC->getParentModule(); auto lookupResult = M->lookupConformance(T, Proto); - if (!lookupResult) { + if (lookupResult.isInvalid()) { if (ComplainLoc.isValid()) diagnoseConformanceFailure(T, Proto, DC, ComplainLoc); else recordDependency(); - return None; + return ProtocolConformanceRef::forInvalid(); } // Store the conformance and record the dependency. - if (lookupResult->isConcrete()) { - recordDependency(lookupResult->getConcrete()); + if (lookupResult.isConcrete()) { + recordDependency(lookupResult.getConcrete()); } else { recordDependency(); } @@ -4149,7 +4151,7 @@ Optional TypeChecker::conformsToProtocol( if (options.contains(ConformanceCheckFlags::SkipConditionalRequirements)) return lookupResult; - auto condReqs = lookupResult->getConditionalRequirementsIfAvailable(); + auto condReqs = lookupResult.getConditionalRequirementsIfAvailable(); assert(condReqs && "unhandled recursion: missing conditional requirements when they're " "required"); @@ -4158,7 +4160,7 @@ Optional TypeChecker::conformsToProtocol( // we need to check, do so now. if (!condReqs->empty()) { // Figure out the location of the conditional conformance. - auto conformanceDC = lookupResult->getConcrete()->getDeclContext(); + auto conformanceDC = lookupResult.getConcrete()->getDeclContext(); SourceLoc noteLoc; if (auto ext = dyn_cast(conformanceDC)) noteLoc = ext->getLoc(); @@ -4167,8 +4169,7 @@ Optional TypeChecker::conformsToProtocol( auto conditionalCheckResult = checkGenericArguments( DC, ComplainLoc, noteLoc, T, - {lookupResult->getRequirement()->getSelfInterfaceType()}, - *condReqs, + {lookupResult.getRequirement()->getSelfInterfaceType()}, *condReqs, [](SubstitutableType *dependentType) { return Type(dependentType); }, LookUpConformance(DC), options); switch (conditionalCheckResult) { @@ -4177,7 +4178,7 @@ Optional TypeChecker::conformsToProtocol( case RequirementCheckResult::Failure: case RequirementCheckResult::SubstitutionFailure: - return None; + return ProtocolConformanceRef::forInvalid(); } } @@ -4198,7 +4199,7 @@ Optional TypeChecker::conformsToProtocol( // is only valid during type checking, will never be invoked. // // - mapTypeIntoContext will be a nop. -Optional +ProtocolConformanceRef ModuleDecl::conformsToProtocol(Type sourceTy, ProtocolDecl *targetProtocol) { auto flags = ConformanceCheckFlags::SuppressDependencyTracking; @@ -4206,11 +4207,9 @@ ModuleDecl::conformsToProtocol(Type sourceTy, ProtocolDecl *targetProtocol) { return TypeChecker::conformsToProtocol(sourceTy, targetProtocol, this, flags); } -Optional -TypeChecker::LookUpConformance::operator()( - CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const { +ProtocolConformanceRef TypeChecker::LookUpConformance:: +operator()(CanType dependentType, Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const { if (conformingReplacementType->isTypeParameter()) return ProtocolConformanceRef(conformedProtocol); @@ -5476,7 +5475,7 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) { req.getSecondType()->castTo()->getDecl(); auto conformance = conformsToProtocol(defaultAssocTypeInContext, requirementProto, proto, None); - if (!conformance) { + if (conformance.isInvalid()) { // Diagnose the lack of a conformance. This is potentially an ABI // incompatibility. diagnose(proto, diag::assoc_type_default_conformance_failed, @@ -5492,6 +5491,6 @@ void TypeChecker::inferDefaultWitnesses(ProtocolDecl *proto) { // Record the default associated conformance. proto->setDefaultAssociatedConformanceWitness( - req.getFirstType()->getCanonicalType(), requirementProto, *conformance); + req.getFirstType()->getCanonicalType(), requirementProto, conformance); } } diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 27143998d343d..002a66b138f68 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -970,9 +970,9 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) { = TypeChecker::conformsToProtocol( baseTy, assocType->getProtocol(), dc, ConformanceCheckFlags::SkipConditionalRequirements); - if (!localConformance || localConformance->isAbstract() || - (localConformance->getConcrete()->getRootConformance() - != conformance)) { + if (localConformance.isInvalid() || localConformance.isAbstract() || + (localConformance.getConcrete()->getRootConformance() != + conformance)) { return nullptr; } diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 786faa9514999..91b89cdc619c3 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -767,17 +767,17 @@ class StmtChecker : public StmtVisitor { TypeChecker::conformsToProtocol(sequenceType, sequenceProto, DC, ConformanceCheckFlags::InExpression, sequence->getLoc()); - if (!conformance) + if (conformance.isInvalid()) return nullptr; S->setSequenceConformance(conformance); - iteratorTy = conformance->getTypeWitnessByName(sequenceType, - TC.Context.Id_Iterator); + iteratorTy = conformance.getTypeWitnessByName(sequenceType, + TC.Context.Id_Iterator); if (iteratorTy->hasError()) return nullptr; - auto witness = conformance->getWitnessByName( - sequenceType, TC.Context.Id_makeIterator); + auto witness = conformance.getWitnessByName(sequenceType, + TC.Context.Id_makeIterator); if (!witness) return nullptr; S->setMakeIterator(witness); @@ -801,9 +801,8 @@ class StmtChecker : public StmtVisitor { // TODO: test/DebugInfo/iteration.swift requires this extra info to // be around. - auto nextResultType = - OptionalType::get(conformance->getTypeWitnessByName( - sequenceType, TC.Context.Id_Element)); + auto nextResultType = OptionalType::get(conformance.getTypeWitnessByName( + sequenceType, TC.Context.Id_Element)); PatternBindingDecl::createImplicit( TC.Context, StaticSpellingKind::None, genPat, new (TC.Context) OpaqueValueExpr(S->getInLoc(), nextResultType), DC, @@ -832,11 +831,11 @@ class StmtChecker : public StmtVisitor { auto genConformance = TypeChecker::conformsToProtocol( iteratorTy, iteratorProto, DC, ConformanceCheckFlags::InExpression, sequence->getLoc()); - if (!genConformance) + if (genConformance.isInvalid()) return nullptr; - Type elementTy = genConformance->getTypeWitnessByName(iteratorTy, - TC.Context.Id_Element); + Type elementTy = + genConformance.getTypeWitnessByName(iteratorTy, TC.Context.Id_Element); if (elementTy->hasError()) return nullptr; @@ -849,7 +848,7 @@ class StmtChecker : public StmtVisitor { S->setIteratorVarRef(varRef); auto witness = - genConformance->getWitnessByName(iteratorTy, TC.Context.Id_next); + genConformance.getWitnessByName(iteratorTy, TC.Context.Id_next); S->setIteratorNext(witness); auto nextResultType = cast(S->getIteratorNext().getDecl()) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 990c9a814ef40..412f2206a3b3a 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -878,19 +878,18 @@ createPropertyLoadOrCallSuperclassGetter(AccessorDecl *accessor, ctx); } -static Optional +static ProtocolConformanceRef checkConformanceToNSCopying(ASTContext &ctx, VarDecl *var, Type type) { auto dc = var->getDeclContext(); auto proto = ctx.getNSCopyingDecl(); if (proto) { - auto result = TypeChecker::conformsToProtocol(type, proto, dc, None); - if (result) + if (auto result = TypeChecker::conformsToProtocol(type, proto, dc, None)) return result; } ctx.Diags.diagnose(var->getLoc(), diag::nscopying_doesnt_conform); - return None; + return ProtocolConformanceRef::forInvalid(); } static std::pair getUnderlyingTypeOfVariable(VarDecl *var) { @@ -903,8 +902,7 @@ static std::pair getUnderlyingTypeOfVariable(VarDecl *var) { } } -Optional -TypeChecker::checkConformanceToNSCopying(VarDecl *var) { +ProtocolConformanceRef TypeChecker::checkConformanceToNSCopying(VarDecl *var) { Type type = getUnderlyingTypeOfVariable(var).first; return ::checkConformanceToNSCopying(Context, var, type); } @@ -930,7 +928,7 @@ static Expr *synthesizeCopyWithZoneCall(Expr *Val, VarDecl *VD, //- (id)copyWithZone:(NSZone *)zone; DeclName copyWithZoneName(Ctx, Ctx.getIdentifier("copy"), { Ctx.Id_with }); FuncDecl *copyMethod = nullptr; - for (auto member : conformance->getRequirement()->getMembers()) { + for (auto member : conformance.getRequirement()->getMembers()) { if (auto func = dyn_cast(member)) { if (func->getFullName() == copyWithZoneName) { copyMethod = func; @@ -948,9 +946,8 @@ static Expr *synthesizeCopyWithZoneCall(Expr *Val, VarDecl *VD, } SubstitutionMap subs = - SubstitutionMap::get(copyMethod->getGenericSignature(), - {underlyingType}, - ArrayRef(*conformance)); + SubstitutionMap::get(copyMethod->getGenericSignature(), {underlyingType}, + ArrayRef(conformance)); ConcreteDeclRef copyMethodRef(copyMethod, subs); auto copyMethodType = copyMethod->getInterfaceType() ->castTo() diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index c082ebc7d4372..e252fb500ecac 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -892,15 +892,15 @@ static void maybeDiagnoseBadConformanceRef(DeclContext *dc, // If we weren't given a conformance, go look it up. ProtocolConformance *conformance = nullptr; - if (protocol) - if (auto conformanceRef = TypeChecker::conformsToProtocol( - parentTy, protocol, dc, - (ConformanceCheckFlags::InExpression | - ConformanceCheckFlags::SuppressDependencyTracking | - ConformanceCheckFlags::SkipConditionalRequirements))) { - if (conformanceRef->isConcrete()) - conformance = conformanceRef->getConcrete(); - } + if (protocol) { + auto conformanceRef = TypeChecker::conformsToProtocol( + parentTy, protocol, dc, + (ConformanceCheckFlags::InExpression | + ConformanceCheckFlags::SuppressDependencyTracking | + ConformanceCheckFlags::SkipConditionalRequirements)); + if (conformanceRef.isConcrete()) + conformance = conformanceRef.getConcrete(); + } // If any errors have occurred, don't bother diagnosing this cross-file // issue. @@ -2587,13 +2587,12 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr, auto result = TypeChecker::conformsToProtocol( replacement, proto, DC, ConformanceCheckOptions()); - // TODO: getSubstitutions callback ought to return Optional. - if (!result) { + if (result.isInvalid()) { ok = false; return ProtocolConformanceRef(proto); } - - return *result; + + return result; }); if (!ok) @@ -2712,7 +2711,7 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, interfaceResults = results; interfaceErrorResult = errorResult; } - Optional witnessMethodConformance; + ProtocolConformanceRef witnessMethodConformance; if (witnessMethodProtocol) { auto resolved = resolveType(witnessMethodProtocol, options); if (resolved->hasError()) diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index d3ea8ba3a1f72..80c6e3f4e941e 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -1487,10 +1487,9 @@ class TypeChecker final : public LazyResolver { /// /// \returns the conformance, if \c T conforms to the protocol \c Proto, or /// an empty optional. - static Optional containsProtocol( - Type T, ProtocolDecl *Proto, - DeclContext *DC, - ConformanceCheckOptions options); + static ProtocolConformanceRef + containsProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, + ConformanceCheckOptions options); /// Determine whether the given type conforms to the given protocol. /// @@ -1509,12 +1508,10 @@ class TypeChecker final : public LazyResolver { /// /// \returns The protocol conformance, if \c T conforms to the /// protocol \c Proto, or \c None. - static Optional conformsToProtocol( - Type T, - ProtocolDecl *Proto, - DeclContext *DC, - ConformanceCheckOptions options, - SourceLoc ComplainLoc = SourceLoc()); + static ProtocolConformanceRef + conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, + ConformanceCheckOptions options, + SourceLoc ComplainLoc = SourceLoc()); /// Functor class suitable for use as a \c LookupConformanceFn to look up a /// conformance through a particular declaration context using the given @@ -1525,10 +1522,9 @@ class TypeChecker final : public LazyResolver { public: explicit LookUpConformance(DeclContext *dc) : dc(dc) { } - Optional - operator()(CanType dependentType, - Type conformingReplacementType, - ProtocolDecl *conformedProtocol) const; + ProtocolConformanceRef operator()(CanType dependentType, + Type conformingReplacementType, + ProtocolDecl *conformedProtocol) const; }; /// Completely check the given conformance. @@ -1539,7 +1535,7 @@ class TypeChecker final : public LazyResolver { IterableDeclContext *idc); /// Check that the type of the given property conforms to NSCopying. - Optional checkConformanceToNSCopying(VarDecl *var); + ProtocolConformanceRef checkConformanceToNSCopying(VarDecl *var); /// Derive an implicit declaration to satisfy a requirement of a derived /// protocol conformance. diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index d571f561f2d62..a8a8fcc26d1cf 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -5038,7 +5038,7 @@ class swift::TypeDeserializer { errorResult = maybeErrorResult.get(); } - Optional witnessMethodConformance; + ProtocolConformanceRef witnessMethodConformance; if (*representation == SILFunctionTypeRepresentation::WitnessMethod) { witnessMethodConformance = MF.readConformance(MF.DeclTypeCursor); } @@ -5388,9 +5388,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance, // conformance requirements are on Self. This isn't actually a /safe/ change // even in Objective-C, but we mostly just don't want to crash. - // FIXME: DenseMap requires that its value type be default-constructible, - // which ProtocolConformanceRef is not, hence the extra Optional. - llvm::SmallDenseMap, 16> + llvm::SmallDenseMap conformancesForProtocols; while (conformanceCount--) { ProtocolConformanceRef nextConformance = readConformance(DeclTypeCursor); @@ -5405,7 +5403,7 @@ void ModuleFile::finishNormalConformance(NormalProtocolConformance *conformance, req.getSecondType()->castTo()->getDecl(); auto iter = conformancesForProtocols.find(proto); if (iter != conformancesForProtocols.end()) { - reqConformances.push_back(iter->getSecond().getValue()); + reqConformances.push_back(iter->getSecond()); } else { // Put in an abstract conformance as a placeholder. This is a lie, but // there's not much better we can do. We're relying on the fact that diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index eea40363a18d5..7b3000604f138 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3981,8 +3981,8 @@ class Serializer::TypeSerializer : public TypeVisitor { fnTy->getNumYields(), fnTy->getNumResults(), S.addGenericSignatureRef(sig), variableData); - if (auto conformance = fnTy->getWitnessMethodConformanceOrNone()) - S.writeConformance(*conformance, S.DeclTypeAbbrCodes); + if (auto conformance = fnTy->getWitnessMethodConformanceOrInvalid()) + S.writeConformance(conformance, S.DeclTypeAbbrCodes); } void visitArraySliceType(const ArraySliceType *sliceTy) {