From b12d844fcc35b60f01fb9c092bd5a7fc1616defd Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Thu, 29 May 2025 15:50:22 -0700 Subject: [PATCH] [CSSimplify] Remove ad-hoc optional mismatch handling for arguments Since we have `repairViaOptionalUnwrap`, let's use that to fix argument/parameter mismatches instead of doing ad-hoc matching. --- lib/Sema/CSSimplify.cpp | 51 +++++++---------------------- test/Constraints/if_expr.swift | 1 + test/Constraints/rdar44770297.swift | 3 -- 3 files changed, 13 insertions(+), 42 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 654719af07d..2a6e0f260f8 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -4989,8 +4989,18 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType, // First, let's check whether it has been determined that // it was incorrect to use `?` in this position. - if (cs.hasFixFor(cs.getConstraintLocator(subExpr), FixKind::RemoveUnwrap)) + if (cs.hasFixFor(cs.getConstraintLocator(subExpr), FixKind::RemoveUnwrap)) { + if (auto *typeVar = + fromType->getOptionalObjectType()->getAs()) { + // If the optional chain is invalid let's unwrap optional and + // re-introduce the constraint to be solved later once both sides + // are sufficiently resolved, this would allow to diagnose not only + // the invalid unwrap but an invalid conversion (if any) as well. + cs.addConstraint(matchKind, typeVar, toType, + cs.getConstraintLocator(locator)); + } return true; + } auto type = cs.getType(subExpr); // If the type of sub-expression is optional, type of the @@ -5919,43 +5929,6 @@ bool ConstraintSystem::repairFailures( if (repairByTreatingRValueAsLValue(lhs, rhs)) break; - // If the problem is related to missing unwrap, there is a special - // fix for that. - if (lhs->getOptionalObjectType() && !rhs->getOptionalObjectType()) { - // If this is an attempt to check whether optional conforms to a - // particular protocol, let's do that before attempting to force - // unwrap the optional. - if (hasConversionOrRestriction(ConversionRestrictionKind::Existential)) - break; - - if (auto *typeVar = - lhs->getOptionalObjectType()->getAs()) { - auto *argLoc = typeVar->getImpl().getLocator(); - if (argLoc->directlyAt()) { - auto OEE = castToExpr(argLoc->getAnchor()); - // If the optional chain in the argument position is invalid - // let's unwrap optional and re-introduce the constraint to - // be solved later once both sides are sufficiently resolved, - // this would allow to diagnose not only the invalid unwrap - // but an invalid conversion (if any) as well. - if (hasFixFor(getConstraintLocator(OEE->getSubExpr()), - FixKind::RemoveUnwrap)) { - addConstraint(matchKind, typeVar, rhs, loc); - return true; - } - } - } - - auto result = matchTypes(lhs->getOptionalObjectType(), rhs, matchKind, - TMF_ApplyingFix, locator); - - if (result.isSuccess()) { - conversionsOrFixes.push_back( - ForceOptional::create(*this, lhs, rhs, loc)); - break; - } - } - // If argument in l-value type and parameter is `inout` or a pointer, // let's see if it's generic parameter matches and suggest adding explicit // `&`. @@ -6082,7 +6055,7 @@ bool ConstraintSystem::repairFailures( if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes, locator)) - break; + return true; { auto *calleeLocator = getCalleeLocator(loc); diff --git a/test/Constraints/if_expr.swift b/test/Constraints/if_expr.swift index 81307396b30..301a02145a2 100644 --- a/test/Constraints/if_expr.swift +++ b/test/Constraints/if_expr.swift @@ -705,6 +705,7 @@ func builderInClosure() { func testInvalidOptionalChainingInIfContext() { let v63796 = 1 if v63796? {} // expected-error{{cannot use optional chaining on non-optional value of type 'Int'}} + // expected-error@-1 {{type 'Int' cannot be used as a boolean; test for '!= 0' instead}} } // https://github.com/swiftlang/swift/issues/79395 diff --git a/test/Constraints/rdar44770297.swift b/test/Constraints/rdar44770297.swift index 0853b150b35..77dc228fc25 100644 --- a/test/Constraints/rdar44770297.swift +++ b/test/Constraints/rdar44770297.swift @@ -10,6 +10,3 @@ func foo(_: () throws -> T) -> T.A? { // expected-note {{where 'T' = 'Neve let _ = foo() {fatalError()} & nil // expected-error@-1 {{global function 'foo' requires that 'Never' conform to 'P'}} -// expected-error@-2 {{value of optional type 'Never.A?' must be unwrapped to a value of type 'Never.A'}} -// expected-note@-3 {{coalesce using '??' to provide a default when the optional value contains 'nil'}} -// expected-note@-4 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}