mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -313,6 +313,11 @@ public:
|
||||
/// be satisfied.
|
||||
ArrayRef<Requirement> getConditionalRequirements() const;
|
||||
|
||||
/// Substitute the conforming type and produce a ProtocolConformance that
|
||||
/// applies to the substituted type.
|
||||
ProtocolConformance *subst(Type substType,
|
||||
SubstitutionMap subMap) const;
|
||||
|
||||
/// Substitute the conforming type and produce a ProtocolConformance that
|
||||
/// applies to the substituted type.
|
||||
ProtocolConformance *subst(Type substType,
|
||||
|
||||
@@ -47,9 +47,8 @@ class ProtocolConformanceRef {
|
||||
using UnionType = llvm::PointerUnion<ProtocolDecl*, ProtocolConformance*>;
|
||||
UnionType Union;
|
||||
|
||||
explicit ProtocolConformanceRef(UnionType value) : Union(value) {
|
||||
assert(value && "cannot construct ProtocolConformanceRef with null");
|
||||
}
|
||||
explicit ProtocolConformanceRef(UnionType value) : Union(value) {}
|
||||
|
||||
public:
|
||||
/// Create an abstract protocol conformance reference.
|
||||
explicit ProtocolConformanceRef(ProtocolDecl *proto) : Union(proto) {
|
||||
@@ -63,17 +62,30 @@ public:
|
||||
"cannot construct ProtocolConformanceRef with null");
|
||||
}
|
||||
|
||||
static ProtocolConformanceRef forInvalid() {
|
||||
return ProtocolConformanceRef(UnionType((ProtocolDecl *)nullptr));
|
||||
}
|
||||
|
||||
bool isInvalid() const {
|
||||
return !Union;
|
||||
}
|
||||
|
||||
/// Create either a concrete or an abstract protocol conformance reference,
|
||||
/// depending on whether ProtocolConformance is null.
|
||||
explicit ProtocolConformanceRef(ProtocolDecl *protocol,
|
||||
ProtocolConformance *conf);
|
||||
|
||||
bool isConcrete() const { return Union.is<ProtocolConformance*>(); }
|
||||
bool isConcrete() const {
|
||||
return !isInvalid() && Union.is<ProtocolConformance*>();
|
||||
}
|
||||
ProtocolConformance *getConcrete() const {
|
||||
return Union.get<ProtocolConformance*>();
|
||||
}
|
||||
|
||||
bool isAbstract() const { return Union.is<ProtocolDecl*>(); }
|
||||
bool isAbstract() const {
|
||||
return !isInvalid() && Union.is<ProtocolDecl*>();
|
||||
}
|
||||
|
||||
ProtocolDecl *getAbstract() const {
|
||||
return Union.get<ProtocolDecl*>();
|
||||
}
|
||||
@@ -87,6 +99,10 @@ public:
|
||||
/// Return the protocol requirement.
|
||||
ProtocolDecl *getRequirement() const;
|
||||
|
||||
/// Apply a substitution to the conforming type.
|
||||
ProtocolConformanceRef subst(Type origType,
|
||||
SubstitutionMap subMap) const;
|
||||
|
||||
/// Apply a substitution to the conforming type.
|
||||
ProtocolConformanceRef subst(Type origType,
|
||||
TypeSubstitutionFn subs,
|
||||
|
||||
@@ -172,9 +172,7 @@ protected:
|
||||
|
||||
ProtocolConformanceRef remapConformance(Type type,
|
||||
ProtocolConformanceRef conf) {
|
||||
return conf.subst(type,
|
||||
QuerySubstitutionMap{SubsMap},
|
||||
LookUpConformanceInSubstitutionMap(SubsMap));
|
||||
return conf.subst(type, SubsMap);
|
||||
}
|
||||
|
||||
SubstitutionMap remapSubstitutionMap(SubstitutionMap Subs) {
|
||||
|
||||
@@ -87,7 +87,6 @@ TYPE(TUPLE)
|
||||
TRAILING_INFO(TUPLE_TYPE_ELT)
|
||||
TYPE(FUNCTION)
|
||||
TYPE(METATYPE)
|
||||
TYPE(LVALUE_unused)
|
||||
TYPE(INOUT)
|
||||
TYPE(ARCHETYPE)
|
||||
TYPE(PROTOCOL_COMPOSITION)
|
||||
@@ -144,42 +143,44 @@ PATTERN(ANY)
|
||||
PATTERN(TYPED)
|
||||
PATTERN(VAR)
|
||||
|
||||
OTHER(PARAMETERLIST, 226)
|
||||
OTHER(PARAMETERLIST_ELT, 227)
|
||||
OTHER(FOREIGN_ERROR_CONVENTION, 228)
|
||||
OTHER(DECL_CONTEXT, 229)
|
||||
OTHER(XREF_TYPE_PATH_PIECE, 230)
|
||||
OTHER(XREF_VALUE_PATH_PIECE, 231)
|
||||
OTHER(XREF_EXTENSION_PATH_PIECE, 232)
|
||||
OTHER(XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE, 233)
|
||||
OTHER(XREF_GENERIC_PARAM_PATH_PIECE, 234)
|
||||
OTHER(XREF_INITIALIZER_PATH_PIECE, 235)
|
||||
OTHER(PARAMETERLIST, 210)
|
||||
OTHER(PARAMETERLIST_ELT, 211)
|
||||
OTHER(FOREIGN_ERROR_CONVENTION, 212)
|
||||
OTHER(DECL_CONTEXT, 213)
|
||||
OTHER(XREF_TYPE_PATH_PIECE, 214)
|
||||
OTHER(XREF_VALUE_PATH_PIECE, 215)
|
||||
OTHER(XREF_EXTENSION_PATH_PIECE, 216)
|
||||
OTHER(XREF_OPERATOR_OR_ACCESSOR_PATH_PIECE, 217)
|
||||
OTHER(XREF_GENERIC_PARAM_PATH_PIECE, 218)
|
||||
OTHER(XREF_INITIALIZER_PATH_PIECE, 219)
|
||||
|
||||
OTHER(ABSTRACT_CLOSURE_EXPR_CONTEXT, 236)
|
||||
OTHER(PATTERN_BINDING_INITIALIZER_CONTEXT, 237)
|
||||
OTHER(DEFAULT_ARGUMENT_INITIALIZER_CONTEXT, 238)
|
||||
OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 239)
|
||||
OTHER(ABSTRACT_CLOSURE_EXPR_CONTEXT, 220)
|
||||
OTHER(PATTERN_BINDING_INITIALIZER_CONTEXT, 221)
|
||||
OTHER(DEFAULT_ARGUMENT_INITIALIZER_CONTEXT, 222)
|
||||
OTHER(TOP_LEVEL_CODE_DECL_CONTEXT, 223)
|
||||
|
||||
OTHER(GENERIC_PARAM_LIST, 240)
|
||||
OTHER(GENERIC_PARAM_LIST, 230)
|
||||
TRAILING_INFO(GENERIC_PARAM)
|
||||
TRAILING_INFO(GENERIC_REQUIREMENT)
|
||||
TRAILING_INFO(LAYOUT_REQUIREMENT)
|
||||
OTHER(GENERIC_SIGNATURE, 244)
|
||||
OTHER(SIL_GENERIC_ENVIRONMENT, 245)
|
||||
OTHER(SUBSTITUTION_MAP, 246)
|
||||
OTHER(GENERIC_SIGNATURE, 234)
|
||||
OTHER(SIL_GENERIC_ENVIRONMENT, 235)
|
||||
OTHER(SUBSTITUTION_MAP, 236)
|
||||
|
||||
OTHER(LOCAL_DISCRIMINATOR, 248)
|
||||
OTHER(PRIVATE_DISCRIMINATOR, 249)
|
||||
OTHER(LOCAL_DISCRIMINATOR, 237)
|
||||
OTHER(PRIVATE_DISCRIMINATOR, 238)
|
||||
|
||||
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 250)
|
||||
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 251)
|
||||
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 252)
|
||||
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 253)
|
||||
OTHER(SIL_LAYOUT, 197) // FIXME: Note out-of-order
|
||||
OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 198) // FIXME: Note out-of-order
|
||||
OTHER(PROTOCOL_CONFORMANCE_XREF, 199) // FIXME: Note out-of-order
|
||||
OTHER(MEMBERS, 254)
|
||||
OTHER(XREF, 255)
|
||||
OTHER(ABSTRACT_PROTOCOL_CONFORMANCE, 240)
|
||||
OTHER(NORMAL_PROTOCOL_CONFORMANCE, 241)
|
||||
OTHER(SPECIALIZED_PROTOCOL_CONFORMANCE, 242)
|
||||
OTHER(INHERITED_PROTOCOL_CONFORMANCE, 243)
|
||||
OTHER(INVALID_PROTOCOL_CONFORMANCE, 244)
|
||||
|
||||
OTHER(SIL_LAYOUT, 245)
|
||||
OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 246)
|
||||
OTHER(PROTOCOL_CONFORMANCE_XREF, 247)
|
||||
OTHER(MEMBERS, 248)
|
||||
OTHER(XREF, 249)
|
||||
|
||||
#undef RECORD
|
||||
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL
|
||||
|
||||
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
|
||||
/// describe what change you made. The content of this comment isn't important;
|
||||
/// it just ensures a conflict if two people change the module format.
|
||||
/// Don't worry about adhering to the 80-column limit for this line.
|
||||
const uint16_t VERSION_MINOR = 426; // SIL key path external components with local attempts
|
||||
const uint16_t VERSION_MINOR = 427; // Invalid conformances
|
||||
|
||||
using DeclIDField = BCFixed<31>;
|
||||
|
||||
@@ -1287,6 +1287,11 @@ namespace decls_block {
|
||||
DeclIDField // the protocol
|
||||
>;
|
||||
|
||||
/// A placeholder for an invalid conformance.
|
||||
using InvalidProtocolConformanceLayout = BCRecordLayout<
|
||||
INVALID_PROTOCOL_CONFORMANCE
|
||||
>;
|
||||
|
||||
using NormalProtocolConformanceLayout = BCRecordLayout<
|
||||
NORMAL_PROTOCOL_CONFORMANCE,
|
||||
DeclIDField, // the protocol
|
||||
|
||||
@@ -2853,7 +2853,9 @@ static void dumpProtocolConformanceRefRec(
|
||||
const ProtocolConformanceRef conformance, llvm::raw_ostream &out,
|
||||
unsigned indent,
|
||||
llvm::SmallPtrSetImpl<const ProtocolConformance *> &visited) {
|
||||
if (conformance.isConcrete()) {
|
||||
if (conformance.isInvalid()) {
|
||||
out.indent(indent) << "(invalid_conformance)";
|
||||
} else if (conformance.isConcrete()) {
|
||||
dumpProtocolConformanceRec(conformance.getConcrete(), out, indent, visited);
|
||||
} else {
|
||||
out.indent(indent) << "(abstract_conformance protocol="
|
||||
|
||||
@@ -74,6 +74,8 @@ ProtocolConformanceRef::ProtocolConformanceRef(ProtocolDecl *protocol,
|
||||
}
|
||||
|
||||
ProtocolDecl *ProtocolConformanceRef::getRequirement() const {
|
||||
assert(!isInvalid());
|
||||
|
||||
if (isConcrete()) {
|
||||
return getConcrete()->getProtocol();
|
||||
} else {
|
||||
@@ -81,10 +83,21 @@ ProtocolDecl *ProtocolConformanceRef::getRequirement() const {
|
||||
}
|
||||
}
|
||||
|
||||
ProtocolConformanceRef
|
||||
ProtocolConformanceRef::subst(Type origType,
|
||||
SubstitutionMap subMap) const {
|
||||
return subst(origType,
|
||||
QuerySubstitutionMap{subMap},
|
||||
LookUpConformanceInSubstitutionMap(subMap));
|
||||
}
|
||||
|
||||
ProtocolConformanceRef
|
||||
ProtocolConformanceRef::subst(Type origType,
|
||||
TypeSubstitutionFn subs,
|
||||
LookupConformanceFn conformances) const {
|
||||
if (isInvalid())
|
||||
return *this;
|
||||
|
||||
auto substType = origType.subst(subs, conformances,
|
||||
SubstFlags::UseErrorType);
|
||||
|
||||
@@ -96,8 +109,7 @@ ProtocolConformanceRef::subst(Type origType,
|
||||
// If this is a class, we need to traffic in the actual type that
|
||||
// implements the protocol, not 'Self' and not any subclasses (with their
|
||||
// inherited conformances).
|
||||
substType =
|
||||
substType->eraseDynamicSelfType()->getSuperclassForDecl(classDecl);
|
||||
substType = substType->getSuperclassForDecl(classDecl);
|
||||
}
|
||||
return ProtocolConformanceRef(
|
||||
getConcrete()->subst(substType, subs, conformances));
|
||||
@@ -130,6 +142,8 @@ ProtocolConformanceRef::getTypeWitnessByName(Type type,
|
||||
ProtocolConformanceRef conformance,
|
||||
Identifier name,
|
||||
LazyResolver *resolver) {
|
||||
assert(!conformance.isInvalid());
|
||||
|
||||
// Find the named requirement.
|
||||
AssociatedTypeDecl *assocType = nullptr;
|
||||
auto members = conformance.getRequirement()->lookupDirect(name);
|
||||
@@ -739,9 +753,7 @@ ProtocolConformanceRef::getAssociatedConformance(Type conformingType,
|
||||
SubstitutionMap::getProtocolSubstitutions(getRequirement(),
|
||||
conformingType, *this);
|
||||
auto abstractConf = ProtocolConformanceRef(protocol);
|
||||
return abstractConf.subst(assocType,
|
||||
QuerySubstitutionMap{subMap},
|
||||
LookUpConformanceInSubstitutionMap(subMap));
|
||||
return abstractConf.subst(assocType, subMap);
|
||||
}
|
||||
|
||||
ProtocolConformanceRef
|
||||
@@ -942,9 +954,7 @@ SpecializedProtocolConformance::getAssociatedConformance(Type assocType,
|
||||
? conformance.getConcrete()->getType()
|
||||
: GenericConformance->getAssociatedType(assocType, resolver));
|
||||
|
||||
return conformance.subst(origType,
|
||||
QuerySubstitutionMap{subMap},
|
||||
LookUpConformanceInSubstitutionMap(subMap));
|
||||
return conformance.subst(origType, subMap);
|
||||
}
|
||||
|
||||
ConcreteDeclRef
|
||||
@@ -1027,6 +1037,14 @@ bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
ProtocolConformance *
|
||||
ProtocolConformance::subst(Type substType,
|
||||
SubstitutionMap subMap) const {
|
||||
return subst(substType,
|
||||
QuerySubstitutionMap{subMap},
|
||||
LookUpConformanceInSubstitutionMap(subMap));
|
||||
}
|
||||
|
||||
ProtocolConformance *
|
||||
ProtocolConformance::subst(Type substType,
|
||||
TypeSubstitutionFn subs,
|
||||
@@ -1351,14 +1369,14 @@ ProtocolConformance *ProtocolConformance::getCanonicalConformance() {
|
||||
|
||||
/// Check of all types used by the conformance are canonical.
|
||||
bool ProtocolConformanceRef::isCanonical() const {
|
||||
if (isAbstract())
|
||||
if (isAbstract() || isInvalid())
|
||||
return true;
|
||||
return getConcrete()->isCanonical();
|
||||
}
|
||||
|
||||
ProtocolConformanceRef
|
||||
ProtocolConformanceRef::getCanonicalConformanceRef() const {
|
||||
if (isAbstract())
|
||||
if (isAbstract() || isInvalid())
|
||||
return *this;
|
||||
return ProtocolConformanceRef(getConcrete()->getCanonicalConformance());
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ SubstitutionMap SubstitutionMap::get(GenericSignature *genericSig,
|
||||
auto protoType = req.getSecondType()->castTo<ProtocolType>();
|
||||
auto proto = protoType->getDecl();
|
||||
auto conformance = lookupConformance(depTy, replacement, proto)
|
||||
.getValueOr(ProtocolConformanceRef(proto));
|
||||
.getValueOr(ProtocolConformanceRef::forInvalid());
|
||||
conformances.push_back(conformance);
|
||||
}
|
||||
|
||||
@@ -369,6 +369,9 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
|
||||
continue;
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -444,7 +447,7 @@ SubstitutionMap SubstitutionMap::subst(TypeSubstitutionFn subs,
|
||||
ProtocolDecl *proto) ->Optional<ProtocolConformanceRef> {
|
||||
auto conformance =
|
||||
lookupConformance(dependentType, proto)
|
||||
.getValueOr(ProtocolConformanceRef(proto));
|
||||
.getValueOr(ProtocolConformanceRef::forInvalid());
|
||||
auto substType = dependentType.subst(*this, SubstFlags::UseErrorType);
|
||||
return conformance.subst(substType, subs, conformances);
|
||||
});
|
||||
@@ -610,6 +613,9 @@ void SubstitutionMap::verify() const {
|
||||
|
||||
auto conformance = getConformances()[conformanceIndex];
|
||||
|
||||
if (conformance.isInvalid())
|
||||
continue;
|
||||
|
||||
// An existential type can have an abstract conformance to
|
||||
// AnyObject or an @objc protocol.
|
||||
if (conformance.isAbstract() &&
|
||||
|
||||
@@ -70,6 +70,9 @@ MetatypeInst *SILGenBuilder::createMetatype(SILLocation loc, SILType metatype) {
|
||||
if (!decl)
|
||||
return false;
|
||||
|
||||
if (isa<ProtocolDecl>(decl))
|
||||
return false;
|
||||
|
||||
auto *genericSig = decl->getGenericSignature();
|
||||
if (!genericSig)
|
||||
return false;
|
||||
|
||||
@@ -1998,9 +1998,14 @@ Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) {
|
||||
Type lookupBaseType = newBase->getWithoutSpecifierType();
|
||||
|
||||
if (lookupBaseType->mayHaveMembers()) {
|
||||
auto subs = lookupBaseType->getContextSubstitutionMap(
|
||||
cs.DC->getParentModule(),
|
||||
assocType->getDeclContext());
|
||||
auto *proto = assocType->getProtocol();
|
||||
auto conformance = cs.DC->getParentModule()->lookupConformance(
|
||||
lookupBaseType, proto);
|
||||
if (!conformance)
|
||||
return DependentMemberType::get(lookupBaseType, assocType);
|
||||
|
||||
auto subs = SubstitutionMap::getProtocolSubstitutions(
|
||||
proto, lookupBaseType, *conformance);
|
||||
auto result = assocType->getDeclaredInterfaceType().subst(subs);
|
||||
|
||||
if (result && !result->hasError())
|
||||
|
||||
@@ -469,6 +469,10 @@ ProtocolConformanceRef ModuleFile::readConformance(
|
||||
|
||||
unsigned kind = Cursor.readRecord(next.ID, scratch);
|
||||
switch (kind) {
|
||||
case INVALID_PROTOCOL_CONFORMANCE: {
|
||||
return ProtocolConformanceRef::forInvalid();
|
||||
}
|
||||
|
||||
case ABSTRACT_PROTOCOL_CONFORMANCE: {
|
||||
DeclID protoID;
|
||||
AbstractProtocolConformanceLayout::readRecord(scratch, protoID);
|
||||
|
||||
@@ -179,6 +179,7 @@ namespace sil_block {
|
||||
= decls_block::SPECIALIZED_PROTOCOL_CONFORMANCE,
|
||||
INHERITED_PROTOCOL_CONFORMANCE
|
||||
= decls_block::INHERITED_PROTOCOL_CONFORMANCE,
|
||||
INVALID_PROTOCOL_CONFORMANCE = decls_block::INVALID_PROTOCOL_CONFORMANCE,
|
||||
GENERIC_PARAM = decls_block::GENERIC_PARAM,
|
||||
GENERIC_REQUIREMENT = decls_block::GENERIC_REQUIREMENT,
|
||||
LAYOUT_REQUIREMENT = decls_block::LAYOUT_REQUIREMENT,
|
||||
|
||||
@@ -862,6 +862,8 @@ void Serializer::writeBlockInfoBlock() {
|
||||
|
||||
// These layouts can exist in both decl blocks and sil blocks.
|
||||
#define BLOCK_RECORD_WITH_NAMESPACE(K, X) emitRecordID(Out, X, #X, nameBuffer)
|
||||
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
|
||||
decls_block::INVALID_PROTOCOL_CONFORMANCE);
|
||||
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
|
||||
decls_block::ABSTRACT_PROTOCOL_CONFORMANCE);
|
||||
BLOCK_RECORD_WITH_NAMESPACE(sil_block,
|
||||
@@ -1640,6 +1642,12 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
|
||||
GenericEnvironment *genericEnv) {
|
||||
using namespace decls_block;
|
||||
|
||||
if (conformanceRef.isInvalid()) {
|
||||
unsigned abbrCode = abbrCodes[InvalidProtocolConformanceLayout::Code];
|
||||
InvalidProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conformanceRef.isAbstract()) {
|
||||
unsigned abbrCode = abbrCodes[AbstractProtocolConformanceLayout::Code];
|
||||
AbstractProtocolConformanceLayout::emitRecord(Out, ScratchRecord, abbrCode,
|
||||
@@ -4073,6 +4081,7 @@ void Serializer::writeAllDeclsAndTypes() {
|
||||
registerDeclTypeAbbr<NormalProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<SpecializedProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<InheritedProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<InvalidProtocolConformanceLayout>();
|
||||
registerDeclTypeAbbr<NormalProtocolConformanceIdLayout>();
|
||||
registerDeclTypeAbbr<ProtocolConformanceXrefLayout>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user