Skip to content

Commit a29686f

Browse files
authored
Issue-60730: Addressing the situation where we were saying that (any … (#61191)
* Issue-60730: Addressing the situation where we were saying that (any P)? does not conform to P, instead we should offer the Force Optional error messaging * Issue-60730: Removing assigned of AllowArgumentMismatch fix that would get thrown away if we fall into ForceOptional fix * Issue-60730: Removing file that was accidentally changed * Issue-60730: Updating to use simplifyConformsToConstraint - and to clean up code per comments * Issue-60730: Updating to pass protocoDecl instead of type2 to simplifyConformsToConstraint * Issue-60730: Updating to pass protocoDecl instead of type2 to simplifyConformsToConstraint * Issue-60730: Updating to not pass 1 to recordFix, where that is the default value * Issue-60730: Adding in test to validate that the fix works as expected * Issue-60730: Cleaning up test based on PR Comments * Issue-60730: Correcting typo in test * Issue-60730: Adding additional test cases for layers of optionals and for non-conforming argument * Issue-60730: Updating test to include fixme(diagnostics) for multilpe layers of force unwrap
1 parent 2c9819a commit a29686f

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,18 +3627,29 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
36273627

36283628
if (last.is<LocatorPathElt::ApplyArgToParam>()) {
36293629
auto proto = protoDecl->getDeclaredInterfaceType();
3630-
auto *fix = AllowArgumentMismatch::create(
3631-
*this, type1, proto, getConstraintLocator(anchor, path));
3632-
36333630
// Impact is 2 here because there are two failures
36343631
// 1 - missing conformance and 2 - incorrect argument type.
36353632
//
36363633
// This would make sure that arguments with incorrect
36373634
// conformances are not prioritized over general argument
36383635
// mismatches.
3636+
if (type1->isOptional()) {
3637+
auto unwrappedType = type1->lookThroughAllOptionalTypes();
3638+
auto result = simplifyConformsToConstraint(
3639+
unwrappedType, protoDecl, kind, locator,
3640+
subflags | TMF_ApplyingFix);
3641+
if (result == SolutionKind::Solved) {
3642+
auto fix = ForceOptional::create(*this, type1, proto,
3643+
getConstraintLocator(locator));
3644+
if (recordFix(fix))
3645+
return getTypeMatchFailure(locator);
3646+
break;
3647+
}
3648+
}
3649+
auto fix = AllowArgumentMismatch::create(
3650+
*this, type1, proto, getConstraintLocator(anchor, path));
36393651
if (recordFix(fix, /*impact=*/2))
36403652
return getTypeMatchFailure(locator);
3641-
36423653
break;
36433654
}
36443655

test/Constraints/optional.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,3 +565,27 @@ func testFunctionContainerMethodCall(container: FunctionContainer?) {
565565
// expected-note@-3 {{coalesce}}
566566
// expected-note@-4 {{force-unwrap}}
567567
}
568+
569+
// Test for https://github.com/apple/swift/issues/60730
570+
// rdar://94037733
571+
do {
572+
struct S: P {}
573+
func takesP(_: any P) {}
574+
func passOptional(value: (any P)?) {
575+
takesP(value)
576+
// expected-error@-1 {{value of optional type '(any P)?' must be unwrapped to a value of type 'any P'}}
577+
// expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
578+
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
579+
}
580+
func passLayersOfOptional(value: (any P)??) {
581+
// FIXME(diagnostics): Consider recording multiple ForceUnwrap fixes based on number of optionals
582+
takesP(value)
583+
// expected-error@-1 {{value of optional type '(any P)??' must be unwrapped to a value of type '(any P)?}}
584+
// expected-note@-2 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
585+
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
586+
}
587+
func passNonConformingValue(value: (any BinaryInteger)?){
588+
takesP(value)
589+
// expected-error@-1 {{argument type '(any BinaryInteger)?' does not conform to expected type 'P'}}
590+
}
591+
}

0 commit comments

Comments
 (0)