Skip to content

Commit b5cb81b

Browse files
authored
Merge pull request #30160 from xedin/rdar-59773317
[ConstraintSystem] Don't record general contextual mismatch if there are restrictions present
2 parents d114a0e + 0cd44a8 commit b5cb81b

File tree

8 files changed

+45
-38
lines changed

8 files changed

+45
-38
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,12 @@ bool ContextualFailure::diagnoseAsError() {
18781878
if (diagnoseCoercionToUnrelatedType())
18791879
return true;
18801880

1881+
if (isa<OptionalTryExpr>(anchor)) {
1882+
emitDiagnostic(anchor->getLoc(), diag::cannot_convert_initializer_value,
1883+
getFromType(), getToType());
1884+
return true;
1885+
}
1886+
18811887
return false;
18821888
}
18831889

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,6 +3609,10 @@ bool ConstraintSystem::repairFailures(
36093609
if (lhs->isHole() || rhs->isHole())
36103610
return true;
36113611

3612+
// If either side is not yet resolved, it's too early for this fix.
3613+
if (lhs->isTypeVariableOrMember() || rhs->isTypeVariableOrMember())
3614+
break;
3615+
36123616
auto purpose = getContextualTypePurpose(anchor);
36133617
if (rhs->isVoid() &&
36143618
(purpose == CTP_ReturnStmt || purpose == CTP_ReturnSingleExpr)) {
@@ -3649,33 +3653,16 @@ bool ConstraintSystem::repairFailures(
36493653
break;
36503654
}
36513655

3652-
// If either side is not yet resolved, it's too early for this fix.
3653-
if (lhs->isTypeVariableOrMember() || rhs->isTypeVariableOrMember())
3654-
break;
3655-
3656-
// If contextual type is an existential value, it's handled
3657-
// after conversion restriction is attempted.
3658-
if (rhs->isExistentialType())
3659-
break;
3660-
36613656
if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind, conversionsOrFixes,
36623657
locator))
36633658
break;
36643659

3665-
// If there is a deep equality, superclass restriction
3666-
// already recorded, let's not add bother ignoring
3667-
// contextual type, because actual fix is going to
3668-
// be performed once restriction is applied.
3669-
if (hasConversionOrRestriction(ConversionRestrictionKind::Superclass))
3670-
break;
3671-
3672-
if (hasConversionOrRestriction(
3673-
ConversionRestrictionKind::MetatypeToExistentialMetatype))
3674-
break;
3675-
3676-
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality) &&
3677-
!hasConversionOrRestriction(
3678-
ConversionRestrictionKind::OptionalToOptional))
3660+
// If there are any restrictions here we need to wait and let
3661+
// `simplifyRestrictedConstraintImpl` handle them.
3662+
if (llvm::any_of(conversionsOrFixes,
3663+
[](const RestrictionOrFix &correction) {
3664+
return bool(correction.getRestriction());
3665+
}))
36793666
break;
36803667

