Skip to content

Commit ec9d114

Browse files
authored
Merge pull request #18757 from gregomni/optional-as
[Sema] Improve type coercion fixits for optional-to-optional conversions.
2 parents e0cef24 + 32bacc8 commit ec9d114

File tree

3 files changed

+23
-13
lines changed

3 files changed

+23
-13
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2869,6 +2869,10 @@ static bool addTypeCoerceFixit(InFlightDiagnostic &diag, ConstraintSystem &CS,
28692869
Type fromType, Type toType, Expr *expr) {
28702870
// Look through optional types; casts can add them, but can't remove extra
28712871
// ones.
2872+
bool bothOptional =
2873+
fromType->getOptionalObjectType() && toType->getOptionalObjectType();
2874+
if (bothOptional)
2875+
fromType = fromType->getOptionalObjectType();
28722876
toType = toType->lookThroughAllOptionalTypes();
28732877

28742878
CheckedCastKind Kind = CS.getTypeChecker().typeCheckCheckedCast(
@@ -2877,9 +2881,11 @@ static bool addTypeCoerceFixit(InFlightDiagnostic &diag, ConstraintSystem &CS,
28772881
if (Kind != CheckedCastKind::Unresolved) {
28782882
SmallString<32> buffer;
28792883
llvm::raw_svector_ostream OS(buffer);
2880-
toType->print(OS);
28812884
bool canUseAs = Kind == CheckedCastKind::Coercion ||
28822885
Kind == CheckedCastKind::BridgingCoercion;
2886+
if (bothOptional && canUseAs)
2887+
toType = OptionalType::get(toType);
2888+
toType->print(OS);
28832889
diag.fixItInsert(
28842890
Lexer::getLocForEndOfToken(CS.DC->getASTContext().SourceMgr,
28852891
expr->getEndLoc()),

test/Constraints/bridging.swift

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -276,30 +276,34 @@ func rdar19831698() {
276276
// <rdar://problem/19836341> Incorrect fixit for NSString? to String? conversions
277277
func rdar19836341(_ ns: NSString?, vns: NSString?) {
278278
var vns = vns
279-
let _: String? = ns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}
280-
var _: String? = ns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}
281-
// FIXME: there should be a fixit appending "as String?" to the line; for now
282-
// it's sufficient that it doesn't suggest appending "as String"
279+
let _: String? = ns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}{{22-22= as String?}}
280+
var _: String? = ns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}{{22-22= as String?}}
283281

284282
// Important part about below diagnostic is that from-type is described as
285283
// 'NSString?' and not '@lvalue NSString?':
286-
let _: String? = vns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}
287-
var _: String? = vns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}
288-
284+
let _: String? = vns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}{{23-23= as String?}}
285+
var _: String? = vns // expected-error{{cannot convert value of type 'NSString?' to specified type 'String?'}}{{23-23= as String?}}
286+
289287
vns = ns
290288
}
291289

292290
// <rdar://problem/20029786> Swift compiler sometimes suggests changing "as!" to "as?!"
293291
func rdar20029786(_ ns: NSString?) {
294-
var s: String = ns ?? "str" as String as String // expected-error{{cannot convert value of type 'NSString?' to expected argument type 'String?'}}
295-
var s2 = ns ?? "str" as String as String // expected-error {{cannot convert value of type 'String' to expected argument type 'NSString'}}
292+
var s: String = ns ?? "str" as String as String // expected-error{{cannot convert value of type 'NSString?' to expected argument type 'String?'}}{{21-21= as String?}}
293+
var s2 = ns ?? "str" as String as String // expected-error {{cannot convert value of type 'String' to expected argument type 'NSString'}}{{43-43= as NSString}}
296294

297-
let s3: NSString? = "str" as String? // expected-error {{cannot convert value of type 'String?' to specified type 'NSString?'}}
295+
let s3: NSString? = "str" as String? // expected-error {{cannot convert value of type 'String?' to specified type 'NSString?'}}{{39-39= as NSString?}}
298296

299-
var s4: String = ns ?? "str" // expected-error{{cannot convert value of type 'NSString' to specified type 'String'}}
297+
var s4: String = ns ?? "str" // expected-error{{cannot convert value of type 'NSString' to specified type 'String'}}{{31-31= as String}}
300298
var s5: String = (ns ?? "str") as String // fixed version
301299
}
302300

301+
// Make sure more complicated cast has correct parenthesization
302+
func castMoreComplicated(anInt: Int?) {
303+
let _: (NSObject & NSCopying)? = anInt // expected-error{{cannot convert value of type 'Int?' to specified type '(NSObject & NSCopying)?'}}{{41-41= as (NSObject & NSCopying)?}}
304+
}
305+
306+
303307
// <rdar://problem/19813772> QoI: Using as! instead of as in this case produces really bad diagnostic
304308
func rdar19813772(_ nsma: NSMutableArray) {
305309
var a1 = nsma as! Array // expected-error{{generic parameter 'Element' could not be inferred in cast to 'Array'}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{26-26=<Any>}}

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

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

2020
func foo2(_ messageData: Any?) -> AnyObject? {
21-
return messageData as AnyObject
21+
return messageData as AnyObject?
2222
}

0 commit comments

Comments
 (0)