Skip to content

Commit f088237

Browse files
committed
IUO: Generate Optional<T> rather than ImplicitlyUnwrappedOptional<T>.
Stop creating ImplicitlyUnwrappedOptional<T> so that we can remove it from the type system. Enable the code that generates disjunctions for Optional<T> and rewrites expressions based on the original declared type being 'T!'. Most of the changes supporting this were previously merged to master, but some things were difficult to merge to master without actually removing IUOs from the type system: - Dynamic member lookup and dynamic subscripting - Changes to ensure the bridging peephole still works Past commits have attempted to retain as much fidelity with how we were printing things as possible. There are some cases where we still are not printing things the same way: - In diagnostics we will print '?' rather than '!' - Some SourceKit and Code Completion output where we print a Type rather than Decl. Things like module printing via swift-ide-test attempt to print '!' any place that we now have Optional types that were declared as IUOs. There are some diagnostics regressions related to the fact that we can no longer "look through" IUOs. For the same reason some output and functionality changes in Code Completion. I have an idea of how we can restore these, and have opened a bug to investigate doing so. There are some small source compatibility breaks that result from this change: - Results of dynamic lookup that are themselves declared IUO can in rare circumstances be inferred differently. This shows up in test/ClangImporter/objc_parse.swift, where we have var optStr = obj.nsstringProperty Rather than inferring optStr to be 'String!?', we now infer this to be 'String??', which is in line with the expectations of SE-0054. The fact that we were only inferring the outermost IUO to be an Optional in Swift 4 was a result of the incomplete implementation of SE-0054 as opposed to a particular design. This should rarely cause problems since in the common-case of actually using the property rather than just assigning it to a value with inferred type, we will behave the same way. - Overloading functions with inout parameters strictly by a difference in optionality (i.e. Optional<T> vs. ImplicitlyUnwrappedOptional<T>) will result in an error rather than the diagnostic that was added in Swift 4.1. - Any place where '!' was being used where it wasn't supposed to be allowed by SE-0054 will now treat the '!' as if it were '?'. Swift 4.1 generates warnings for these saying that putting '!' in that location is deprecated. These locations include for example typealiases or any place where '!' is nested in another type like `Int!?` or `[Int!]`. This commit effectively means ImplicitlyUnwrappedOptional<T> is no longer part of the type system, although I haven't actually removed all of the code dealing with it yet. ImplicitlyUnwrappedOptional<T> is is dead, long live implicitly unwrapped Optional<T>! Resolves rdar://problem/33272674.
1 parent adfceb4 commit f088237

File tree

99 files changed

+650
-575
lines changed

Some content is hidden

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

99 files changed

+650
-575
lines changed

include/swift/AST/Expr.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ class alignas(8) Expr {
303303
NumVariadicArgs : 16
304304
);
305305

306+
SWIFT_INLINE_BITFIELD(ForceValueExpr, Expr, 1,
307+
ForcedIUO : 1
308+
);
309+
306310
SWIFT_INLINE_BITFIELD(InOutToPointerExpr, ImplicitConversionExpr, 1,
307311
IsNonAccessing : 1
308312
);
@@ -2507,9 +2511,11 @@ class ForceValueExpr : public Expr {
25072511
SourceLoc ExclaimLoc;
25082512

25092513
public:
2510-
ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc)
2514+
ForceValueExpr(Expr *subExpr, SourceLoc exclaimLoc, bool forcedIUO = false)
25112515
: Expr(ExprKind::ForceValue, /*Implicit=*/exclaimLoc.isInvalid(), Type()),
2512-
SubExpr(subExpr), ExclaimLoc(exclaimLoc) {}
2516+
SubExpr(subExpr), ExclaimLoc(exclaimLoc) {
2517+
Bits.ForceValueExpr.ForcedIUO = forcedIUO;
2518+
}
25132519

