Skip to content

Commit 499146d

Browse files
Merge pull request #78739 from AnthonyLatsis/hatzegopteryx
TypeCheckType: Rework IUO diagnostics using behavior limitation
2 parents 91d7cc4 + 35f1370 commit 499146d

File tree

10 files changed

+293
-129
lines changed

10 files changed

+293
-129
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6145,14 +6145,12 @@ ERROR(closure_unlabeled_parameter_following_variadic_parameter,none,
61456145
ERROR(parameter_vararg_default,none,
61466146
"variadic parameter cannot have a default value", ())
61476147

6148-
WARNING(implicitly_unwrapped_optional_in_illegal_position_interpreted_as_optional,none,
6149-
"using '!' is not allowed here; treating this as '?' instead", ())
6150-
6151-
WARNING(implicitly_unwrapped_optional_deprecated_in_this_position,Deprecation,
6152-
"using '!' here is deprecated and will be removed in a future release", ())
6153-
6154-
ERROR(implicitly_unwrapped_optional_in_illegal_position,none,
6155-
"using '!' is not allowed here; perhaps '?' was intended?", ())
6148+
ERROR(iuo_invalid_here, none,
6149+
"using '!' is not allowed here", ())
6150+
ERROR(iuo_deprecated_here,Deprecation,
6151+
"using '!' here is deprecated", ())
6152+
NOTE(iuo_use_optional_instead,none,
6153+
"use '?' instead", ())
61566154

61576155
// Ownership
61586156
ERROR(invalid_ownership_type,none,

lib/Sema/TypeCheckType.cpp

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5405,32 +5405,40 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
54055405
}
54065406

54075407
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)) {
54215425
repr->setInvalid();
5426+
}
54225427

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)
54345442
.fixItReplace(repr->getExclamationLoc(), "?");
54355443
}
54365444
}

test/Constraints/iuo.swift

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -179,43 +179,6 @@ class rdar37241550 {
179179
}
180180
}
181181

182-
class B {}
183-
class D : B {
184-
var i: Int!
185-
}
186-
187-
func coerceToIUO(d: D?) -> B {
188-
return d as B! // expected-warning {{using '!' here is deprecated and will be removed in a future release}}
189-
}
190-
191-
func forcedDowncastToOptional(b: B?) -> D? {
192-
return b as! D! // expected-warning {{using '!' here is deprecated and will be removed in a future release}}
193-
}
194-
195-
func forcedDowncastToObject(b: B?) -> D {
196-
return b as! D! // expected-warning {{using '!' here is deprecated and will be removed in a future release}}
197-
}
198-
199-
func forcedDowncastToObjectIUOMember(b: B?) -> Int {
200-
return (b as! D!).i // expected-warning {{using '!' here is deprecated and will be removed in a future release}}
201-
}
202-
203-
func forcedUnwrapViaForcedCast(b: B?) -> B {
204-
return b as! B! // expected-warning {{forced cast from 'B?' to 'B' only unwraps optionals; did you mean to use '!'?}}
205-
// expected-warning@-1 {{using '!' here is deprecated and will be removed in a future release}}
206-
}
207-
208-
func conditionalDowncastToOptional(b: B?) -> D? {
209-
return b as? D! // expected-warning {{using '!' here is deprecated and will be removed in a future release}}
210-
}
211-
212-
func conditionalDowncastToObject(b: B?) -> D {
213-
return b as? D! // expected-error {{value of optional type 'D?' must be unwrapped to a value of type 'D'}}
214-
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
215-
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
216-
// expected-warning@-3 {{using '!' here is deprecated and will be removed in a future release}}
217-
}
218-
219182
// https://github.com/apple/swift/issues/49536
220183
// Ensure that we select the overload that does *not* involve forcing an IUO.
221184
do {

0 commit comments

Comments
 (0)