Skip to content

Commit 27627fd

Browse files
committed
[Sema] NFC: Refactor AllowIUO policy into individual flags
Whether implicitly unwrapped optionals are allowed or not it is separable from the contexts in which they are allowed.
1 parent 7676855 commit 27627fd

File tree

7 files changed

+60
-34
lines changed

7 files changed

+60
-34
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,6 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) {
12481248
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
12491249
options |= TypeResolutionFlags::AllowUnboundGenerics;
12501250
options |= TypeResolutionFlags::InExpression;
1251-
options |= TypeResolutionFlags::AllowIUO;
12521251
bool hadParameterError = false;
12531252

12541253
GenericTypeToArchetypeResolver resolver(closure);

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,9 +1045,10 @@ static void validatePatternBindingEntry(TypeChecker &tc,
10451045
// In particular, it's /not/ correct to check the PBD's DeclContext because
10461046
// top-level variables in a script file are accessible from other files,
10471047
// even though the PBD is inside a TopLevelCodeDecl.
1048-
TypeResolutionOptions options = TypeResolutionFlags::InExpression;
1048+
TypeResolutionOptions options = TypeResolutionFlags::PatternBindingEntry;
1049+
options |= TypeResolutionFlags::InExpression;
1050+
options |= TypeResolutionFlags::Direct;
10491051

1050-
options |= TypeResolutionFlags::AllowIUO;
10511052
if (binding->getInit(entryNumber)) {
10521053
// If we have an initializer, we can also have unknown types.
10531054
options |= TypeResolutionFlags::AllowUnspecifiedTypes;

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,8 @@ static bool checkGenericFuncSignature(TypeChecker &tc,
531531
if (auto fn = dyn_cast<FuncDecl>(func)) {
532532
if (!fn->getBodyResultTypeLoc().isNull()) {
533533
// Check the result type of the function.
534-
TypeResolutionOptions options = TypeResolutionFlags::AllowIUO;
534+
TypeResolutionOptions options = TypeResolutionFlags::FunctionResult;
535+
options |= TypeResolutionFlags::Direct;
535536
if (fn->hasDynamicSelf())
536537
options |= TypeResolutionFlags::DynamicSelfResult;
537538

@@ -899,8 +900,10 @@ static bool checkGenericSubscriptSignature(TypeChecker &tc,
899900
&resolver);
900901

901902
// Check the element type.
903+
TypeResolutionOptions elementOptions = TypeResolutionFlags::Direct;
904+
elementOptions |= TypeResolutionFlags::FunctionResult;
902905
badType |= tc.validateType(subscript->getElementTypeLoc(), subscript,
903-
TypeResolutionFlags::AllowIUO, &resolver);
906+
elementOptions, &resolver);
904907

905908
// Infer requirements from it.
906909
if (genericParams && builder) {

lib/Sema/TypeCheckPattern.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -749,11 +749,12 @@ static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
749749
// If the element is a variadic parameter, resolve the parameter type as if
750750
// it were in non-parameter position, since we want functions to be
751751
// @escaping in this case.
752-
auto elementOptions = (options | (decl->isVariadic()
753-
? TypeResolutionFlags::VariadicFunctionInput
754-
: TypeResolutionFlags::FunctionInput));
755-
if (!decl->isVariadic())
756-
elementOptions |= TypeResolutionFlags::AllowIUO;
752+
options |= TypeResolutionFlags::Direct;
753+
if (decl->isVariadic()) {
754+
options |= TypeResolutionFlags::VariadicFunctionInput;
755+
} else {
756+
options |= TypeResolutionFlags::FunctionInput;
757+
}
757758

758759
bool hadError = false;
759760

@@ -762,8 +763,7 @@ static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
762763
// We might have a null typeLoc if this is a closure parameter list,
763764
// where parameters are allowed to elide their types.
764765
if (!TL.isNull()) {
765-
hadError |= TC.validateType(TL, DC,
766-
elementOptions, &resolver);
766+
hadError |= TC.validateType(TL, DC, options, &resolver);
767767
}
768768

769769
auto *TR = TL.getTypeRepr();
@@ -773,7 +773,7 @@ static bool validateParameterType(ParamDecl *decl, DeclContext *DC,
773773
// If this is declared with '!' indicating that it is an Optional
774774
// that we should implicitly unwrap if doing so is required to type
775775
// check, then add an attribute to the decl.
776-
if (elementOptions.contains(TypeResolutionFlags::AllowIUO) && TR &&
776+
if (!decl->isVariadic() && TR &&
777777
TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) {
778778
auto &C = DC->getASTContext();
779779
decl->getAttrs().add(

lib/Sema/TypeCheckType.cpp

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,6 @@ adjustOptionsForGenericArgs(TypeResolutionOptions options) {
319319
options -= TypeResolutionFlags::FunctionInput;
320320
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
321321
options -= TypeResolutionFlags::AllowUnavailableProtocol;
322-
options -= TypeResolutionFlags::AllowIUO;
323322

324323
return options;
325324
}
@@ -1515,7 +1514,8 @@ namespace {
15151514
Type resolveOptionalType(OptionalTypeRepr *repr,
15161515
TypeResolutionOptions options);
15171516
Type resolveImplicitlyUnwrappedOptionalType(ImplicitlyUnwrappedOptionalTypeRepr *repr,
1518-
TypeResolutionOptions options);
1517+
TypeResolutionOptions options,
1518+
bool isDirect);
15191519
Type resolveTupleType(TupleTypeRepr *repr,
15201520
TypeResolutionOptions options);
15211521
Type resolveCompositionType(CompositionTypeRepr *repr,
@@ -1567,14 +1567,21 @@ Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) {
15671567
// them.
15681568
if (!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
15691569
!isa<AttributedTypeRepr>(repr) && !isa<FunctionTypeRepr>(repr) &&
1570-
!isa<IdentTypeRepr>(repr)) {
1570+
!isa<IdentTypeRepr>(repr) &&
1571+
!isa<ImplicitlyUnwrappedOptionalTypeRepr>(repr)) {
15711572
options -= TypeResolutionFlags::FunctionInput;
15721573
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
15731574
}
15741575

15751576
if (Context.LangOpts.DisableAvailabilityChecking)
15761577
options |= TypeResolutionFlags::AllowUnavailable;
15771578

1579+
bool isDirect = false;
1580+
if ((options & TypeResolutionFlags::Direct) && !isa<SpecifierTypeRepr>(repr)){
1581+
isDirect = true;
1582+
options -= TypeResolutionFlags::Direct;
1583+
}
1584+
15781585
switch (repr->getKind()) {
15791586
case TypeReprKind::Error:
15801587
return ErrorType::get(Context);
@@ -1616,10 +1623,10 @@ Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) {
16161623
case TypeReprKind::Optional:
16171624
return resolveOptionalType(cast<OptionalTypeRepr>(repr), options);
16181625

1619-
case TypeReprKind::ImplicitlyUnwrappedOptional:
1620-
return resolveImplicitlyUnwrappedOptionalType(
1621-
cast<ImplicitlyUnwrappedOptionalTypeRepr>(repr),
1622-
options);
1626+
case TypeReprKind::ImplicitlyUnwrappedOptional: {
1627+
auto iuoRepr = cast<ImplicitlyUnwrappedOptionalTypeRepr>(repr);
1628+
return resolveImplicitlyUnwrappedOptionalType(iuoRepr, options, isDirect);
1629+
}
16231630

16241631
case TypeReprKind::Tuple:
16251632
return resolveTupleType(cast<TupleTypeRepr>(repr), options);
@@ -2100,9 +2107,10 @@ bool TypeResolver::resolveASTFunctionTypeParams(
21002107
Type TypeResolver::resolveASTFunctionType(FunctionTypeRepr *repr,
21012108
TypeResolutionOptions options,
21022109
FunctionType::ExtInfo extInfo) {
2110+
options -= TypeResolutionFlags::Direct;
21032111
options -= TypeResolutionFlags::FunctionInput;
2112+
options -= TypeResolutionFlags::FunctionResult;
21042113
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
2105-
options -= TypeResolutionFlags::AllowIUO;
21062114

21072115
SmallVector<AnyFunctionType::Param, 8> params;
21082116
if (resolveASTFunctionTypeParams(repr->getArgsTypeRepr(), options,
@@ -2597,9 +2605,11 @@ Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
25972605
return ErrorType::get(Context);
25982606
}
25992607

2600-
// Anything within the inout isn't a parameter anymore.
2601-
options -= TypeResolutionFlags::FunctionInput;
2602-
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
2608+
if (!isa<ImplicitlyUnwrappedOptionalTypeRepr>(repr->getBase())) {
2609+
// Anything within the inout isn't a parameter anymore.
2610+
options -= TypeResolutionFlags::FunctionInput;
2611+
options -= TypeResolutionFlags::TypeAliasUnderlyingType;
2612+
}
26032613

26042614
Type ty = resolveType(repr->getBase(), options);
26052615
if (!ty || ty->hasError()) return ty;
@@ -2682,9 +2692,15 @@ Type TypeResolver::resolveOptionalType(OptionalTypeRepr *repr,
26822692
}
26832693

26842694
Type TypeResolver::resolveImplicitlyUnwrappedOptionalType(
2685-
ImplicitlyUnwrappedOptionalTypeRepr *repr,
2686-
TypeResolutionOptions options) {
2687-
if (!options.contains(TypeResolutionFlags::AllowIUO)) {
2695+
ImplicitlyUnwrappedOptionalTypeRepr *repr,
2696+
TypeResolutionOptions options,
2697+
bool isDirect) {
2698+
TypeResolutionOptions allowIUO = TypeResolutionFlags::SILType;
2699+
allowIUO |= TypeResolutionFlags::FunctionInput;
2700+
allowIUO |= TypeResolutionFlags::FunctionResult;
2701+
allowIUO |= TypeResolutionFlags::PatternBindingEntry;
2702+
2703+
if (!isDirect || !(options & allowIUO)) {
26882704
// Prior to Swift 5, we allow 'as T!' and turn it into a disjunction.
26892705
if (TC.Context.isSwiftVersionAtLeast(5)) {
26902706
TC.diagnose(repr->getStartLoc(),
@@ -2724,11 +2740,9 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
27242740
SmallVector<TupleTypeElt, 8> elements;
27252741
elements.reserve(repr->getNumElements());
27262742

2727-
27282743
auto elementOptions = options;
27292744
if (repr->isParenType()) {
2730-
// We also want to disallow IUO within even a paren.
2731-
elementOptions -= TypeResolutionFlags::AllowIUO;
2745+
elementOptions -= TypeResolutionFlags::Direct;
27322746
} else {
27332747
elementOptions = withoutContext(elementOptions, true);
27342748
}

lib/Sema/TypeChecker.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,6 @@ bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
839839
options |= TypeResolutionFlags::AllowUnboundGenerics;
840840
if (isSILMode) {
841841
options |= TypeResolutionFlags::SILMode;
842-
options |= TypeResolutionFlags::AllowIUO;
843842
}
844843
if (isSILType)
845844
options |= TypeResolutionFlags::SILType;

lib/Sema/TypeChecker.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ enum class TypeResolutionFlags : unsigned {
479479

480480
/// Whether we are in the input type of a function, or under one level of
481481
/// tuple type. This is not set for multi-level tuple arguments.
482+
/// See also: TypeResolutionFlags::Direct
482483
FunctionInput = 1 << 5,
483484

484485
/// Whether this is a variadic function input.
@@ -543,8 +544,8 @@ enum class TypeResolutionFlags : unsigned {
543544
/// Whether we are checking the parameter list of a subscript.
544545
SubscriptParameters = 1 << 23,
545546

546-
/// Is it okay to resolve an IUO sigil ("!") here?
547-
AllowIUO = 1 << 24,
547+
/// Whether we are at the direct base of a type expression.
548+
Direct = 1 << 24,
548549

549550
/// Whether this type is being used in a cast or coercion expression.
550551
InCastOrCoercionExpression = 1 << 25,
@@ -557,6 +558,13 @@ enum class TypeResolutionFlags : unsigned {
557558

558559
/// Whether we should not produce diagnostics if the type is invalid.
559560
SilenceErrors = 1 << 28,
561+
562+
/// Whether we are in the result type of a function, including multi-level
563+
/// tuple return values. See also: TypeResolutionFlags::Direct
564+
FunctionResult = 1 << 29,
565+
566+
/// Whether this is a pattern binding entry.
567+
PatternBindingEntry = 1 << 30,
560568
};
561569

562570
/// Option set describing how type resolution should work.
@@ -565,12 +573,14 @@ using TypeResolutionOptions = OptionSet<TypeResolutionFlags>;
565573
/// Strip the contextual options from the given type resolution options.
566574
static inline TypeResolutionOptions
567575
withoutContext(TypeResolutionOptions options, bool preserveSIL = false) {
576+
options -= TypeResolutionFlags::Direct;
568577
options -= TypeResolutionFlags::FunctionInput;
569578
options -= TypeResolutionFlags::VariadicFunctionInput;
579+
options -= TypeResolutionFlags::FunctionResult;
570580
options -= TypeResolutionFlags::EnumCase;
571581
options -= TypeResolutionFlags::SubscriptParameters;
572582
options -= TypeResolutionFlags::ImmediateOptionalTypeArgument;
573-
options -= TypeResolutionFlags::AllowIUO;
583+
options -= TypeResolutionFlags::PatternBindingEntry;
574584
if (!preserveSIL) options -= TypeResolutionFlags::SILType;
575585
return options;
576586
}

0 commit comments

Comments
 (0)