25142520
SourceRange getSourceRange() const {
25152521
if (ExclaimLoc.isInvalid())
@@ -2534,6 +2540,10 @@ class ForceValueExpr : public Expr {
25342540
Expr *getSubExpr() const { return SubExpr; }
25352541
void setSubExpr(Expr *expr) { SubExpr = expr; }
25362542

2543+
bool isForceOfImplicitlyUnwrappedOptional() const {
2544+
return Bits.ForceValueExpr.ForcedIUO;
2545+
}
2546+
25372547
static bool classof(const Expr *E) {
25382548
return E->getKind() == ExprKind::ForceValue;
25392549
}

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4114,7 +4114,9 @@ class ImplicitlyUnwrappedOptionalType : public UnarySyntaxSugarType {
41144114
ImplicitlyUnwrappedOptionalType(const ASTContext &ctx, Type base,
41154115
RecursiveTypeProperties properties)
41164116
: UnarySyntaxSugarType(TypeKind::ImplicitlyUnwrappedOptional, ctx, base,
4117-
properties) {}
4117+
properties) {
4118+
//llvm_unreachable("ImplicitlyUnwrappedOptionalType::ImplicitlyUnwrappedOptionalType");
4119+
}
41184120

41194121
public:
41204122
/// Return a uniqued optional type with the specified base type.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,7 +1792,7 @@ static ImportedType rectifySubscriptTypes(Type getterType, bool getterIsIUO,
17921792

17931793
// Create an optional of the object type that can be implicitly
17941794
// unwrapped which subsumes both behaviors.
1795-
return {ImplicitlyUnwrappedOptionalType::get(setterType), true};
1795+
return {OptionalType::get(setterType), true};
17961796
}
17971797

17981798
/// Add an AvailableAttr to the declaration for the given
@@ -4073,7 +4073,7 @@ namespace {
40734073
nullability = translateNullability(*typeNullability);
40744074
}
40754075
if (nullability != OTK_None && !errorConvention.hasValue()) {
4076-
resultTy = OptionalType::get(nullability, resultTy);
4076+
resultTy = OptionalType::get(resultTy);
40774077
isIUO = nullability == OTK_ImplicitlyUnwrappedOptional;
40784078
}
40794079

@@ -6115,8 +6115,8 @@ ConstructorDecl *SwiftDeclConverter::importConstructor(
61156115

61166116
// Rebuild the function type with the appropriate result type;
61176117
Type resultTy = selfTy;
6118-
if (failability)
6119-
resultTy = OptionalType::get(failability, resultTy);
6118+
if (failability != OTK_None)
6119+
resultTy = OptionalType::get(resultTy);
61206120

61216121
type = FunctionType::get(oldFnType->getInput(), resultTy,
61226122
oldFnType->getExtInfo());

lib/ClangImporter/ImportType.cpp

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,6 @@ namespace {
160160
return OptKind;
161161
}
162162

163-
/// Wrap a type in the Optional type appropriate to the import kind.
164-
static Type getOptionalType(Type payloadType, ImportTypeKind kind,
165-
OptionalTypeKind OptKind) {
166-
OptKind = getOptionalKind(kind, OptKind);
167-
168-
if (OptKind == OTK_None)
169-
return payloadType;
170-
171-
return OptionalType::get(OptKind, payloadType);
172-
}
173-
174163
class SwiftTypeConverter :
175164
public clang::TypeVisitor<SwiftTypeConverter, ImportResult>
176165
{
@@ -1277,7 +1266,7 @@ static ImportedType adjustTypeForConcreteImport(
12771266
auto resultTy = boundGenericTy->getGenericArgs().front();
12781267
if (OTK != OTK_None) {
12791268
assert(OTK != OTK_ImplicitlyUnwrappedOptional);
1280-
resultTy = OptionalType::get(OTK, resultTy);
1269+
resultTy = OptionalType::get(resultTy);
12811270
}
12821271

12831272
StringRef pointerName;
@@ -1398,14 +1387,6 @@ static ImportedType adjustTypeForConcreteImport(
13981387
return {importedType, isIUO};
13991388
}
14001389

1401-
static Type adjustOptionality(ImportedType importedType) {
1402-
if (!importedType.isImplicitlyUnwrapped())
1403-
return importedType.getType();
1404-
1405-
return ImplicitlyUnwrappedOptionalType::get(
1406-
importedType.getType()->getOptionalObjectType());
1407-
}
1408-
14091390
ImportedType ClangImporter::Implementation::importType(
14101391
clang::QualType type, ImportTypeKind importKind, bool allowNSUIntegerAsInt,
14111392
Bridgeability bridging, OptionalTypeKind optionality,
@@ -1460,10 +1441,7 @@ ImportedType ClangImporter::Implementation::importType(
14601441
assert(!adjustedType ||
14611442
!adjustedType.getType()->getImplicitlyUnwrappedOptionalObjectType());
14621443

1463-
// Make an IUO type based on isIUO. This will be removed when IUOs
1464-
// are removed from the type system.
1465-
return {adjustOptionality(adjustedType),
1466-
adjustedType.isImplicitlyUnwrapped()};
1444+
return adjustedType;
14671445
}
14681446

14691447
Type ClangImporter::Implementation::importTypeIgnoreIUO(
@@ -1474,12 +1452,8 @@ Type ClangImporter::Implementation::importTypeIgnoreIUO(
14741452
auto importedType = importType(type, importKind, allowNSUIntegerAsInt,
14751453
bridging, optionality, resugarNSErrorPointer);
14761454

1477-
// We allow IUO types to be returned at the moment. At some point we
1478-
// will never generate them and this can be removed.
1479-
assert(!importedType || importedType.isImplicitlyUnwrapped() ==
1480-
!importedType.getType()
1481-
->getImplicitlyUnwrappedOptionalObjectType()
1482-
.isNull());
1455+
assert(!importedType ||
1456+
!importedType.getType()->getImplicitlyUnwrappedOptionalObjectType());
14831457

14841458
return importedType.getType();
14851459
}
@@ -1558,7 +1532,7 @@ static Type applyNoEscape(Type type) {
15581532
// Recurse into optional types.
15591533
OptionalTypeKind optKind;
15601534
if (Type objectType = type->getAnyOptionalObjectType(optKind)) {
1561-
return OptionalType::get(optKind, applyNoEscape(objectType));
1535+
return OptionalType::get(applyNoEscape(objectType));
15621536
}
15631537

15641538
// Apply @noescape to function types.
@@ -2013,7 +1987,7 @@ ImportedType ClangImporter::Implementation::importMethodType(
20131987
if (nonOptionalTy->isAnyClassReferenceType()) {
20141988
swiftResultTy = getUnmanagedType(*this, nonOptionalTy);
20151989
if (OptionalityOfReturn != OTK_None)
2016-
swiftResultTy = OptionalType::get(OptionalityOfReturn, swiftResultTy);
1990+
swiftResultTy = OptionalType::get(swiftResultTy);
20171991
}
20181992
}
20191993

@@ -2085,11 +2059,14 @@ ImportedType ClangImporter::Implementation::importMethodType(
20852059
bool paramIsIUO;
20862060
if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
20872061
paramTy->isObjCIdType()) {
2088-
swiftParamTy = getOptionalType(getNSCopyingType(),
2089-
ImportTypeKind::Parameter,
2090-
optionalityOfParam);
20912062
auto optKind =
20922063
getOptionalKind(ImportTypeKind::Parameter, optionalityOfParam);
2064+
2065+
if (optKind == OTK_None)
2066+
swiftParamTy = getNSCopyingType();
2067+
else
2068+
swiftParamTy = OptionalType::get(getNSCopyingType());
2069+
20932070
paramIsIUO = optKind == OTK_ImplicitlyUnwrappedOptional;
20942071
} else {
20952072
ImportTypeKind importKind = ImportTypeKind::Parameter;

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,9 +1944,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19441944
suffix = "!";
19451945
}
19461946

1947-
// FIXME: This goes away when IUOs are removed from the type system.
1948-
assert(T->getReferenceStorageReferent()->getImplicitlyUnwrappedOptionalObjectType());
1949-
19501947
Type ObjectType =
19511948
T->getReferenceStorageReferent()->getAnyOptionalObjectType();
19521949

@@ -3188,6 +3185,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
31883185
}
31893186
}
31903187
} else if (Type Unwrapped = ExprType->getImplicitlyUnwrappedOptionalObjectType()) {
3188+
// FIXME: This can go away when IUOs have been removed from the type
3189+
// system.
31913190
lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
31923191
TypeResolver.get(),
31933192
IncludeInstanceMembers);

lib/SILGen/SILGenConvert.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,8 +1153,7 @@ Optional<Conversion> Conversion::adjustForInitialForceValue() const {
11531153

11541154
case BridgeToObjC: {
11551155
auto sourceOptType =
1156-
ImplicitlyUnwrappedOptionalType::get(getBridgingSourceType())
1157-
->getCanonicalType();
1156+
OptionalType::get(getBridgingSourceType())->getCanonicalType();
11581157
return Conversion::getBridging(ForceAndBridgeToObjC,
11591158
sourceOptType,
11601159
getBridgingResultType(),

lib/SILGen/SILGenExpr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5066,8 +5066,7 @@ RValue RValueEmitter::emitForceValue(ForceValueExpr *loc, Expr *E,
50665066
// If this is an implicit force of an ImplicitlyUnwrappedOptional,
50675067
// and we're emitting into an unbridging conversion, try adjusting the
50685068
// context.
5069-
if (loc->isImplicit() &&
5070-
E->getType()->getImplicitlyUnwrappedOptionalObjectType()) {
5069+
if (loc->isImplicit() && loc->isForceOfImplicitlyUnwrappedOptional()) {
50715070
if (auto conv = C.getAsConversion()) {
50725071
if (auto adjusted = conv->getConversion().adjustForInitialForceValue()) {
50735072
auto value =

lib/SILGen/SILGenPoly.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,10 @@ ManagedValue Transform::transform(ManagedValue v,
392392
});
393393
}
394394

395-
// If the value is IUO, but the desired formal type isn't optional, force it.
396-
if (inputOTK == OTK_ImplicitlyUnwrappedOptional
397-
&& outputOTK == OTK_None) {
395+
// If the value is an optional, but the desired formal type isn't an
396+
// optional or Any, force it.
397+
if (inputOTK != OTK_None && outputOTK == OTK_None
398+
&& !outputSubstType->isExistentialType()) {
398399
v = SGF.emitCheckedGetOptionalValueFrom(Loc, v,
399400
SGF.getTypeLowering(v.getType()),
400401
SGFContext());

0 commit comments

Comments
 (0)