diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 9aec42cba61bf..d774aae611c8e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1371,15 +1371,6 @@ ERROR(pattern_binds_no_variables,none, "variables", (unsigned)) -ERROR(pattern_no_uninhabited_type,none, - "%select{%select{variable|constant}0|stored property}1 %2 cannot have " - "enum type %3 with no cases", - (bool, bool, Identifier, Type)) -ERROR(pattern_no_uninhabited_tuple_type,none, - "%select{%select{variable|constant}0|stored property}1 %2 cannot have " - "tuple type %3 containing enum with no cases", - (bool, bool, Identifier, Type)) - ERROR(nscoding_unstable_mangled_name,none, "%select{private|fileprivate|nested|local}0 class %1 has an " "unstable name when archiving via 'NSCoding'", @@ -3312,6 +3303,12 @@ ERROR(ambiguous_enum_pattern_type,none, WARNING(type_inferred_to_undesirable_type,none, "%select{variable|constant}2 %0 inferred to have type %1, " "which may be unexpected", (Identifier, Type, bool)) +WARNING(type_inferred_to_uninhabited_type,none, + "%select{variable|constant}2 %0 inferred to have type %1, " + "which is an enum with no cases", (Identifier, Type, bool)) +WARNING(type_inferred_to_uninhabited_tuple_type,none, + "%select{variable|constant}2 %0 inferred to have type %1, " + "which contains an enum with no cases", (Identifier, Type, bool)) NOTE(add_explicit_type_annotation_to_silence,none, "add an explicit type annotation to silence this warning", ()) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 45b30586f23fe..d2ed1a29085a9 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2541,25 +2541,6 @@ class DeclChecker : public DeclVisitor { } } - // Reject variable if it is a stored property with an uninhabited type - if (VD->hasStorage() && - VD->getInterfaceType()->isStructurallyUninhabited()) { - auto uninhabitedTypeDiag = diag::pattern_no_uninhabited_type; - - if (VD->getInterfaceType()->is()) { - uninhabitedTypeDiag = diag::pattern_no_uninhabited_tuple_type; - } else { - assert((VD->getInterfaceType()->is() || - VD->getInterfaceType()->is()) && - "unknown structurally uninhabited type"); - } - - TC.diagnose(VD->getLoc(), uninhabitedTypeDiag, VD->isLet(), - VD->isInstanceMember(), VD->getName(), - VD->getInterfaceType()); - VD->markInvalid(); - } - if (!checkOverrides(VD)) { // If a property has an override attribute but does not override // anything, complain. diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index c76ad25f3b906..cfddd4d13bf57 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1091,14 +1091,16 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, var->getTypeLoc().setType(var->getType()); // If we are inferring a variable to have type AnyObject.Type, - // "()", or optional thereof, emit a diagnostic. In the first 2 cases, the - // coder probably forgot a cast and expected a concrete type. In the later - // case, they probably didn't mean to bind to a variable, or there is some - // other bug. We always tell them that they can silence the warning with an - // explicit type annotation (and provide a fixit) as a note. + // "()", an uninhabited type, or optional thereof, emit a diagnostic. + // In the first 2 cases, the coder probably forgot a cast and expected a + // concrete type. In the later case, they probably didn't mean to bind to + // a variable, or there is some other bug. We always tell them that they + // can silence the warning with an explicit type annotation + // (and provide a fixit) as a note. Type diagTy = type->getOptionalObjectType(); if (!diagTy) diagTy = type; + auto diag = diag::type_inferred_to_undesirable_type; bool shouldRequireType = false; if (NP->isImplicit()) { // If the whole pattern is implicit, the user didn't write it. @@ -1108,14 +1110,24 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, } else if (auto MTT = diagTy->getAs()) { if (MTT->getInstanceType()->isAnyObject()) shouldRequireType = true; + } else if (diagTy->isStructurallyUninhabited()) { + shouldRequireType = true; + diag = diag::type_inferred_to_uninhabited_type; + + if (diagTy->is()) { + diag = diag::type_inferred_to_uninhabited_tuple_type; + } else { + assert((diagTy->is() || diagTy->is()) && + "unknown structurally uninhabited type"); + } } if (shouldRequireType && !options.is(TypeResolverContext::ForEachStmt) && !options.is(TypeResolverContext::EditorPlaceholderExpr) && !(options & TypeResolutionFlags::FromNonInferredPattern)) { - diagnose(NP->getLoc(), diag::type_inferred_to_undesirable_type, - NP->getDecl()->getName(), type, NP->getDecl()->isLet()); + diagnose(NP->getLoc(), diag, NP->getDecl()->getName(), type, + NP->getDecl()->isLet()); diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence); } diff --git a/test/IRGen/generic_enums.swift b/test/IRGen/generic_enums.swift index 31286b399c338..c475aa02ca8f4 100644 --- a/test/IRGen/generic_enums.swift +++ b/test/IRGen/generic_enums.swift @@ -5,6 +5,4 @@ struct Bar { var b: Foo } -enum Foo{ - case bar -} +enum Foo {} diff --git a/test/Reflection/Inputs/TypeLowering.swift b/test/Reflection/Inputs/TypeLowering.swift index e17254d37c226..aa3cfb20b1116 100644 --- a/test/Reflection/Inputs/TypeLowering.swift +++ b/test/Reflection/Inputs/TypeLowering.swift @@ -168,14 +168,8 @@ public struct MetatypeStruct { public let abstractMetatype: MetadataHolder } -// We don't allow stored properties to have uninhabited types now, but make a -// wrapper over one to continue testing this public enum EmptyEnum {} -public struct EmptyEnumWrapper { - public var value: T -} - public enum NoPayloadEnum { case A case B @@ -224,7 +218,7 @@ public enum MultiPayloadGenericDynamic { } public struct EnumStruct { - public let empty: EmptyEnumWrapper + public let empty: EmptyEnum public let noPayload: NoPayloadEnum public let sillyNoPayload: SillyNoPayloadEnum public let singleton: SingletonEnum diff --git a/test/Reflection/typeref_lowering.swift b/test/Reflection/typeref_lowering.swift index 7195463542f4e..4ae17868db3f3 100644 --- a/test/Reflection/typeref_lowering.swift +++ b/test/Reflection/typeref_lowering.swift @@ -1032,9 +1032,7 @@ // CHECK-64: (struct TypeLowering.EnumStruct) // CHECK-64-NEXT: (struct size=81 alignment=8 stride=88 num_extra_inhabitants=[[PTR_XI]] bitwise_takable=1 // CHECK-64-NEXT: (field name=empty offset=0 -// CHECK-64-NEXT: (struct size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1 -// CHECK-64-NEXT: (field name=value offset=0 -// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1)))) +// CHECK-64-NEXT: (no_payload_enum size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1)) // CHECK-64-NEXT: (field name=noPayload offset=0 // CHECK-64-NEXT: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1)) // CHECK-64-NEXT: (field name=sillyNoPayload offset=1 diff --git a/test/attr/attr_noreturn.swift b/test/attr/attr_noreturn.swift index d68b44238024e..8dea7613d6954 100644 --- a/test/attr/attr_noreturn.swift +++ b/test/attr/attr_noreturn.swift @@ -34,8 +34,7 @@ func noReturn3(_: Int) // expected-error@-2 {{'@noreturn' has been removed; functions that never return should have a return type of 'Never' instead}}{{1-11=}}{{53-56=Never}} // Test that error recovery gives us the 'Never' return type -let x: Never = noReturn1(0) -// expected-error@-1 {{constant 'x' cannot have enum type 'Never' with no cases}} +let x: Never = noReturn1(0) // No error // @noreturn in function type declarations let valueNoReturn: @noreturn () -> () diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift index ac6a76a2583ff..034a14fdb0d9b 100644 --- a/test/attr/attr_objc.swift +++ b/test/attr/attr_objc.swift @@ -941,12 +941,11 @@ class infer_instanceVar1 { // expected-note@-2 {{Swift structs cannot be represented in Objective-C}} var var_PlainEnum: PlainEnum - // expected-error@-1 {{stored property 'var_PlainEnum' cannot have enum type 'PlainEnum' with no cases}} +// CHECK-LABEL: {{^}} var var_PlainEnum: PlainEnum @objc var var_PlainEnum_: PlainEnum // expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}} // expected-note@-2 {{non-'@objc' enums cannot be represented in Objective-C}} - // expected-error@-3 {{stored property 'var_PlainEnum_' cannot have enum type 'PlainEnum' with no cases}} var var_PlainProtocol: PlainProtocol // CHECK-LABEL: {{^}} var var_PlainProtocol: PlainProtocol @@ -1272,7 +1271,6 @@ class infer_instanceVar1 { // expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'PlainStruct'}} unowned var var_Unowned_bad3: PlainEnum // expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'PlainEnum'}} - // expected-error@-2 {{stored property 'var_Unowned_bad3' cannot have enum type 'PlainEnum' with no cases}} unowned var var_Unowned_bad4: String // expected-error@-1 {{'unowned' may only be applied to class and class-bound protocol types, not 'String'}} // CHECK-NOT: @objc{{.*}}Unowned_fail diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift index 6e1f6f7e38008..40a457e494958 100644 --- a/test/decl/var/properties.swift +++ b/test/decl/var/properties.swift @@ -1268,24 +1268,12 @@ class WeakFixItTest { weak var bar : WFI_P1 & WFI_P2 } -// SR-8811 -// Stored properties cannot have uninhabited types +// SR-8811 (Warning) -struct SR8811 { - var x: Never // expected-error {{stored property 'x' cannot have enum type 'Never' with no cases}} - - var y: (Int, Never, Bool) // expected-error {{stored property 'y' cannot have tuple type '(Int, Never, Bool)' containing enum with no cases}} -} - -let sr8811x: Never // expected-error {{constant 'sr8811x' cannot have enum type 'Never' with no cases}} +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}} -var sr8811y: (Int, Never) // expected-error {{variable 'sr8811y' cannot have tuple type '(Int, Never)' containing enum with no cases}} - -// Ok -var sr8811z: Never { - return fatalError() -} +let sr8811b: Never = fatalError() // Ok -enum SR8811EmptyGenericEnum {} +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}} -let sr8811z: SR8811EmptyGenericEnum // expected-error {{constant 'sr8811z' cannot have enum type 'SR8811EmptyGenericEnum' with no cases}} +let sr8811d: (Int, Never) = (16, fatalError()) // Ok diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 0473b67d103cc..62b9e1e6eb3c3 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -584,9 +584,9 @@ func conversionTest(_ a: inout Double, b: inout Int) { var pi_f3 = float.init(getPi()) // expected-error {{ambiguous use of 'init(_:)'}} var pi_f4 = float.init(pi_f) - var e = Empty(f) // expected-error {{variable 'e' cannot have enum type 'Empty' with no cases}} + 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}} var e2 = Empty(d) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Float'}} - var e3 = Empty(Float(d)) // expected-error {{variable 'e3' cannot have enum type 'Empty' with no cases}} + 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}} } struct Rule { // expected-note {{'init(target:dependencies:)' declared here}}