Improve recursion-breaking when resolving type witnesses.

Specifically track when we're resolving type witnesses for a given
conformance, and refuse to recursively attempt to resolve those type
witnesses. The standard library patch in rdar://problem/21789238
triggers this, and isolating it in a small test case has proven
illusive.

Swift SVN r30160
This commit is contained in:
Doug Gregor
2015-07-13 20:06:57 +00:00
parent 0e35bad9dc
commit 161f309975
7 changed files with 134 additions and 84 deletions

View File

@@ -69,17 +69,16 @@ enum class ProtocolConformanceKind {
}; };
/// Describes the state of a protocol conformance, which may be complete, /// Describes the state of a protocol conformance, which may be complete,
/// incomplete, or invalid. /// incomplete, or currently being checked.
enum class ProtocolConformanceState { enum class ProtocolConformanceState {
/// The conformance has been fully checked and is complete and well-formed. /// The conformance has been fully checked.
Complete, Complete,
/// The conformance is known but is not yet complete. /// The conformance is known but is not yet complete.
Incomplete, Incomplete,
/// The conformance's type witnesses are currently being resolved.
CheckingTypeWitnesses,
/// The conformance is being checked. /// The conformance is being checked.
Checking, Checking,
/// The conformance has been found to be invalid and should not be
/// used.
Invalid
}; };
/// \brief Describes how a particular type conforms to a given protocol, /// \brief Describes how a particular type conforms to a given protocol,
@@ -119,19 +118,18 @@ public:
/// Retrieve the state of this conformance. /// Retrieve the state of this conformance.
ProtocolConformanceState getState() const; ProtocolConformanceState getState() const;
/// Determine whether this conformance is complete and well-formed. /// Determine whether this conformance is complete.
bool isComplete() const { bool isComplete() const {
return getState() == ProtocolConformanceState::Complete; return getState() == ProtocolConformanceState::Complete;
} }
/// Determine whether this conformance is invalid. /// Determine whether this conformance is invalid.
bool isInvalid() const { bool isInvalid() const;
return getState() == ProtocolConformanceState::Invalid;
}
/// Determine whether this conformance is incomplete. /// Determine whether this conformance is incomplete.
bool isIncomplete() const { bool isIncomplete() const {
return getState() == ProtocolConformanceState::Incomplete || return getState() == ProtocolConformanceState::Incomplete ||
getState() == ProtocolConformanceState::CheckingTypeWitnesses ||
getState() == ProtocolConformanceState::Checking; getState() == ProtocolConformanceState::Checking;
} }
@@ -295,7 +293,9 @@ class NormalProtocolConformance : public ProtocolConformance,
/// The declaration context containing the ExtensionDecl or /// The declaration context containing the ExtensionDecl or
/// NominalTypeDecl that declared the conformance. /// NominalTypeDecl that declared the conformance.
DeclContext *DC; ///
/// Also stores the "invalid" bit.
llvm::PointerIntPair<DeclContext *, 1, bool> DCAndInvalid;
/// \brief The mapping of individual requirements in the protocol over to /// \brief The mapping of individual requirements in the protocol over to
/// the declarations that satisfy those requirements. /// the declarations that satisfy those requirements.
@@ -319,7 +319,7 @@ class NormalProtocolConformance : public ProtocolConformance,
SourceLoc loc, DeclContext *dc, SourceLoc loc, DeclContext *dc,
ProtocolConformanceState state) ProtocolConformanceState state)
: ProtocolConformance(ProtocolConformanceKind::Normal, conformingType), : ProtocolConformance(ProtocolConformanceKind::Normal, conformingType),
ProtocolAndState(protocol, state), Loc(loc), DC(dc) ProtocolAndState(protocol, state), Loc(loc), DCAndInvalid(dc, false)
{ {
} }
@@ -332,7 +332,7 @@ public:
/// Get the declaration context that contains the conforming extension or /// Get the declaration context that contains the conforming extension or
/// nominal type declaration. /// nominal type declaration.
DeclContext *getDeclContext() const { return DC; } DeclContext *getDeclContext() const { return DCAndInvalid.getPointer(); }
/// Retrieve the state of this conformance. /// Retrieve the state of this conformance.
ProtocolConformanceState getState() const { ProtocolConformanceState getState() const {
@@ -344,6 +344,12 @@ public:
ProtocolAndState.setInt(state); ProtocolAndState.setInt(state);
} }
/// Determine whether this conformance is invalid.
bool isInvalid() const { return DCAndInvalid.getInt(); }
/// Mark this conformance as invalid.
void setInvalid() { DCAndInvalid.setInt(true); }
/// Retrieve the type witness substitution and type decl (if one exists) /// Retrieve the type witness substitution and type decl (if one exists)
/// for the given associated type. /// for the given associated type.
std::pair<const Substitution &, TypeDecl *> std::pair<const Substitution &, TypeDecl *>
@@ -628,6 +634,10 @@ public:
} }
}; };
inline bool ProtocolConformance::isInvalid() const {
return getRootNormalConformance()->isInvalid();
}
} // end namespace swift } // end namespace swift
#endif // LLVM_SWIFT_AST_PROTOCOLCONFORMANCE_H #endif // LLVM_SWIFT_AST_PROTOCOLCONFORMANCE_H