36813668
conversionsOrFixes.push_back(IgnoreContextualType::create(
@@ -8532,7 +8519,8 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
85328519
auto impact = 2;
85338520
if (loc->isForAssignment() || loc->isForCoercion() ||
85348521
loc->isForContextualType() ||
8535-
loc->isLastElement<LocatorPathElt::ApplyArgToParam>()) {
8522+
loc->isLastElement<LocatorPathElt::ApplyArgToParam>() ||
8523+
loc->isForOptionalTry()) {
85368524
if (restriction == ConversionRestrictionKind::Superclass) {
85378525
if (auto *fix =
85388526
CoerceToCheckedCast::attempt(*this, fromType, toType, loc))

lib/Sema/ConstraintLocator.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,15 @@ bool ConstraintLocator::isForContextualType() const {
234234
}
235235

236236
bool ConstraintLocator::isForAssignment() const {
237-
auto *anchor = getAnchor();
238-
return anchor && isa<AssignExpr>(anchor) && getPath().empty();
237+
return directlyAt<AssignExpr>();
239238
}
240239

241240
bool ConstraintLocator::isForCoercion() const {
242-
auto *anchor = getAnchor();
243-
return anchor && isa<CoerceExpr>(anchor) && getPath().empty();
241+
return directlyAt<CoerceExpr>();
242+
}
243+
244+
bool ConstraintLocator::isForOptionalTry() const {
245+
return directlyAt<OptionalTryExpr>();
244246
}
245247

246248
GenericTypeParamType *ConstraintLocator::getGenericParameter() const {

lib/Sema/ConstraintLocator.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,15 @@ class ConstraintLocator : public llvm::FoldingSetNode {
371371
/// Determine whether this locator points to the coercion expression.
372372
bool isForCoercion() const;
373373

374+
/// Determine whether this locator points to the `try?` expression.
375+
bool isForOptionalTry() const;
376+
377+
/// Determine whether this locator points directly to a given expression.
378+
template <class E> bool directlyAt() const {
379+
auto *anchor = getAnchor();
380+
return anchor && isa<E>(anchor) && getPath().empty();
381+
}
382+
374383
/// Attempts to cast the first path element of the locator to a specific
375384
/// \c LocatorPathElt subclass, returning \c None if either unsuccessful or
376385
/// the locator has no path elements.

test/Constraints/enum_cases.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,16 @@ foo(Foo.a, Foo.b) // Ok in Swift 4 because we strip labels from the arguments
9393

9494
// rdar://problem/32551313 - Useless SE-0110 diagnostic
9595

96-
enum E_32551313<L, R> { // expected-note {{'R' declared as parameter to type 'E_32551313'}}
96+
enum E_32551313<L, R> {
9797
case Left(L)
9898
case Right(R)
9999
}
100100

101101
struct Foo_32551313 {
102-
// FIXME(diagnostics): We should be able to figure out L and R from contextual type
103102
static func bar() -> E_32551313<(String, Foo_32551313?), (String, String)>? {
104-
return E_32551313.Left("", Foo_32551313()) // expected-error {{extra argument in call}}
105-
// expected-error@-1 {{generic parameter 'R' could not be inferred}} expected-note@-1 {{explicitly specify the generic arguments to fix this issue}}
106-
// expected-error@-2 {{cannot convert return expression of type 'E_32551313<String, R>' to return type 'E_32551313<(String, Foo_32551313?), (String, String)>?'}}
103+
return E_32551313.Left("", Foo_32551313())
104+
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type '(String, Foo_32551313?)'}}
105+
// expected-error@-2 {{extra argument in call}}
107106
}
108107
}
109108

test/Constraints/fixes.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,15 @@ struct Q {
159159
}
160160
let q = Q(s: nil)
161161
let a: Int? = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
162-
// expected-error@-1 {{cannot convert value of type 'String.UTF8View' to specified type 'Int?'}}
162+
// expected-error@-1 {{cannot convert value of type 'String.UTF8View?' to specified type 'Int?'}}
163163
// expected-note@-2{{chain the optional using '?'}}{{18-18=?}}
164-
// expected-note@-3{{force-unwrap using '!'}}{{18-18=!}}
165164
let b: Int = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
166165
// expected-error@-1 {{cannot convert value of type 'String.UTF8View' to specified type 'Int'}}
167166
// expected-note@-2{{chain the optional using '?'}}{{17-17=?}}
168167
// expected-note@-3{{force-unwrap using '!'}}{{17-17=!}}
169168
let d: Int! = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
170-
// expected-error@-1 {{cannot convert value of type 'String.UTF8View' to specified type 'Int?'}}
169+
// expected-error@-1 {{cannot convert value of type 'String.UTF8View?' to specified type 'Int?'}}
171170
// expected-note@-2{{chain the optional using '?'}}{{18-18=?}}
172-
// expected-note@-3{{force-unwrap using '!'}}{{18-18=!}}
173171
let c = q.s.utf8 // expected-error{{value of optional type 'String?' must be unwrapped to refer to member 'utf8' of wrapped base type 'String'}}
174172
// expected-note@-1{{chain the optional using '?' to access member 'utf8' only for non-'nil' base values}}{{12-12=?}}
175173
// expected-note@-2{{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{12-12=!}}

test/Constraints/function_conversion.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ noEscapeParam = escapingParam // expected-error {{converting non-escaping value
6363

6464
escapingParam = takesAny
6565
noEscapeParam = takesAny // expected-error {{converting non-escaping value to 'Any' may allow it to escape}}
66+
67+
// rdar://problem/59773317 - Improve type error message when returning (or escaping) a function-typed value as an optional of that type
68+
func rdar_59773317(x: () -> Int) -> (() -> Int)? { // expected-note {{parameter 'x' is implicitly non-escaping}}
69+
return x // expected-error {{using non-escaping parameter 'x' in a context expecting an @escaping closure}}
70+
}

test/FixCode/fixits-apply-objc.swift.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,5 @@ func foo1(_ an : Any) {
107107
}
108108

109109
func foo2(_ messageData: Any?) -> AnyObject? {
110-
return messageData as AnyObject?
110+
return messageData as AnyObject
111111
}

0 commit comments

Comments
 (0)