Skip to content

Commit af0c7bd

Browse files
committed
Initial implementation of SE-0054 "Abolish IUO Type" (#2322)
This is a squash of the following commits: * [SE-0054] Import function pointer arg, return types, typedefs as optional IUOs are only allowed on function decl arguments and return types, so don't import typedefs or function pointer args or return types as IUO. * [SE-0054] Only allow IUOs in function arg and result type. When validating a TypeRepr, raise a diagnostic if an IUO is found anywhere other thn the top level or as a function parameter or return tpye. * [SE-0054] Disable inference of IUOs by default When considering a constraint of the form '$T1 is convertible to T!', generate potential bindings 'T' and 'T?' for $T1, but not 'T!'. This prevents variables without explicit type information from ending up with IUO type. It also prevents implicit instantiation of functions and types with IUO type arguments. * [SE-0054] Remove the -disable-infer-iuos flag. * Add nonnull annotations to ObjectiveCTests.h in benchmark suite.
1 parent 2ef514e commit af0c7bd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+178
-320
lines changed

benchmark/utils/ObjectiveCTests/ObjectiveCTests.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#import <Foundation/Foundation.h>
1414

15+
NS_ASSUME_NONNULL_BEGIN
16+
1517
@interface BridgeTester : NSObject {
1618
NSString *myString;
1719
NSArray<NSString *> *myArrayOfStrings;
@@ -24,3 +26,5 @@
2426
- (NSArray<NSString *> *)testToArrayOfStrings;
2527

2628
@end
29+
30+
NS_ASSUME_NONNULL_END

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,10 @@ NOTE(override_unnecessary_IUO_use_strict,none,
14611461
NOTE(override_unnecessary_IUO_silence,none,
14621462
"add parentheses to silence this warning", ())
14631463

1464+
ERROR(iuo_in_illegal_position,none,
1465+
"implicitly unwrapped optionals are only allowed at top level and as "
1466+
"function results", ())
1467+
14641468
ERROR(override_mutable_covariant_property,none,
14651469
"cannot override mutable property %0 of type %1 with covariant type %2",
14661470
(Identifier, Type, Type))

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,6 @@ namespace swift {
157157
/// Enable the Swift 3 migration via Fix-Its.
158158
bool Swift3Migration = false;
159159

160-
/// Allow IUO types to be inferred for otherwise untyped variables.
161-
bool InferIUOs = true;
162-
163160
/// Sets the target we are building for and updates platform conditions
164161
/// to match.
165162
///

include/swift/Option/FrontendOptions.td

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,6 @@ def swift3_migration :
244244
Flag<["-"], "swift3-migration">,
245245
HelpText<"Enable Fix-It based migration aids for Swift 3">;
246246

247-
def disable_infer_iuos :
248-
Flag<["-"], "disable-infer-iuos">,
249-
HelpText<"Disable inferring IUO type for otherwise unconstrained variables">;
250-
251247
def warn_omit_needless_words :
252248
Flag<["-"], "Womit-needless-words">,
253249
HelpText<"Warn about needless words in names">;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,13 +1325,15 @@ namespace {
13251325
auto storedUnderlyingType = Impl.importType(
13261326
Decl->getUnderlyingType(), ImportTypeKind::Value,
13271327
isInSystemModule(DC),
1328-
Decl->getUnderlyingType()->isBlockPointerType());
1328+
Decl->getUnderlyingType()->isBlockPointerType(),
1329+
OTK_Optional);
13291330

13301331
// Find a bridged type, which may be different
13311332
auto computedPropertyUnderlyingType = Impl.importType(
13321333
Decl->getUnderlyingType(), ImportTypeKind::Property,
13331334
isInSystemModule(DC),
1334-
Decl->getUnderlyingType()->isBlockPointerType());
1335+
Decl->getUnderlyingType()->isBlockPointerType(),
1336+
OTK_Optional);
13351337

13361338
if (storedUnderlyingType.getCanonicalTypeOrNull() ==
13371339
computedPropertyUnderlyingType.getCanonicalTypeOrNull()) {
@@ -1365,7 +1367,8 @@ namespace {
13651367
SwiftType = Impl.importType(ClangType,
13661368
ImportTypeKind::Typedef,
13671369
isInSystemModule(DC),
1368-
ClangType->isBlockPointerType());
1370+
ClangType->isBlockPointerType(),
1371+
OTK_Optional);
13691372
}
13701373

13711374
if (!SwiftType)

lib/ClangImporter/ImportType.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,8 @@ namespace {
456456
auto resultTy = Impl.importType(type->getReturnType(),
457457
ImportTypeKind::Result,
458458
AllowNSUIntegerAsInt,
459-
CanFullyBridgeTypes);
459+
CanFullyBridgeTypes,
460+
OTK_Optional);
460461
if (!resultTy)
461462
return Type();
462463

@@ -466,7 +467,8 @@ namespace {
466467
param != paramEnd; ++param) {
467468
auto swiftParamTy = Impl.importType(*param, ImportTypeKind::Parameter,
468469
AllowNSUIntegerAsInt,
469-
CanFullyBridgeTypes);
470+
CanFullyBridgeTypes,
471+
OTK_Optional);
470472
if (!swiftParamTy)
471473
return Type();
472474

@@ -489,7 +491,8 @@ namespace {
489491
auto resultTy = Impl.importType(type->getReturnType(),
490492
ImportTypeKind::Result,
491493
AllowNSUIntegerAsInt,
492-
CanFullyBridgeTypes);
494+
CanFullyBridgeTypes,
495+
OTK_Optional);
493496
if (!resultTy)
494497
return Type();
495498

lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -760,9 +760,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
760760
Opts.WarnOmitNeedlessWords = Args.hasArg(OPT_warn_omit_needless_words);
761761
Opts.StripNSPrefix |= Args.hasArg(OPT_enable_strip_ns_prefix);
762762
Opts.InferImportAsMember |= Args.hasArg(OPT_enable_infer_import_as_member);
763-
if (Args.hasArg(OPT_disable_infer_iuos)) {
764-
Opts.InferIUOs = false;
765-
}
766763

767764
Opts.EnableThrowWithoutTry |= Args.hasArg(OPT_enable_throw_without_try);
768765

lib/Sema/CSSolver.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -875,18 +875,15 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
875875
}
876876
}
877877

878+
// Don't deduce IUO types.
878879
Type alternateType;
879-
ASTContext &ctx = cs.getTypeChecker().Context;
880-
if (!ctx.LangOpts.InferIUOs) {
881-
// Don't deduce IUO types.
882-
if (kind == AllowedBindingKind::Supertypes &&
883-
constraint->getKind() >= ConstraintKind::Conversion &&
884-
constraint->getKind() <= ConstraintKind::OperatorArgumentConversion) {
885-
if (auto objectType =
886-
cs.lookThroughImplicitlyUnwrappedOptionalType(type)) {
887-
type = OptionalType::get(objectType);
888-
alternateType = objectType;
889-
}
880+
if (kind == AllowedBindingKind::Supertypes &&
881+
constraint->getKind() >= ConstraintKind::Conversion &&
882+
constraint->getKind() <= ConstraintKind::OperatorArgumentConversion) {
883+
if (auto objectType =
884+
cs.lookThroughImplicitlyUnwrappedOptionalType(type)) {
885+
type = OptionalType::get(objectType);
886+
alternateType = objectType;
890887
}
891888
}
892889

lib/Sema/TypeCheckType.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,64 @@ Type TypeChecker::resolveIdentifierType(
13401340
return result;
13411341
}
13421342

1343+
// Returns true if any illegal IUOs were found. If inference of IUO type is disabled, IUOs may only be specified in the following positions:
1344+
// * outermost type
1345+
// * function param
1346+
// * function return type
1347+
static bool checkForIllegalIUOs(TypeChecker &TC, TypeRepr *Repr,
1348+
TypeResolutionOptions Options) {
1349+
class IllegalIUOWalker : public ASTWalker {
1350+
TypeChecker &TC;
1351+
SmallVector<bool, 4> IUOsAllowed;
1352+
bool FoundIllegalIUO = false;
1353+
1354+
public:
1355+
IllegalIUOWalker(TypeChecker &TC, bool IsGenericParameter)
1356+
: TC(TC)
1357+
, IUOsAllowed{!IsGenericParameter} {}
1358+
1359+
bool walkToTypeReprPre(TypeRepr *T) {
1360+
bool iuoAllowedHere = IUOsAllowed.back();
1361+
1362+
// Raise a diagnostic if we run into a prohibited IUO.
1363+
if (!iuoAllowedHere) {
1364+
if (auto *iuoTypeRepr =
1365+
dyn_cast<ImplicitlyUnwrappedOptionalTypeRepr>(T)) {
1366+
TC.diagnose(iuoTypeRepr->getStartLoc(), diag::iuo_in_illegal_position)
1367+
.fixItReplace(iuoTypeRepr->getExclamationLoc(), "?");
1368+
FoundIllegalIUO = true;
1369+
}
1370+
}
1371+
1372+
bool childIUOsAllowed = false;
1373+
if (iuoAllowedHere) {
1374+
if (auto *tupleTypeRepr = dyn_cast<TupleTypeRepr>(T)) {
1375+
if (tupleTypeRepr->isParenType()) {
1376+
childIUOsAllowed = true;
1377+
}
1378+
} else if (isa<FunctionTypeRepr>(T)) {
1379+
childIUOsAllowed = true;
1380+
} else if (isa<AttributedTypeRepr>(T) || isa<InOutTypeRepr>(T)) {
1381+
childIUOsAllowed = true;
1382+
}
1383+
}
1384+
IUOsAllowed.push_back(childIUOsAllowed);
1385+
return true;
1386+
}
1387+
1388+
bool walkToTypeReprPost(TypeRepr *T) {
1389+
IUOsAllowed.pop_back();
1390+
return true;
1391+
}
1392+
1393+
bool getFoundIllegalIUO() const { return FoundIllegalIUO; }
1394+
};
1395+
1396+
IllegalIUOWalker Walker(TC, Options.contains(TR_GenericSignature));
1397+
Repr->walk(Walker);
1398+
return Walker.getFoundIllegalIUO();
1399+
}
1400+
13431401
bool TypeChecker::validateType(TypeLoc &Loc, DeclContext *DC,
13441402
TypeResolutionOptions options,
13451403
GenericTypeResolver *resolver,
@@ -1351,6 +1409,9 @@ bool TypeChecker::validateType(TypeLoc &Loc, DeclContext *DC,
13511409
return Loc.isError();
13521410

13531411
if (Loc.getType().isNull()) {
1412+
// Raise error if we parse an IUO type in an illegal position.
1413+
checkForIllegalIUOs(*this, Loc.getTypeRepr(), options);
1414+
13541415
auto type = resolveType(Loc.getTypeRepr(), DC, options, resolver,
13551416
unsatisfiedDependency);
13561417
if (!type) {

stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ func _printDebuggingAdvice(_ fullTestName: String) {
599599
var invocation = [Process.arguments[0]]
600600
let interpreter = getenv("SWIFT_INTERPRETER")
601601
if interpreter != nil {
602-
if let interpreterCmd = String(validatingUTF8: interpreter) {
602+
if let interpreterCmd = String(validatingUTF8: interpreter!) {
603603
invocation.insert(interpreterCmd, at: 0)
604604
}
605605
}

0 commit comments

Comments
 (0)