@@ -5405,32 +5405,40 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
5405
5405
}
5406
5406
5407
5407
if (doDiag && !options.contains (TypeResolutionFlags::SilenceErrors)) {
5408
- // Prior to Swift 5, we allow 'as T!' and turn it into a disjunction.
5409
- if (ctx.isSwiftVersionAtLeast (5 )) {
5410
- // Mark this repr as invalid. This is the only way to indicate that
5411
- // something went wrong without supressing checking other reprs in
5412
- // the same type. For example:
5413
- //
5414
- // struct S<T, U> { ... }
5415
- //
5416
- // _ = S<Int!, String!>(...)
5417
- //
5418
- // Compiler should diagnose both `Int!` and `String!` as invalid,
5419
- // but returning `ErrorType` from here would stop type resolution
5420
- // after `Int!`.
5408
+ // In language modes up to Swift 5, we allow `T!` in invalid position for
5409
+ // compatibility and downgrade the error to a warning.
5410
+ const unsigned swiftLangModeForError = 5 ;
5411
+
5412
+ // If we are about to error, mark this node as invalid.
5413
+ // This is the only way to indicate that something went wrong without
5414
+ // supressing checking of sibling nodes.
5415
+ // For example:
5416
+ //
5417
+ // struct S<T, U> { ... }
5418
+ //
5419
+ // _ = S<Int!, String!>(...)
5420
+ //
5421
+ // Compiler should diagnose both `Int!` and `String!` as invalid,
5422
+ // but returning `ErrorType` from here would stop type resolution
5423
+ // after `Int!`.
5424
+ if (ctx.isSwiftVersionAtLeast (swiftLangModeForError)) {
5421
5425
repr->setInvalid ();
5426
+ }
5422
5427
5423
- diagnose (repr->getStartLoc (),
5424
- diag::implicitly_unwrapped_optional_in_illegal_position)
5425
- .fixItReplace (repr->getExclamationLoc (), " ?" );
5426
- } else if (options.is (TypeResolverContext::ExplicitCastExpr)) {
5427
- diagnose (
5428
- repr->getStartLoc (),
5429
- diag::implicitly_unwrapped_optional_deprecated_in_this_position);
5430
- } else {
5431
- diagnose (
5432
- repr->getStartLoc (),
5433
- diag::implicitly_unwrapped_optional_in_illegal_position_interpreted_as_optional)
5428
+ Diag<> diagID = diag::iuo_deprecated_here;
5429
+ if (ctx.isSwiftVersionAtLeast (swiftLangModeForError)) {
5430
+ diagID = diag::iuo_invalid_here;
5431
+ }
5432
+
5433
+ diagnose (repr->getExclamationLoc (), diagID)
5434
+ .warnUntilSwiftVersion (swiftLangModeForError);
5435
+
5436
+ // Suggest a regular optional, but not when `T!` is the right-hand side of
5437
+ // a cast expression.
5438
+ // In this case, the user is likely trying to cast an expression of optional
5439
+ // type, and this fix-it is not generally helpful.
5440
+ if (!options.is (TypeResolverContext::ExplicitCastExpr)) {
5441
+ diagnose (repr->getExclamationLoc (), diag::iuo_use_optional_instead)
5434
5442
.fixItReplace (repr->getExclamationLoc (), " ?" );
5435
5443
}
5436
5444
}
0 commit comments