mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[GSB] Improve handling of conformances resolved by concrete types.
Centralize and simplify the handling of conformance requirements resolved by same-type-to-concrete requirements in a few ways: * Always store a ProtocolConformanceRef in via-superclass and via-concrete requirement sources, so we never lose this information. * When concretizing a nested type based on its parent, use the via-concrete conformance information rather than performing lookup again, simplifying this operation considerably and avoiding redundant lookups. * When adding a conformance requirement to a potential archetype that is equivalent to a concrete type, attempt to find and record the conformance. Fixes SR-4295 / rdar://problem/31372308.
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include "swift/AST/Decl.h"
|
#include "swift/AST/Decl.h"
|
||||||
#include "swift/AST/DiagnosticEngine.h"
|
#include "swift/AST/DiagnosticEngine.h"
|
||||||
#include "swift/AST/Identifier.h"
|
#include "swift/AST/Identifier.h"
|
||||||
|
#include "swift/AST/ProtocolConformanceRef.h"
|
||||||
#include "swift/AST/Types.h"
|
#include "swift/AST/Types.h"
|
||||||
#include "swift/AST/TypeLoc.h"
|
#include "swift/AST/TypeLoc.h"
|
||||||
#include "swift/AST/TypeRepr.h"
|
#include "swift/AST/TypeRepr.h"
|
||||||
@@ -286,6 +287,15 @@ private:
|
|||||||
FloatingRequirementSource source,
|
FloatingRequirementSource source,
|
||||||
UnresolvedHandlingKind unresolvedHandling);
|
UnresolvedHandlingKind unresolvedHandling);
|
||||||
|
|
||||||
|
/// Resolve the conformance of the given potential archetype to
|
||||||
|
/// the given protocol when the potential archetype is known to be equivalent
|
||||||
|
/// to a concrete type.
|
||||||
|
///
|
||||||
|
/// \returns the requirement source for the resolved conformance, or nullptr
|
||||||
|
/// if the conformance could not be resolved.
|
||||||
|
const RequirementSource *resolveConcreteConformance(PotentialArchetype *pa,
|
||||||
|
ProtocolDecl *proto);
|
||||||
|
|
||||||
/// Retrieve the constraint source conformance for the superclass constraint
|
/// Retrieve the constraint source conformance for the superclass constraint
|
||||||
/// of the given potential archetype (if present) to the given protocol.
|
/// of the given potential archetype (if present) to the given protocol.
|
||||||
///
|
///
|
||||||
@@ -293,9 +303,8 @@ private:
|
|||||||
/// queried.
|
/// queried.
|
||||||
///
|
///
|
||||||
/// \param proto The protocol to which we are establishing conformance.
|
/// \param proto The protocol to which we are establishing conformance.
|
||||||
const RequirementSource *resolveSuperConformance(
|
const RequirementSource *resolveSuperConformance(PotentialArchetype *pa,
|
||||||
GenericSignatureBuilder::PotentialArchetype *pa,
|
ProtocolDecl *proto);
|
||||||
ProtocolDecl *proto);
|
|
||||||
|
|
||||||
/// \brief Add a new conformance requirement specifying that the given
|
/// \brief Add a new conformance requirement specifying that the given
|
||||||
/// potential archetype conforms to the given protocol.
|
/// potential archetype conforms to the given protocol.
|
||||||
@@ -775,7 +784,7 @@ public:
|
|||||||
|
|
||||||
/// A requirement that was resolved via a superclass requirement.
|
/// A requirement that was resolved via a superclass requirement.
|
||||||
///
|
///
|
||||||
/// This stores the \c ProtocolConformance* used to resolve the
|
/// This stores the \c ProtocolConformanceRef used to resolve the
|
||||||
/// requirement.
|
/// requirement.
|
||||||
Superclass,
|
Superclass,
|
||||||
|
|
||||||
@@ -826,7 +835,7 @@ private:
|
|||||||
TypeBase *type;
|
TypeBase *type;
|
||||||
|
|
||||||
/// A protocol conformance used to satisfy the requirement.
|
/// A protocol conformance used to satisfy the requirement.
|
||||||
ProtocolConformance *conformance;
|
void *conformance;
|
||||||
|
|
||||||
/// An associated type to which a requirement is being applied.
|
/// An associated type to which a requirement is being applied.
|
||||||
AssociatedTypeDecl *assocType;
|
AssociatedTypeDecl *assocType;
|
||||||
@@ -943,7 +952,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RequirementSource(Kind kind, const RequirementSource *parent,
|
RequirementSource(Kind kind, const RequirementSource *parent,
|
||||||
ProtocolConformance *conformance)
|
ProtocolConformanceRef conformance)
|
||||||
: kind(kind), storageKind(StorageKind::ProtocolConformance),
|
: kind(kind), storageKind(StorageKind::ProtocolConformance),
|
||||||
hasTrailingWrittenRequirementLoc(false),
|
hasTrailingWrittenRequirementLoc(false),
|
||||||
usesRequirementSignature(false), parent(parent) {
|
usesRequirementSignature(false), parent(parent) {
|
||||||
@@ -952,7 +961,7 @@ public:
|
|||||||
assert(isAcceptableStorageKind(kind, storageKind) &&
|
assert(isAcceptableStorageKind(kind, storageKind) &&
|
||||||
"RequirementSource kind/storageKind mismatch");
|
"RequirementSource kind/storageKind mismatch");
|
||||||
|
|
||||||
storage.conformance = conformance;
|
storage.conformance = conformance.getOpaqueValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequirementSource(Kind kind, const RequirementSource *parent,
|
RequirementSource(Kind kind, const RequirementSource *parent,
|
||||||
@@ -1019,13 +1028,14 @@ public:
|
|||||||
/// A requirement source that describes that a requirement that is resolved
|
/// A requirement source that describes that a requirement that is resolved
|
||||||
/// via a superclass requirement.
|
/// via a superclass requirement.
|
||||||
const RequirementSource *viaSuperclass(
|
const RequirementSource *viaSuperclass(
|
||||||
GenericSignatureBuilder &builder,
|
GenericSignatureBuilder &builder,
|
||||||
ProtocolConformance *conformance) const;
|
ProtocolConformanceRef conformance) const;
|
||||||
|
|
||||||
/// A requirement source that describes that a requirement that is resolved
|
/// A requirement source that describes that a requirement that is resolved
|
||||||
/// via a same-type-to-concrete requirement.
|
/// via a same-type-to-concrete requirement.
|
||||||
const RequirementSource *viaConcrete(GenericSignatureBuilder &builder,
|
const RequirementSource *viaConcrete(
|
||||||
ProtocolConformance *conformance) const;
|
GenericSignatureBuilder &builder,
|
||||||
|
ProtocolConformanceRef conformance) const;
|
||||||
|
|
||||||
/// A constraint source that describes that a constraint that is resolved
|
/// A constraint source that describes that a constraint that is resolved
|
||||||
/// for a nested type via a constraint on its parent.
|
/// for a nested type via a constraint on its parent.
|
||||||
@@ -1126,9 +1136,9 @@ public:
|
|||||||
ProtocolDecl *getProtocolDecl() const;
|
ProtocolDecl *getProtocolDecl() const;
|
||||||
|
|
||||||
/// Retrieve the protocol conformance for this requirement, if there is one.
|
/// Retrieve the protocol conformance for this requirement, if there is one.
|
||||||
ProtocolConformance *getProtocolConformance() const {
|
ProtocolConformanceRef getProtocolConformance() const {
|
||||||
if (storageKind != StorageKind::ProtocolConformance) return nullptr;
|
assert(storageKind == StorageKind::ProtocolConformance);
|
||||||
return storage.conformance;
|
return ProtocolConformanceRef::getFromOpaqueValue(storage.conformance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the associated type declaration for this requirement, if there
|
/// Retrieve the associated type declaration for this requirement, if there
|
||||||
|
|||||||
@@ -544,20 +544,21 @@ const RequirementSource *RequirementSource::viaProtocolRequirement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const RequirementSource *RequirementSource::viaSuperclass(
|
const RequirementSource *RequirementSource::viaSuperclass(
|
||||||
GenericSignatureBuilder &builder,
|
GenericSignatureBuilder &builder,
|
||||||
ProtocolConformance *conformance) const {
|
ProtocolConformanceRef conformance) const {
|
||||||
REQUIREMENT_SOURCE_FACTORY_BODY(
|
REQUIREMENT_SOURCE_FACTORY_BODY(
|
||||||
(nodeID, Superclass, this, conformance,
|
(nodeID, Superclass, this, conformance.getOpaqueValue(),
|
||||||
nullptr, nullptr),
|
nullptr, nullptr),
|
||||||
(Superclass, this, conformance),
|
(Superclass, this, conformance),
|
||||||
0, WrittenRequirementLoc());
|
0, WrittenRequirementLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
const RequirementSource *RequirementSource::viaConcrete(
|
const RequirementSource *RequirementSource::viaConcrete(
|
||||||
GenericSignatureBuilder &builder,
|
GenericSignatureBuilder &builder,
|
||||||
ProtocolConformance *conformance) const {
|
ProtocolConformanceRef conformance) const {
|
||||||
REQUIREMENT_SOURCE_FACTORY_BODY(
|
REQUIREMENT_SOURCE_FACTORY_BODY(
|
||||||
(nodeID, Concrete, this, conformance, nullptr, nullptr),
|
(nodeID, Concrete, this, conformance.getOpaqueValue(),
|
||||||
|
nullptr, nullptr),
|
||||||
(Concrete, this, conformance),
|
(Concrete, this, conformance),
|
||||||
0, WrittenRequirementLoc());
|
0, WrittenRequirementLoc());
|
||||||
}
|
}
|
||||||
@@ -679,10 +680,7 @@ ProtocolDecl *RequirementSource::getProtocolDecl() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
case StorageKind::ProtocolConformance:
|
case StorageKind::ProtocolConformance:
|
||||||
if (storage.conformance)
|
return getProtocolConformance().getRequirement();
|
||||||
return storage.conformance->getProtocol();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
case StorageKind::AssociatedTypeDecl:
|
case StorageKind::AssociatedTypeDecl:
|
||||||
return storage.assocType->getProtocol();
|
return storage.assocType->getProtocol();
|
||||||
@@ -873,12 +871,16 @@ void RequirementSource::print(llvm::raw_ostream &out,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StorageKind::ProtocolConformance:
|
case StorageKind::ProtocolConformance: {
|
||||||
if (storage.conformance) {
|
auto conformance = getProtocolConformance();
|
||||||
out << " (" << storage.conformance->getType()->getString() << ": "
|
if (conformance.isConcrete()) {
|
||||||
<< storage.conformance->getProtocol()->getName() << ")";
|
out << " (" << conformance.getConcrete()->getType()->getString() << ": "
|
||||||
|
<< conformance.getConcrete()->getProtocol()->getName() << ")";
|
||||||
|
} else {
|
||||||
|
out << " (abstract " << conformance.getRequirement()->getName() << ")";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case StorageKind::AssociatedTypeDecl:
|
case StorageKind::AssociatedTypeDecl:
|
||||||
out << " (" << storage.assocType->getProtocol()->getName()
|
out << " (" << storage.assocType->getProtocol()->getName()
|
||||||
@@ -1305,9 +1307,40 @@ ConstraintResult GenericSignatureBuilder::handleUnresolvedRequirement(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RequirementSource *
|
||||||
|
GenericSignatureBuilder::resolveConcreteConformance(PotentialArchetype *pa,
|
||||||
|
ProtocolDecl *proto) {
|
||||||
|
auto concrete = pa->getConcreteType();
|
||||||
|
if (!concrete) return nullptr;
|
||||||
|
|
||||||
|
// Lookup the conformance of the concrete type to this protocol.
|
||||||
|
auto conformance =
|
||||||
|
getLookupConformanceFn()(pa->getDependentType({ }, /*allowUnresolved=*/true)
|
||||||
|
->getCanonicalType(),
|
||||||
|
concrete,
|
||||||
|
proto->getDeclaredInterfaceType()
|
||||||
|
->castTo<ProtocolType>());
|
||||||
|
if (!conformance) return nullptr;
|
||||||
|
|
||||||
|
// Conformance to this protocol is redundant; update the requirement source
|
||||||
|
// appropriately.
|
||||||
|
auto paEquivClass = pa->getOrCreateEquivalenceClass();
|
||||||
|
const RequirementSource *concreteSource;
|
||||||
|
if (auto writtenSource =
|
||||||
|
paEquivClass->findAnyConcreteConstraintAsWritten(pa))
|
||||||
|
concreteSource = writtenSource->source;
|
||||||
|
else
|
||||||
|
concreteSource = paEquivClass->concreteTypeConstraints.front().source;
|
||||||
|
|
||||||
|
concreteSource = concreteSource->viaConcrete(*this, *conformance);
|
||||||
|
paEquivClass->conformsTo[proto].push_back({pa, proto, concreteSource});
|
||||||
|
++NumConformanceConstraints;
|
||||||
|
return concreteSource;
|
||||||
|
}
|
||||||
|
|
||||||
const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
|
const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
|
||||||
GenericSignatureBuilder::PotentialArchetype *pa,
|
PotentialArchetype *pa,
|
||||||
ProtocolDecl *proto) {
|
ProtocolDecl *proto) {
|
||||||
// Get the superclass constraint.
|
// Get the superclass constraint.
|
||||||
Type superclass = pa->getSuperclass();
|
Type superclass = pa->getSuperclass();
|
||||||
if (!superclass) return nullptr;
|
if (!superclass) return nullptr;
|
||||||
@@ -1332,7 +1365,7 @@ const RequirementSource *GenericSignatureBuilder::resolveSuperConformance(
|
|||||||
superclassSource = paEquivClass->superclassConstraints.front().source;
|
superclassSource = paEquivClass->superclassConstraints.front().source;
|
||||||
|
|
||||||
superclassSource =
|
superclassSource =
|
||||||
superclassSource->viaSuperclass(*this, conformance->getConcrete());
|
superclassSource->viaSuperclass(*this, *conformance);
|
||||||
paEquivClass->conformsTo[proto].push_back({pa, proto, superclassSource});
|
paEquivClass->conformsTo[proto].push_back({pa, proto, superclassSource});
|
||||||
++NumConformanceConstraints;
|
++NumConformanceConstraints;
|
||||||
return superclassSource;
|
return superclassSource;
|
||||||
@@ -1376,7 +1409,7 @@ static void maybeAddSameTypeRequirementForNestedType(
|
|||||||
if (!assocType) return;
|
if (!assocType) return;
|
||||||
|
|
||||||
// Dig out the type witness.
|
// Dig out the type witness.
|
||||||
auto superConformance = superSource->getProtocolConformance();
|
auto superConformance = superSource->getProtocolConformance().getConcrete();
|
||||||
auto concreteType =
|
auto concreteType =
|
||||||
superConformance->getTypeWitness(assocType, builder.getLazyResolver());
|
superConformance->getTypeWitness(assocType, builder.getLazyResolver());
|
||||||
if (!concreteType) return;
|
if (!concreteType) return;
|
||||||
@@ -1421,9 +1454,13 @@ bool PotentialArchetype::addConformance(ProtocolDecl *proto,
|
|||||||
++NumConformanceConstraints;
|
++NumConformanceConstraints;
|
||||||
++NumConformances;
|
++NumConformances;
|
||||||
|
|
||||||
// Determine whether there is a superclass constraint where the
|
// If there is a concrete type that resolves this conformance requirement,
|
||||||
// superclass conforms to this protocol.
|
// record the conformance.
|
||||||
(void)getBuilder()->resolveSuperConformance(this, proto);
|
if (!builder.resolveConcreteConformance(this, proto)) {
|
||||||
|
// Otherwise, determine whether there is a superclass constraint where the
|
||||||
|
// superclass conforms to this protocol.
|
||||||
|
(void)builder.resolveSuperConformance(this, proto);
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve any existing nested types that need it.
|
// Resolve any existing nested types that need it.
|
||||||
for (auto &nested : NestedTypes) {
|
for (auto &nested : NestedTypes) {
|
||||||
@@ -1664,12 +1701,11 @@ namespace {
|
|||||||
// parent PA that has a concrete type.
|
// parent PA that has a concrete type.
|
||||||
static void concretizeNestedTypeFromConcreteParent(
|
static void concretizeNestedTypeFromConcreteParent(
|
||||||
GenericSignatureBuilder::PotentialArchetype *parent,
|
GenericSignatureBuilder::PotentialArchetype *parent,
|
||||||
const RequirementSource *parentConcreteSource,
|
|
||||||
GenericSignatureBuilder::PotentialArchetype *nestedPA,
|
GenericSignatureBuilder::PotentialArchetype *nestedPA,
|
||||||
GenericSignatureBuilder &builder,
|
GenericSignatureBuilder &builder) {
|
||||||
llvm::function_ref<ProtocolConformanceRef(ProtocolDecl *)>
|
auto parentEquiv = parent->getEquivalenceClassIfPresent();
|
||||||
lookupConformance) {
|
assert(parentEquiv && "can't have a concrete type without an equiv class");
|
||||||
auto concreteParent = parent->getConcreteType();
|
auto concreteParent = parentEquiv->concreteType;
|
||||||
assert(concreteParent &&
|
assert(concreteParent &&
|
||||||
"attempting to resolve concrete nested type of non-concrete PA");
|
"attempting to resolve concrete nested type of non-concrete PA");
|
||||||
|
|
||||||
@@ -1678,11 +1714,21 @@ static void concretizeNestedTypeFromConcreteParent(
|
|||||||
auto assocType = nestedPA->getResolvedAssociatedType();
|
auto assocType = nestedPA->getResolvedAssociatedType();
|
||||||
if (!assocType) return;
|
if (!assocType) return;
|
||||||
|
|
||||||
auto source = parentConcreteSource->viaConcrete(builder, /*FIXME: */nullptr)
|
auto proto = assocType->getProtocol();
|
||||||
->viaParent(builder, assocType);
|
assert(parentEquiv->conformsTo.count(proto) > 0 &&
|
||||||
|
"No conformance requirement");
|
||||||
|
const RequirementSource *parentConcreteSource = nullptr;
|
||||||
|
for (const auto &constraint : parentEquiv->conformsTo.find(proto)->second) {
|
||||||
|
if (constraint.source->kind == RequirementSource::Concrete) {
|
||||||
|
parentConcreteSource = constraint.source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Get the conformance from the parent.
|
// Error condition: parent did not conform to this protocol, so they
|
||||||
auto conformance = lookupConformance(assocType->getProtocol());
|
if (!parentConcreteSource) return;
|
||||||
|
|
||||||
|
auto source = parentConcreteSource->viaParent(builder, assocType);
|
||||||
|
auto conformance = parentConcreteSource->getProtocolConformance();
|
||||||
|
|
||||||
Type witnessType;
|
Type witnessType;
|
||||||
if (conformance.isConcrete()) {
|
if (conformance.isConcrete()) {
|
||||||
@@ -2059,21 +2105,7 @@ PotentialArchetype *PotentialArchetype::updateNestedTypeForConformance(
|
|||||||
// FIXME: This feels like massive overkill. Why do we have to loop?
|
// FIXME: This feels like massive overkill. Why do we have to loop?
|
||||||
if (isConcreteType()) {
|
if (isConcreteType()) {
|
||||||
for (auto equivT : getRepresentative()->getEquivalenceClassMembers()) {
|
for (auto equivT : getRepresentative()->getEquivalenceClassMembers()) {
|
||||||
concretizeNestedTypeFromConcreteParent(
|
concretizeNestedTypeFromConcreteParent(equivT, resultPA, builder);
|
||||||
equivT, RequirementSource::forNestedTypeNameMatch(this),
|
|
||||||
resultPA, builder,
|
|
||||||
[&](ProtocolDecl *proto) -> ProtocolConformanceRef {
|
|
||||||
auto depTy = resultPA->getDependentType({},
|
|
||||||
/*allowUnresolved=*/true)
|
|
||||||
->getCanonicalType();
|
|
||||||
auto protocolTy =
|
|
||||||
proto->getDeclaredInterfaceType()->castTo<ProtocolType>();
|
|
||||||
auto conformance = builder.getLookupConformanceFn()(
|
|
||||||
depTy, getConcreteType(), protocolTy);
|
|
||||||
assert(conformance &&
|
|
||||||
"failed to find PA's conformance to known protocol");
|
|
||||||
return *conformance;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3379,49 +3411,26 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirementToConcrete(
|
|||||||
// Record the requirement.
|
// Record the requirement.
|
||||||
equivClass->concreteType = Concrete;
|
equivClass->concreteType = Concrete;
|
||||||
|
|
||||||
// Make sure the concrete type fulfills the requirements on the archetype.
|
// Make sure the concrete type fulfills the conformance requirements of
|
||||||
// FIXME: Move later...
|
// this equivalence class.
|
||||||
DenseMap<ProtocolDecl *, ProtocolConformanceRef> conformances;
|
|
||||||
CanType depTy = rep->getDependentType({ }, /*allowUnresolved=*/true)
|
|
||||||
->getCanonicalType();
|
|
||||||
for (auto protocol : rep->getConformsTo()) {
|
for (auto protocol : rep->getConformsTo()) {
|
||||||
auto conformance =
|
if (!resolveConcreteConformance(rep, protocol)) {
|
||||||
getLookupConformanceFn()(depTy, Concrete,
|
if (!Concrete->hasError() && Source->getLoc().isValid()) {
|
||||||
protocol->getDeclaredInterfaceType()
|
|
||||||
->castTo<ProtocolType>());
|
|
||||||
if (!conformance) {
|
|
||||||
if (!Concrete->hasError()) {
|
|
||||||
Diags.diagnose(Source->getLoc(),
|
Diags.diagnose(Source->getLoc(),
|
||||||
diag::requires_generic_param_same_type_does_not_conform,
|
diag::requires_generic_param_same_type_does_not_conform,
|
||||||
Concrete, protocol->getName());
|
Concrete, protocol->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ConstraintResult::Conflicting;
|
return ConstraintResult::Conflicting;
|
||||||
}
|
}
|
||||||
|
|
||||||
conformances.insert({protocol, *conformance});
|
|
||||||
|
|
||||||
// Abstract conformances are acceptable for existential types.
|
|
||||||
assert(conformance->isConcrete() || Concrete->isExistentialType());
|
|
||||||
|
|
||||||
// Update the requirement source now that we know it's concrete.
|
|
||||||
// FIXME: Bad concrete source info.
|
|
||||||
auto concreteSource = Source->viaConcrete(*this,
|
|
||||||
conformance->isConcrete()
|
|
||||||
? conformance->getConcrete()
|
|
||||||
: nullptr);
|
|
||||||
equivClass->conformsTo[protocol].push_back({T, protocol, concreteSource});
|
|
||||||
++NumConformanceConstraints;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eagerly resolve any existing nested types to their concrete forms (others
|
// Eagerly resolve any existing nested types to their concrete forms (others
|
||||||
// will be "concretized" as they are constructed, in getNestedType).
|
// will be "concretized" as they are constructed, in getNestedType).
|
||||||
for (auto equivT : rep->getEquivalenceClassMembers()) {
|
for (auto equivT : rep->getEquivalenceClassMembers()) {
|
||||||
for (auto nested : equivT->getNestedTypes()) {
|
for (auto nested : equivT->getNestedTypes()) {
|
||||||
concretizeNestedTypeFromConcreteParent(
|
concretizeNestedTypeFromConcreteParent(equivT, nested.second.front(),
|
||||||
equivT, Source, nested.second.front(), *this,
|
*this);
|
||||||
[&](ProtocolDecl *proto) -> ProtocolConformanceRef {
|
|
||||||
return conformances.find(proto)->second;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// RUN: not --crash %target-swift-frontend -emit-ir -primary-file %s
|
// RUN: not %target-swift-frontend -emit-ir -primary-file %s
|
||||||
|
|
||||||
// REQUIRES: asserts
|
// REQUIRES: asserts
|
||||||
|
|
||||||
@@ -6,5 +6,5 @@
|
|||||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
|
||||||
// REQUIRES: asserts
|
// REQUIRES: asserts
|
||||||
// RUN: not --crash %target-swift-frontend %s -emit-ir
|
// RUN: not %target-swift-frontend %s -emit-ir
|
||||||
protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
|
protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
|
||||||
Reference in New Issue
Block a user