Skip to content

Commit adba153

Browse files
authored
Merge pull request swiftlang#20211 from Azoy/sr8811-warning
[Sema] Uninhabited stored property downgrade to warning
2 parents a5a8135 + a1bcbe8 commit adba153

File tree

10 files changed

+37
-72
lines changed

10 files changed

+37
-72
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,15 +1386,6 @@ ERROR(pattern_binds_no_variables,none,
13861386
"variables",
13871387
(unsigned))
13881388

1389-
ERROR(pattern_no_uninhabited_type,none,
1390-
"%select{%select{variable|constant}0|stored property}1 %2 cannot have "
1391-
"enum type %3 with no cases",
1392-
(bool, bool, Identifier, Type))
1393-
ERROR(pattern_no_uninhabited_tuple_type,none,
1394-
"%select{%select{variable|constant}0|stored property}1 %2 cannot have "
1395-
"tuple type %3 containing enum with no cases",
1396-
(bool, bool, Identifier, Type))
1397-
13981389
ERROR(nscoding_unstable_mangled_name,none,
13991390
"%select{private|fileprivate|nested|local}0 class %1 has an "
14001391
"unstable name when archiving via 'NSCoding'",
@@ -3327,6 +3318,12 @@ ERROR(ambiguous_enum_pattern_type,none,
33273318
WARNING(type_inferred_to_undesirable_type,none,
33283319
"%select{variable|constant}2 %0 inferred to have type %1, "
33293320
"which may be unexpected", (Identifier, Type, bool))
3321+
WARNING(type_inferred_to_uninhabited_type,none,
3322+
"%select{variable|constant}2 %0 inferred to have type %1, "
3323+
"which is an enum with no cases", (Identifier, Type, bool))
3324+
WARNING(type_inferred_to_uninhabited_tuple_type,none,
3325+
"%select{variable|constant}2 %0 inferred to have type %1, "
3326+
"which contains an enum with no cases", (Identifier, Type, bool))
33303327
NOTE(add_explicit_type_annotation_to_silence,none,
33313328
"add an explicit type annotation to silence this warning", ())
33323329

lib/Sema/TypeCheckDecl.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2541,25 +2541,6 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
25412541
}
25422542
}
25432543

2544-
// Reject variable if it is a stored property with an uninhabited type
2545-
if (VD->hasStorage() &&
2546-
VD->getInterfaceType()->isStructurallyUninhabited()) {
2547-
auto uninhabitedTypeDiag = diag::pattern_no_uninhabited_type;
2548-
2549-
if (VD->getInterfaceType()->is<TupleType>()) {
2550-
uninhabitedTypeDiag = diag::pattern_no_uninhabited_tuple_type;
2551-
} else {
2552-
assert((VD->getInterfaceType()->is<EnumType>() ||
2553-
VD->getInterfaceType()->is<BoundGenericEnumType>()) &&
2554-
"unknown structurally uninhabited type");
2555-
}
2556-
2557-
TC.diagnose(VD->getLoc(), uninhabitedTypeDiag, VD->isLet(),
2558-
VD->isInstanceMember(), VD->getName(),
2559-
VD->getInterfaceType());
2560-
VD->markInvalid();
2561-
}
2562-
25632544
if (!checkOverrides(VD)) {
25642545
// If a property has an override attribute but does not override
25652546
// anything, complain.

lib/Sema/TypeCheckPattern.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,14 +1091,16 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
10911091
var->getTypeLoc().setType(var->getType());
10921092

10931093
// If we are inferring a variable to have type AnyObject.Type,
1094-
// "()", or optional thereof, emit a diagnostic. In the first 2 cases, the
1095-
// coder probably forgot a cast and expected a concrete type. In the later
1096-
// case, they probably didn't mean to bind to a variable, or there is some
1097-
// other bug. We always tell them that they can silence the warning with an
1098-
// explicit type annotation (and provide a fixit) as a note.
1094+
// "()", an uninhabited type, or optional thereof, emit a diagnostic.
1095+
// In the first 2 cases, the coder probably forgot a cast and expected a
1096+
// concrete type. In the later case, they probably didn't mean to bind to
1097+
// a variable, or there is some other bug. We always tell them that they
1098+
// can silence the warning with an explicit type annotation
1099+
// (and provide a fixit) as a note.
10991100
Type diagTy = type->getOptionalObjectType();
11001101
if (!diagTy) diagTy = type;
11011102

1103+
auto diag = diag::type_inferred_to_undesirable_type;
11021104
bool shouldRequireType = false;
11031105
if (NP->isImplicit()) {
11041106
// If the whole pattern is implicit, the user didn't write it.
@@ -1108,14 +1110,24 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
11081110
} else if (auto MTT = diagTy->getAs<AnyMetatypeType>()) {
11091111
if (MTT->getInstanceType()->isAnyObject())
11101112
shouldRequireType = true;
1113+
} else if (diagTy->isStructurallyUninhabited()) {
1114+
shouldRequireType = true;
1115+
diag = diag::type_inferred_to_uninhabited_type;
1116+
1117+
if (diagTy->is<TupleType>()) {
1118+
diag = diag::type_inferred_to_uninhabited_tuple_type;
1119+
} else {
1120+
assert((diagTy->is<EnumType>() || diagTy->is<BoundGenericEnumType>()) &&
1121+
"unknown structurally uninhabited type");
1122+
}
11111123
}
11121124

11131125
if (shouldRequireType &&
11141126
!options.is(TypeResolverContext::ForEachStmt) &&
11151127
!options.is(TypeResolverContext::EditorPlaceholderExpr) &&
11161128
!(options & TypeResolutionFlags::FromNonInferredPattern)) {
1117-
diagnose(NP->getLoc(), diag::type_inferred_to_undesirable_type,
1118-
NP->getDecl()->getName(), type, NP->getDecl()->isLet());
1129+
diagnose(NP->getLoc(), diag, NP->getDecl()->getName(), type,
1130+
NP->getDecl()->isLet());
11191131
diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence);
11201132
}
11211133

