Skip to content

Commit 35730d6

Browse files
committed
Sema: Don't be so eager to force type witnesses when resolving a value witness
resolveWitnessViaLookup() was only called from one place and didn't need to force anything at all, and resolveSingleWitness() now only forces the type witnesses actually referenced by the requirement. An old crasher test case that was considered "fixed" when we started to diagnose it now type checks correctly.
1 parent 82e7631 commit 35730d6

File tree

4 files changed

+35
-30
lines changed

4 files changed

+35
-30
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4121,6 +4121,14 @@ TypeWitnessRequest::evaluate(Evaluator &eval,
41214121
auto *better = getBetterConformanceForResolvingTypeWitnesses(
41224122
conformance, requirement);
41234123

4124+
if (better == conformance) {
4125+
LLVM_DEBUG(llvm::dbgs() << "Conformance to " << conformance->getProtocol()
4126+
<< " is best\n";);
4127+
} else {
4128+
LLVM_DEBUG(llvm::dbgs() << "Conformance to " << better->getProtocol()
4129+
<< " is better than " << conformance->getProtocol()
4130+
<< "\n";);
4131+
}
41244132
if (better != conformance &&
41254133
!ctx.evaluator.hasActiveRequest(ResolveTypeWitnessesRequest{better})) {
41264134
// Let's try to resolve type witnesses in the better conformance.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4018,22 +4018,6 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
40184018
assert(!isa<AssociatedTypeDecl>(requirement) && "Use resolveTypeWitnessVia*");
40194019
auto *nominal = DC->getSelfNominalTypeDecl();
40204020

4021-
// Resolve all associated types before trying to resolve this witness.
4022-
evaluateOrDefault(getASTContext().evaluator,
4023-
ResolveTypeWitnessesRequest{Conformance},
4024-
evaluator::SideEffect());
4025-
4026-
// If any of the type witnesses was erroneous, don't bother to check
4027-
// this value witness: it will fail.
4028-
auto referenced = evaluateOrDefault(getASTContext().evaluator,
4029-
ReferencedAssociatedTypesRequest{requirement},
4030-
TinyPtrVector<AssociatedTypeDecl *>());
4031-
for (auto assocType : referenced) {
4032-
if (Conformance->getTypeWitness(assocType)->hasError()) {
4033-
return ResolveWitnessResult::ExplicitFailed;
4034-
}
4035-
}
4036-
40374021
// Determine whether we can derive a witness for this requirement.
40384022
bool canDerive = false;
40394023

@@ -4537,18 +4521,13 @@ void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
45374521
if (!requirement->isProtocolRequirement())
45384522
return;
45394523

4540-
// Resolve all associated types before trying to resolve this witness.
4541-
evaluateOrDefault(getASTContext().evaluator,
4542-
ResolveTypeWitnessesRequest{Conformance},
4543-
evaluator::SideEffect());
4544-
4545-
// If any of the type witnesses was erroneous, don't bother to check
4546-
// this value witness: it will fail.
4547-
auto assocTypes = evaluateOrDefault(getASTContext().evaluator,
4524+
// Resolve the type witnesses for all associated types referenced by
4525+
// the requirement. If any are erroneous, don't bother resolving the
4526+
// witness.
4527+
auto referenced = evaluateOrDefault(getASTContext().evaluator,
45484528
ReferencedAssociatedTypesRequest{requirement},
45494529
TinyPtrVector<AssociatedTypeDecl *>());
4550-
4551-
for (auto assocType : assocTypes) {
4530+
for (auto assocType : referenced) {
45524531
if (Conformance->getTypeWitness(assocType)->hasError()) {
45534532
Conformance->setInvalid();
45544533
return;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-typecheck-verify-swift -disable-experimental-associated-type-inference
2+
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
3+
4+
// The 'for' loop has to come first, to force Sequence.makeIterator().
5+
for x in S() { _ = x }
6+
7+
struct S: RandomAccessCollection {
8+
public var startIndex: Int { 0 }
9+
public var endIndex: Int { 0 }
10+
public subscript(position: Int) -> Int { 0 }
11+
}
12+
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
// RUN: %target-swift-frontend -emit-sil -module-name main -primary-file %s %S/Inputs/protocol-conformance-issue-53408-other.swift -verify
2-
// RUN: %target-swift-frontend -emit-sil -module-name main %s -primary-file %S/Inputs/protocol-conformance-issue-53408-other.swift
1+
// RUN: not %target-swift-frontend -emit-sil -module-name main -primary-file %s %S/Inputs/protocol-conformance-issue-53408-other.swift -disable-experimental-associated-type-inference
2+
// RUN: %target-swift-frontend -emit-sil -module-name main %s -primary-file %S/Inputs/protocol-conformance-issue-53408-other.swift -disable-experimental-associated-type-inference
3+
// RUN: not %target-swift-frontend -emit-sil -module-name main %s %S/Inputs/protocol-conformance-issue-53408-other.swift -disable-experimental-associated-type-inference
4+
// RUN: %target-swift-frontend -emit-sil -module-name main %S/Inputs/protocol-conformance-issue-53408-other.swift %s -disable-experimental-associated-type-inference
5+
6+
// RUN: %target-swift-frontend -emit-sil -module-name main -primary-file %s %S/Inputs/protocol-conformance-issue-53408-other.swift -enable-experimental-associated-type-inference
7+
// RUN: %target-swift-frontend -emit-sil -module-name main %s -primary-file %S/Inputs/protocol-conformance-issue-53408-other.swift -enable-experimental-associated-type-inference
8+
// RUN: %target-swift-frontend -emit-sil -module-name main %s %S/Inputs/protocol-conformance-issue-53408-other.swift -enable-experimental-associated-type-inference
9+
// RUN: %target-swift-frontend -emit-sil -module-name main %S/Inputs/protocol-conformance-issue-53408-other.swift %s -enable-experimental-associated-type-inference
310

411
// https://github.com/apple/swift/issues/53408
512

613
func reproducer() -> Float { return Struct().func1(1.0) }
7-
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Struct.Input'}}
8-
// expected-error@-2 {{type 'Struct' does not conform to protocol 'Proto1'}}
14+

0 commit comments

Comments
 (0)