Skip to content

Commit 2bab74c

Browse files
authored
Merge pull request #61843 from slavapestov/rqm-invalid-inheritance-clause
RequirementMachine: Better error recovery from invalid protocol inheritance clauses
2 parents 60c8b4b + 23abf74 commit 2bab74c

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,10 +724,28 @@ StructuralRequirementsRequest::evaluate(Evaluator &evaluator,
724724

725725
auto selfTy = proto->getSelfInterfaceType();
726726

727+
unsigned errorCount = errors.size();
727728
realizeInheritedRequirements(proto, selfTy,
728729
/*inferRequirements=*/false,
729730
result, errors);
730731

732+
if (errors.size() > errorCount) {
733+
// Add requirements from inherited protocols, which are obtained via
734+
// getDirectlyInheritedNominalTypeDecls(). Normally this duplicates
735+
// the information found in the resolved types from the inheritance
736+
// clause, except when type resolution fails and returns an ErrorType.
737+
//
738+
// For example, in 'protocol P: Q & Blah', where 'Blah' does not exist,
739+
// the type 'Q & Blah' resolves to an ErrorType, while the simpler
740+
// mechanism in getDirectlyInheritedNominalTypeDecls() still finds 'Q'.
741+
for (auto *inheritedProto : proto->getInheritedProtocols()) {
742+
result.push_back({
743+
Requirement(RequirementKind::Conformance,
744+
selfTy, inheritedProto->getDeclaredInterfaceType()),
745+
SourceLoc(), /*wasInferred=*/false});
746+
}
747+
}
748+
731749
// Add requirements from the protocol's own 'where' clause.
732750
WhereClauseOwner(proto).visitRequirements(TypeResolutionStage::Structural,
733751
[&](const Requirement &req, RequirementRepr *reqRepr) {

test/Generics/issue-61020.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-typecheck-verify-swift -debug-generic-signatures 2>&1 | %FileCheck %s
2+
3+
protocol Base<T> {
4+
associatedtype T
5+
}
6+
7+
// CHECK-LABEL: .Derived@
8+
// CHECK-NEXT: Requirement signature: <Self where Self : Base>
9+
protocol Derived: Base & DoesNotExist { // expected-error {{cannot find type 'DoesNotExist' in scope}}
10+
func position(_: T)
11+
}
12+
13+
// CHECK-LABEL: .OtherDerived@
14+
// CHECK-NEXT: Requirement signature: <Self where Self : Base>
15+
protocol OtherDerived: Base<DoesNotExist> {} // expected-error {{cannot find type 'DoesNotExist' in scope}}

0 commit comments

Comments
 (0)