View File

@@ -731,6 +731,11 @@ ArrayRef<Substitution> BoundGenericType::getSubstitutions(
++index; ++index;
} }
// Before recording substitutions, make sure we didn't end up doing it
// recursively.
if (auto known = ctx.getSubstitutions(canon, gpContext))
return *known;
// Copy and record the substitutions. // Copy and record the substitutions.
auto permanentSubs = ctx.AllocateCopy(resultSubstitutions, auto permanentSubs = ctx.AllocateCopy(resultSubstitutions,
hasTypeVariables hasTypeVariables

View File

@@ -233,7 +233,8 @@ ConcreteDeclRef NormalProtocolConformance::getWitness(
if (known != Mapping.end()) { if (known != Mapping.end()) {
return known->second; return known->second;
} else { } else {
assert(!isComplete() && "Resolver did not resolve requirement"); assert((!isComplete() || isInvalid()) &&
"Resolver did not resolve requirement");
return ConcreteDeclRef(); return ConcreteDeclRef();
} }
} }

View File

@@ -2497,11 +2497,13 @@ static Type getMemberForBaseType(Module *module,
return Type(); return Type();
case ConformanceKind::Conforms: case ConformanceKind::Conforms:
// If we're supposed to skip this conformance's unsatisfied type // If we have an unsatisfied type witness while we're checking the
// conformances we're supposed to skip this conformance's unsatisfied type
// witnesses, and we have an unsatisfied type witness, return // witnesses, and we have an unsatisfied type witness, return
// "missing". // "missing".
if (conformance.getPointer()->getRootNormalConformance() if (conformance.getPointer() &&
== options.getSkippedConformance() && conformance.getPointer()->getRootNormalConformance()->getState()
== ProtocolConformanceState::CheckingTypeWitnesses &&
!conformance.getPointer()->hasTypeWitness(assocType, nullptr)) !conformance.getPointer()->hasTypeWitness(assocType, nullptr))
return Type(); return Type();

View File

@@ -1661,7 +1661,6 @@ struct ASTNodeBase {};
switch (conformance->getState()) { switch (conformance->getState()) {
case ProtocolConformanceState::Complete: case ProtocolConformanceState::Complete:
case ProtocolConformanceState::Invalid:
// More checking below. // More checking below.
break; break;
@@ -1669,6 +1668,7 @@ struct ASTNodeBase {};
// Ignore incomplete conformances; we didn't need them. // Ignore incomplete conformances; we didn't need them.
return; return;
case ProtocolConformanceState::CheckingTypeWitnesses:
case ProtocolConformanceState::Checking: case ProtocolConformanceState::Checking:
dumpRef(decl); dumpRef(decl);
Out << " has a protocol conformance that is still being checked " Out << " has a protocol conformance that is still being checked "

View File

@@ -2581,6 +2581,10 @@ ConformanceChecker::inferTypeWitnessesViaValueWitnesses(ValueDecl *req) {
std::remove_if(witnessResult.Inferred.begin(), std::remove_if(witnessResult.Inferred.begin(),
witnessResult.Inferred.end(), witnessResult.Inferred.end(),
[&](const std::pair<AssociatedTypeDecl *, Type> &result) { [&](const std::pair<AssociatedTypeDecl *, Type> &result) {
// Filter out errors.
if (result.second->is<ErrorType>())
return true;
// Filter out duplicates. // Filter out duplicates.
if (!known.insert({result.first, if (!known.insert({result.first,
result.second->getCanonicalType()}) result.second->getCanonicalType()})
@@ -2712,8 +2716,7 @@ static Type getWitnessTypeForMatching(TypeChecker &tc,
} }
Module *module = conformance->getDeclContext()->getParentModule(); Module *module = conformance->getDeclContext()->getParentModule();
return type.subst(module, substitutions, return type.subst(module, substitutions, SubstOptions::IgnoreMissing);
SubstOptions(SubstOptions::IgnoreMissing, conformance));
} }
/// Remove the 'self' type from the given type, if it's a method type. /// Remove the 'self' type from the given type, if it's a method type.
@@ -2888,6 +2891,13 @@ namespace {
void ConformanceChecker::resolveTypeWitnesses() { void ConformanceChecker::resolveTypeWitnesses() {
llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes; llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
// Track when we are checking type witnesses.
ProtocolConformanceState initialState = Conformance->getState();
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
defer([&] {
Conformance->setState(initialState);
});
for (auto member : Proto->getMembers()) { for (auto member : Proto->getMembers()) {
auto assocType = dyn_cast<AssociatedTypeDecl>(member); auto assocType = dyn_cast<AssociatedTypeDecl>(member);
if (!assocType) if (!assocType)
@@ -3036,27 +3046,50 @@ void ConformanceChecker::resolveTypeWitnesses() {
// Check for completeness of the solution // Check for completeness of the solution
for (auto assocType : unresolvedAssocTypes) { for (auto assocType : unresolvedAssocTypes) {
auto typeWitness = typeWitnesses.begin(assocType); // Local function to record a missing associated type.
if (typeWitness == typeWitnesses.end()) { auto recordMissing = [&] {
// We don't have a type witness for this associated type.
// If we can form a default type, do so.
if (Type defaultType = computeDefaultTypeWitness(assocType)) {
typeWitnesses.insert(assocType, {defaultType, reqDepth});
continue;
}
// If we can derive a type witness, do so.
if (Type derivedType = computeDerivedTypeWitness(assocType)) {
typeWitnesses.insert(assocType, {derivedType, reqDepth});
continue;
}
// The solution is incomplete.
if (!missingTypeWitness) if (!missingTypeWitness)
missingTypeWitness = assocType; missingTypeWitness = assocType;
return; };
auto typeWitness = typeWitnesses.begin(assocType);
if (typeWitness != typeWitnesses.end()) {
// The solution contains an error.
if (typeWitness->first->is<ErrorType>()) {
recordMissing();
return;
}
continue;
} }
// We don't have a type witness for this associated type.
// If we can form a default type, do so.
if (Type defaultType = computeDefaultTypeWitness(assocType)) {
if (defaultType->is<ErrorType>()) {
recordMissing();
return;
}
typeWitnesses.insert(assocType, {defaultType, reqDepth});
continue;
}
// If we can derive a type witness, do so.
if (Type derivedType = computeDerivedTypeWitness(assocType)) {
if (derivedType->is<ErrorType>()) {
recordMissing();
return;
}
typeWitnesses.insert(assocType, {derivedType, reqDepth});
continue;
}
// The solution is incomplete.
recordMissing();
return;
} }
// Determine whether there is already a solution with the same // Determine whether there is already a solution with the same
@@ -3212,6 +3245,9 @@ void ConformanceChecker::resolveTypeWitnesses() {
return; return;
} }
// Error cases follow.
Conformance->setInvalid();
// We're going to produce an error below. Mark each unresolved // We're going to produce an error below. Mark each unresolved
// associated type witness as erroneous. // associated type witness as erroneous.
for (auto assocType : unresolvedAssocTypes) { for (auto assocType : unresolvedAssocTypes) {
@@ -3422,7 +3458,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
if (requirement->isInvalid()) { if (requirement->isInvalid()) {
// FIXME: Note that there is no witness? // FIXME: Note that there is no witness?
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
} }
@@ -3439,7 +3475,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
for (auto assocType : getReferencedAssociatedTypes(requirement)) { for (auto assocType : getReferencedAssociatedTypes(requirement)) {
if (Conformance->getTypeWitness(assocType, nullptr).getReplacement() if (Conformance->getTypeWitness(assocType, nullptr).getReplacement()
->is<ErrorType>()) { ->is<ErrorType>()) {
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
} }
} }
@@ -3450,7 +3486,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
return; return;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3464,7 +3500,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
return; return;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3478,7 +3514,7 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
return; return;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3506,7 +3542,7 @@ void ConformanceChecker::checkConformance() {
// FIXME: Not really true. We could check witnesses that don't involve the // FIXME: Not really true. We could check witnesses that don't involve the
// failed associated types. // failed associated types.
if (AlreadyComplained) { if (AlreadyComplained) {
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
} }
@@ -3520,12 +3556,11 @@ void ConformanceChecker::checkConformance() {
TC.checkGenericArguments(DC, Loc, noteLoc, Proto->getDeclaredType(), TC.checkGenericArguments(DC, Loc, noteLoc, Proto->getDeclaredType(),
Proto->getGenericSignature(), Proto->getGenericSignature(),
{Adoptee})) { {Adoptee})) {
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
return; return;
} }
// Check non-type requirements. // Check non-type requirements.
bool invalid = false;
for (auto member : Proto->getMembers()) { for (auto member : Proto->getMembers()) {
auto requirement = dyn_cast<ValueDecl>(member); auto requirement = dyn_cast<ValueDecl>(member);
if (!requirement) if (!requirement)
@@ -3551,7 +3586,7 @@ void ConformanceChecker::checkConformance() {
TC.validateDecl(requirement, true); TC.validateDecl(requirement, true);
if (requirement->isInvalid()) { if (requirement->isInvalid()) {
invalid = true; Conformance->setInvalid();
continue; continue;
} }
@@ -3566,7 +3601,7 @@ void ConformanceChecker::checkConformance() {
continue; continue;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
invalid = true; Conformance->setInvalid();
continue; continue;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3580,7 +3615,7 @@ void ConformanceChecker::checkConformance() {
continue; continue;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
invalid = true; Conformance->setInvalid();
continue; continue;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3594,7 +3629,7 @@ void ConformanceChecker::checkConformance() {
continue; continue;
case ResolveWitnessResult::ExplicitFailed: case ResolveWitnessResult::ExplicitFailed:
invalid = true; Conformance->setInvalid();
continue; continue;
case ResolveWitnessResult::Missing: case ResolveWitnessResult::Missing:
@@ -3604,12 +3639,6 @@ void ConformanceChecker::checkConformance() {
} }
emitDelayedDiags(); emitDelayedDiags();
if (AlreadyComplained || invalid) {
Conformance->setState(ProtocolConformanceState::Invalid);
} else {
Conformance->setState(ProtocolConformanceState::Complete);
}
} }
static void diagnoseConformanceFailure(TypeChecker &TC, Type T, static void diagnoseConformanceFailure(TypeChecker &TC, Type T,
@@ -3643,7 +3672,7 @@ void ConformanceChecker::diagnoseOrDefer(
ValueDecl *requirement, bool isError, ValueDecl *requirement, bool isError,
std::function<void(TypeChecker &, NormalProtocolConformance *)> fn) { std::function<void(TypeChecker &, NormalProtocolConformance *)> fn) {
if (isError) if (isError)
Conformance->setState(ProtocolConformanceState::Invalid); Conformance->setInvalid();
if (SuppressDiagnostics) { if (SuppressDiagnostics) {
// Stash this in the ASTContext for later emission. // Stash this in the ASTContext for later emission.
@@ -3689,15 +3718,17 @@ checkConformsToProtocol(TypeChecker &TC,
// Check the conformance below. // Check the conformance below.
break; break;
case ProtocolConformanceState::CheckingTypeWitnesses:
case ProtocolConformanceState::Checking: case ProtocolConformanceState::Checking:
case ProtocolConformanceState::Complete:
// Nothing to do. // Nothing to do.
return conformance; return conformance;
case ProtocolConformanceState::Invalid: case ProtocolConformanceState::Complete:
// Emit any delayed diagnostics and return. if (conformance->isInvalid()) {
// FIXME: Should we complete checking to emit more diagnostics? // Emit any delayed diagnostics and return.
ConformanceChecker(TC, conformance, false).emitDelayedDiags(); // FIXME: Should we complete checking to emit more diagnostics?
ConformanceChecker(TC, conformance, false).emitDelayedDiags();
}
return conformance; return conformance;
} }
@@ -3710,12 +3741,13 @@ checkConformsToProtocol(TypeChecker &TC,
// Note that we are checking this conformance now. // Note that we are checking this conformance now.
conformance->setState(ProtocolConformanceState::Checking); conformance->setState(ProtocolConformanceState::Checking);
defer([&] { conformance->setState(ProtocolConformanceState::Complete); });
// If the protocol requires a class, non-classes are a non-starter. // If the protocol requires a class, non-classes are a non-starter.
if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) { if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
TC.diagnose(ComplainLoc, diag::non_class_cannot_conform_to_class_protocol, TC.diagnose(ComplainLoc, diag::non_class_cannot_conform_to_class_protocol,
T, Proto->getDeclaredType()); T, Proto->getDeclaredType());
conformance->setState(ProtocolConformanceState::Invalid); conformance->setInvalid();
return conformance; return conformance;
} }
@@ -3727,7 +3759,7 @@ checkConformsToProtocol(TypeChecker &TC,
TC.diagnose(ComplainLoc, TC.diagnose(ComplainLoc,
diag::foreign_class_cannot_conform_to_objc_protocol, diag::foreign_class_cannot_conform_to_objc_protocol,
T, Proto->getDeclaredType()); T, Proto->getDeclaredType());
conformance->setState(ProtocolConformanceState::Invalid); conformance->setInvalid();
return conformance; return conformance;
} }
} }
@@ -3737,7 +3769,7 @@ checkConformsToProtocol(TypeChecker &TC,
if (Proto->hasMissingRequirements()) { if (Proto->hasMissingRequirements()) {
TC.diagnose(ComplainLoc, diag::protocol_has_missing_requirements, TC.diagnose(ComplainLoc, diag::protocol_has_missing_requirements,
T, Proto->getDeclaredType()); T, Proto->getDeclaredType());
conformance->setState(ProtocolConformanceState::Invalid); conformance->setInvalid();
return conformance; return conformance;
} }
@@ -3759,7 +3791,7 @@ checkConformsToProtocol(TypeChecker &TC,
InheritedProto->getDeclaredType()); InheritedProto->getDeclaredType());
} }
conformance->setState(ProtocolConformanceState::Invalid); conformance->setInvalid();
return conformance; return conformance;
} }
} }

View File

@@ -267,35 +267,35 @@ func testBrokenConformances1() {
StructWithBrokenConformance.#^BROKEN_CONFORMANCE_1^# StructWithBrokenConformance.#^BROKEN_CONFORMANCE_1^#
} }
// BROKEN_CONFORMANCE_1: Begin completions, 52 items // BROKEN_CONFORMANCE_1: Begin completions, 52 items
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DefaultedTypeCommonA{{; name=.+$}} BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonA[#DefaultedTypeCommonA#]; name=DefaultedTypeCommonA
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DefaultedTypeCommonB{{; name=.+$}} BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonB[#DefaultedTypeCommonB#]; name=DefaultedTypeCommonB
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDefaultedTypeB{{; name=.+$}} BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDefaultedTypeB[#FooBaseDefaultedTypeB#]; name=FooBaseDefaultedTypeB
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DeducedTypeCommonA{{; name=.+$}} BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DeducedTypeCommonA[#DeducedTypeCommonA#]; name=DeducedTypeCommonA
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DeducedTypeCommonB{{; name=.+$}} BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DeducedTypeCommonB[#DeducedTypeCommonB#]; name=DeducedTypeCommonB
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonA({#self: Self#})[#() -> Self.DeducedTypeCommonA#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonA({#self: Self#})[#() -> Self.DeducedTypeCommonA#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonB({#self: Self#})[#() -> Self.DeducedTypeCommonB#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonB({#self: Self#})[#() -> Self.DeducedTypeCommonB#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseB({#self: Self#})[#() -> Int#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseB({#self: Self#})[#() -> Int#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooDefaultedType{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooDefaultedType[#FooDefaultedType#]; name=FooDefaultedType
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooDeducedTypeB{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooDeducedTypeB[#FooDeducedTypeB#]; name=FooDeducedTypeB
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooDeducedTypeC{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooDeducedTypeC[#FooDeducedTypeC#]; name=FooDeducedTypeC
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooDeducedTypeD{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooDeducedTypeD[#FooDeducedTypeD#]; name=FooDeducedTypeD
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooB({#self: Self#})[#() -> Self.FooDeducedTypeB#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooB({#self: Self#})[#() -> Self.FooDeducedTypeB#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooC({#self: Self#})[#() -> Self.FooDeducedTypeC#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooC({#self: Self#})[#() -> Self.FooDeducedTypeC#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooD({#self: Self#})[#() -> Self.FooDeducedTypeD#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooD({#self: Self#})[#() -> Self.FooDeducedTypeD#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DefaultedTypeCommonC{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonC[#DefaultedTypeCommonC#]; name=DefaultedTypeCommonC
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DefaultedTypeCommonD{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG:Decl[TypeAlias]/CurrNominal: DefaultedTypeCommonD[#DefaultedTypeCommonD#]; name=DefaultedTypeCommonD
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDefaultedTypeA{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDefaultedTypeA[#FooBaseDefaultedTypeA#]; name=FooBaseDefaultedTypeA
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDefaultedTypeC{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDefaultedTypeC[#FooBaseDefaultedTypeC#]; name=FooBaseDefaultedTypeC
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DeducedTypeCommonC{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DeducedTypeCommonC[#DeducedTypeCommonC#]; name=DeducedTypeCommonC
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: DeducedTypeCommonD{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: DeducedTypeCommonD[#DeducedTypeCommonD#]; name=DeducedTypeCommonD
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonA({#self: Self#})[#() -> Self.DeducedTypeCommonA#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonA({#self: Self#})[#() -> Self.DeducedTypeCommonA#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonB({#self: Self#})[#() -> Self.DeducedTypeCommonB#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonB({#self: Self#})[#() -> Self.DeducedTypeCommonB#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonC({#self: Self#})[#() -> Self.DeducedTypeCommonC#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonC({#self: Self#})[#() -> Self.DeducedTypeCommonC#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonD({#self: Self#})[#() -> Self.DeducedTypeCommonD#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceCommonD({#self: Self#})[#() -> Self.DeducedTypeCommonD#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDeducedTypeA{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDeducedTypeA[#FooBaseDeducedTypeA#]; name=FooBaseDeducedTypeA
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDeducedTypeB{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDeducedTypeB[#FooBaseDeducedTypeB#]; name=FooBaseDeducedTypeB
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDeducedTypeC{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDeducedTypeC[#FooBaseDeducedTypeC#]; name=FooBaseDeducedTypeC
// BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/Super: FooBaseDeducedTypeD{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[TypeAlias]/CurrNominal: FooBaseDeducedTypeD[#FooBaseDeducedTypeD#]; name=FooBaseDeducedTypeD
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseA({#self: Self#})[#() -> Self.FooBaseDeducedTypeA#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseA({#self: Self#})[#() -> Self.FooBaseDeducedTypeA#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseB({#self: Self#})[#() -> Self.FooBaseDeducedTypeB#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseB({#self: Self#})[#() -> Self.FooBaseDeducedTypeB#]{{; name=.+$}}
// BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseC({#self: Self#})[#() -> Self.FooBaseDeducedTypeC#]{{; name=.+$}} // BROKEN_CONFORMANCE_1-DAG: Decl[InstanceMethod]/Super: deduceFooBaseC({#self: Self#})[#() -> Self.FooBaseDeducedTypeC#]{{; name=.+$}}