test/IRGen/generic_enums.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,4 @@ struct Bar<A1, A2> {
55
var b: Foo<A1>
66
}
77

8-
enum Foo<A>{
9-
case bar
10-
}
8+
enum Foo<A> {}

test/Reflection/Inputs/TypeLowering.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,8 @@ public struct MetatypeStruct {
168168
public let abstractMetatype: MetadataHolder<BasicStruct.Type, BasicStruct>
169169
}
170170

171-
// We don't allow stored properties to have uninhabited types now, but make a
172-
// wrapper over one to continue testing this
173171
public enum EmptyEnum {}
174172

175-
public struct EmptyEnumWrapper<T> {
176-
public var value: T
177-
}
178-
179173
public enum NoPayloadEnum {
180174
case A
181175
case B
@@ -224,7 +218,7 @@ public enum MultiPayloadGenericDynamic<T, U> {
224218
}
225219

226220
public struct EnumStruct {
227-
public let empty: EmptyEnumWrapper<EmptyEnum>
221+
public let empty: EmptyEnum
228222
public let noPayload: NoPayloadEnum
229223
public let sillyNoPayload: SillyNoPayloadEnum
230224
public let singleton: SingletonEnum

test/Reflection/typeref_lowering.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,9 +1032,7 @@
10321032
// CHECK-64: (struct TypeLowering.EnumStruct)
10331033
// CHECK-64-NEXT: (struct size=81 alignment=8 stride=88 num_extra_inhabitants=[[PTR_XI]] bitwise_takable=1
10341034
// CHECK-64-NEXT: (field name=empty offset=0
1035-
// CHECK-64-NEXT: (struct size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1
1036-
// CHECK-64-NEXT: (field name=value offset=0
1037-
// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))))
1035+
// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
10381036
// CHECK-64-NEXT: (field name=noPayload offset=0
10391037
// CHECK-64-NEXT: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
10401038
// CHECK-64-NEXT: (field name=sillyNoPayload offset=1

test/attr/attr_noreturn.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ func noReturn3(_: Int)
3434
// expected-error@-2 {{'@noreturn' has been removed; functions that never return should have a return type of 'Never' instead}}{{1-11=}}{{53-56=Never}}
3535

3636
// Test that error recovery gives us the 'Never' return type
37-
let x: Never = noReturn1(0)
38-
// expected-error@-1 {{constant 'x' cannot have enum type 'Never' with no cases}}
37+
let x: Never = noReturn1(0) // No error
3938

4039
// @noreturn in function type declarations
4140
let valueNoReturn: @noreturn () -> ()

test/attr/attr_objc.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -941,12 +941,11 @@ class infer_instanceVar1 {
941941
// expected-note@-2 {{Swift structs cannot be represented in Objective-C}}
942942

943943
var var_PlainEnum: PlainEnum
944-
// expected-error@-1 {{stored property 'var_PlainEnum' cannot have enum type 'PlainEnum' with no cases}}
944+
// CHECK-LABEL: {{^}} var var_PlainEnum: PlainEnum
945945

946946
@objc var var_PlainEnum_: PlainEnum
947947
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
948948
// expected-note@-2 {{non-'@objc' enums cannot be represented in Objective-C}}
949-
// expected-error@-3 {{stored property 'var_PlainEnum_' cannot have enum type 'PlainEnum' with no cases}}
950949

951950
var var_PlainProtocol: PlainProtocol
952951
// CHECK-LABEL: {{^}} var var_PlainProtocol: PlainProtocol
@@ -1272,7 +1271,6 @@ class infer_instanceVar1 {
12721271
// expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'PlainStruct'}}
12731272
unowned var var_Unowned_bad3: PlainEnum
12741273
// expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'PlainEnum'}}
1275-
// expected-error@-2 {{stored property 'var_Unowned_bad3' cannot have enum type 'PlainEnum' with no cases}}
12761274
unowned var var_Unowned_bad4: String
12771275
// expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'String'}}
12781276
// CHECK-NOT: @objc{{.*}}Unowned_fail

test/decl/var/properties.swift

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,24 +1268,12 @@ class WeakFixItTest {
12681268
weak var bar : WFI_P1 & WFI_P2
12691269
}
12701270

1271-
// SR-8811
1272-
// Stored properties cannot have uninhabited types
1271+
// SR-8811 (Warning)
12731272

1274-
struct SR8811 {
1275-
var x: Never // expected-error {{stored property 'x' cannot have enum type 'Never' with no cases}}
1276-
1277-
var y: (Int, Never, Bool) // expected-error {{stored property 'y' cannot have tuple type '(Int, Never, Bool)' containing enum with no cases}}
1278-
}
1279-
1280-
let sr8811x: Never // expected-error {{constant 'sr8811x' cannot have enum type 'Never' with no cases}}
1273+
let sr8811a = fatalError() // expected-warning {{constant 'sr8811a' inferred to have type 'Never', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}}
12811274

1282-
var sr8811y: (Int, Never) // expected-error {{variable 'sr8811y' cannot have tuple type '(Int, Never)' containing enum with no cases}}
1283-
1284-
// Ok
1285-
var sr8811z: Never {
1286-
return fatalError()
1287-
}
1275+
let sr8811b: Never = fatalError() // Ok
12881276

1289-
enum SR8811EmptyGenericEnum<A> {}
1277+
let sr8811c = (16, fatalError()) // expected-warning {{constant 'sr8811c' inferred to have type '(Int, Never)', which contains an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}}
12901278

1291-
let sr8811z: SR8811EmptyGenericEnum<Int> // expected-error {{constant 'sr8811z' cannot have enum type 'SR8811EmptyGenericEnum<Int>' with no cases}}
1279+
let sr8811d: (Int, Never) = (16, fatalError()) // Ok

test/expr/expressions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,9 @@ func conversionTest(_ a: inout Double, b: inout Int) {
584584
var pi_f3 = float.init(getPi()) // expected-error {{ambiguous use of 'init(_:)'}}
585585
var pi_f4 = float.init(pi_f)
586586

587-
var e = Empty(f) // expected-error {{variable 'e' cannot have enum type 'Empty' with no cases}}
587+
var e = Empty(f) // expected-warning {{variable 'e' inferred to have type 'Empty', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}}
588588
var e2 = Empty(d) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Float'}}
589-
var e3 = Empty(Float(d)) // expected-error {{variable 'e3' cannot have enum type 'Empty' with no cases}}
589+
var e3 = Empty(Float(d)) // expected-warning {{variable 'e3' inferred to have type 'Empty', which is an enum with no cases}} expected-note {{add an explicit type annotation to silence this warning}}
590590
}
591591

592592
struct Rule { // expected-note {{'init(target:dependencies:)' declared here}}

0 commit comments

Comments
 (0)