Skip to content

Commit f5264b9

Browse files
Suyash SrijanSuyash Srijan
authored andcommitted
[diag] fix incorrect diagnostic when unwrapping double optional
1 parent 07b1905 commit f5264b9

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,21 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
580580
anchor = assignExpr->getSrc();
581581

582582
auto *unwrapped = anchor->getValueProvidingExpr();
583-
auto type = getType(anchor)->getRValueType();
584-
583+
Type type = [&] {
584+
// The anchor could be pointing to an OptionalEvaluationExpr, with the sub
585+
// expression being a CallExpr, UnresolvedDotExpr, etc which could produce
586+
// an >= 1 optional, so let's return the type of the sub expression.
587+
if (auto OEE = dyn_cast<OptionalEvaluationExpr>(anchor)) {
588+
if (auto subTy = getType(OEE->getSubExpr())) {
589+
if (!subTy->hasLValueType() && subTy->getOptionalObjectType()) {
590+
return subTy->getRValueType();
591+
}
592+
}
593+
}
594+
// Just return the type of the anchor
595+
return getType(anchor)->getRValueType();
596+
}();
597+
585598
auto *tryExpr = dyn_cast<OptionalTryExpr>(unwrapped);
586599
if (!tryExpr)
587600
return diagnoseUnwrap(getConstraintSystem(), unwrapped, type);

test/Constraints/fixes.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,47 @@ func moreComplexUnwrapFixes() {
243243

244244
}
245245
}
246+
247+
struct FooStruct {
248+
func a() -> Int?? { return 10 }
249+
250+
var b: Int?? {
251+
return 15
252+
}
253+
254+
func c() -> Int??? { return 20 }
255+
256+
var d: Int??? {
257+
return 25
258+
}
259+
260+
let e: BarStruct? = BarStruct()
261+
}
262+
263+
struct BarStruct {
264+
func a() -> Int? { return 30 }
265+
var b: Int?? {
266+
return 35
267+
}
268+
}
269+
270+
let thing: FooStruct? = FooStruct()
271+
272+
let _: Int? = thing?.a() // expected-error {{value of optional type 'Int??' must be unwrapped to a value of type 'Int?'}}
273+
// expected-note@-1{{coalesce}}
274+
// expected-note@-2{{force-unwrap}}
275+
let _: Int? = thing?.b // expected-error {{value of optional type 'Int??' must be unwrapped to a value of type 'Int?'}}
276+
// expected-note@-1{{coalesce}}
277+
// expected-note@-2{{force-unwrap}}
278+
let _: Int?? = thing?.c() // expected-error {{value of optional type 'Int???' must be unwrapped to a value of type 'Int??'}}
279+
// expected-note@-1{{coalesce}}
280+
// expected-note@-2{{force-unwrap}}
281+
let _: Int?? = thing?.d // expected-error {{value of optional type 'Int???' must be unwrapped to a value of type 'Int??'}}
282+
// expected-note@-1{{coalesce}}
283+
// expected-note@-2{{force-unwrap}}
284+
let _: Int = thing?.e?.a() // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}}
285+
// expected-note@-1{{coalesce}}
286+
// expected-note@-2{{force-unwrap}}
287+
let _: Int? = thing?.e?.b // expected-error {{value of optional type 'Int??' must be unwrapped to a value of type 'Int?'}}
288+
// expected-note@-1{{coalesce}}
289+
// expected-note@-2{{force-unwrap}}

0 commit comments

Comments
 (0)