From 4a222a0b57592bdd1c4ad2dfff8c325cc156d5f9 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Sat, 19 Oct 2019 18:10:29 -0400 Subject: [PATCH 1/2] [Sema][Diagnostics] Add fixit for warning when inferring an undesirable type --- lib/Sema/TypeCheckPattern.cpp | 4 ++-- test/decl/var/lazy_properties.swift | 2 +- test/decl/var/properties.swift | 10 +++++----- test/decl/var/variables.swift | 4 ++-- test/expr/expressions.swift | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 5f0d1abc45b38..bd5e6e99ee5fe 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1018,8 +1018,8 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, !(options & TypeResolutionFlags::FromNonInferredPattern)) { diags.diagnose(NP->getLoc(), diag, NP->getDecl()->getName(), type, NP->getDecl()->isLet()); - diags.diagnose(NP->getLoc(), - diag::add_explicit_type_annotation_to_silence); + diags.diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence) + .fixItInsertAfter(var->getNameLoc(), ": " + type->getString()); } return false; diff --git a/test/decl/var/lazy_properties.swift b/test/decl/var/lazy_properties.swift index 586fd40ed4cf9..854b65b5d8b60 100644 --- a/test/decl/var/lazy_properties.swift +++ b/test/decl/var/lazy_properties.swift @@ -112,7 +112,7 @@ struct Outer { lazy var y = {_ = 3}() // expected-warning@-1 {{variable 'y' inferred to have type '()', which may be unexpected}} - // expected-note@-2 {{add an explicit type annotation to silence this warning}} + // expected-note@-2 {{add an explicit type annotation to silence this warning}} {{15-15=: ()}} } } diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift index e4e9be2c785db..cde74620d6de7 100644 --- a/test/decl/var/properties.swift +++ b/test/decl/var/properties.swift @@ -1272,11 +1272,11 @@ class WeakFixItTest { // SR-8811 (Warning) -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}} +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}} {{12-12=: Never}} let sr8811b: Never = fatalError() // Ok -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 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}} {{12-12=: (Int, Never)}} let sr8811d: (Int, Never) = (16, fatalError()) // Ok @@ -1292,11 +1292,11 @@ class SR_10995 { } func sr_10995_foo() { - let doubleOptionalNever = makeDoubleOptionalNever() // expected-warning {{constant 'doubleOptionalNever' inferred to have type 'Never??', which may be unexpected}} - // expected-note@-1 {{add an explicit type annotation to silence this warning}} + let doubleOptionalNever = makeDoubleOptionalNever() // expected-warning {{constant 'doubleOptionalNever' inferred to have type 'Never??', which may be unexpected}} + // expected-note@-1 {{add an explicit type annotation to silence this warning}} {{28-28=: Never??}} // expected-warning@-2 {{initialization of immutable value 'doubleOptionalNever' was never used; consider replacing with assignment to '_' or removing it}} let singleOptionalNever = makeSingleOptionalNever() // expected-warning {{constant 'singleOptionalNever' inferred to have type 'Never?', which may be unexpected}} - // expected-note@-1 {{add an explicit type annotation to silence this warning}} + // expected-note@-1 {{add an explicit type annotation to silence this warning}} {{28-28=: Never?}} // expected-warning@-2 {{initialization of immutable value 'singleOptionalNever' was never used; consider replacing with assignment to '_' or removing it}} } } diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index 0befba6d924e1..d6d4239018503 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -36,7 +36,7 @@ struct Broken { // rdar://16252090 - Warning when inferring empty tuple type for declarations var emptyTuple = testShadowing() // expected-warning {{variable 'emptyTuple' inferred to have type '()'}} \ - // expected-note {{add an explicit type annotation to silence this warning}} + // expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: ()}} // rdar://15263687 - Diagnose variables inferenced to 'AnyObject' var ao1 : AnyObject @@ -44,7 +44,7 @@ var ao2 = ao1 var aot1 : AnyObject.Type var aot2 = aot1 // expected-warning {{variable 'aot2' inferred to have type 'AnyObject.Type', which may be unexpected}} \ - // expected-note {{add an explicit type annotation to silence this warning}} + // expected-note {{add an explicit type annotation to silence this warning}} {{9-9=: AnyObject.Type}} for item in [AnyObject]() { // No warning in for-each loop. diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 5bb476a659d36..1f8cc1490751e 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -588,9 +588,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-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 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}} {{8-8=: Empty}} var e2 = Empty(d) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Float'}} - 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}} + 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}} {{9-9=: Empty}} } struct Rule { From 502691f54f463f6fed4fe683220156d1125ae550 Mon Sep 17 00:00:00 2001 From: Jesse Rusak Date: Sat, 19 Oct 2019 18:10:43 -0400 Subject: [PATCH 2/2] [Sema][Diagnostics] Generalize undesirable type warning to include arrays of empty tuples https://bugs.swift.org/browse/SR-11511 --- lib/Sema/TypeCheckPattern.cpp | 15 ++++++------ .../placeholders.swift.placeholders.response | 24 +++++++++++++++++++ test/decl/var/variables.swift | 10 ++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index bd5e6e99ee5fe..fbbfdcf0ce150 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -978,12 +978,10 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, TypeChecker::checkForForbiddenPrefix(Context, var->getBaseName()); // If we are inferring a variable to have type AnyObject.Type, - // "()", 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. + // "()", "[()]", an uninhabited type, or optional thereof, emit a diagnostic. + // They are probably missing a cast or didn't mean to bind to a variable. + // 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->lookThroughAllOptionalTypes(); bool isOptional = !type->getOptionalObjectType().isNull(); if (!diagTy) diagTy = type; @@ -1010,6 +1008,9 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, assert((diagTy->is() || diagTy->is()) && "unknown structurally uninhabited type"); } + } else if (auto *BST = diagTy->getAs()) { + if (BST->getDecl() == Context.getArrayDecl()) + shouldRequireType = BST->getGenericArgs()[0]->isEqual(Context.TheEmptyTupleType); } if (shouldRequireType && @@ -1019,7 +1020,7 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution, diags.diagnose(NP->getLoc(), diag, NP->getDecl()->getName(), type, NP->getDecl()->isLet()); diags.diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence) - .fixItInsertAfter(var->getNameLoc(), ": " + type->getString()); + .fixItInsertAfter(var->getNameLoc(), ": " + type->getWithoutParens()->getString()); } return false; diff --git a/test/SourceKit/Sema/placeholders.swift.placeholders.response b/test/SourceKit/Sema/placeholders.swift.placeholders.response index c5c69719ff3c9..0c192f93389f5 100644 --- a/test/SourceKit/Sema/placeholders.swift.placeholders.response +++ b/test/SourceKit/Sema/placeholders.swift.placeholders.response @@ -27,5 +27,29 @@ key.length: 9 } ] + }, + { + key.line: 8, + key.column: 5, + key.filepath: placeholders.swift, + key.severity: source.diagnostic.severity.warning, + key.description: "constant 'myArray' inferred to have type '[()]', which may be unexpected", + key.diagnostic_stage: source.diagnostic.stage.swift.sema, + key.diagnostics: [ + { + key.line: 8, + key.column: 5, + key.filepath: placeholders.swift, + key.severity: source.diagnostic.severity.note, + key.description: "add an explicit type annotation to silence this warning", + key.fixits: [ + { + key.offset: 236, + key.length: 0, + key.sourcetext: ": [()]" + } + ] + } + ] } ] diff --git a/test/decl/var/variables.swift b/test/decl/var/variables.swift index d6d4239018503..5db9cf770acd0 100644 --- a/test/decl/var/variables.swift +++ b/test/decl/var/variables.swift @@ -60,6 +60,16 @@ func testAnyObjectOptional() -> AnyObject? { return x } +// SR-11511 Warning for inferring an array of empty tuples +var arrayOfEmptyTuples = [""].map { print($0) } // expected-warning {{variable 'arrayOfEmptyTuples' inferred to have type '[()]'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{23-23=: [()]}} + +var maybeEmpty = Optional(arrayOfEmptyTuples) // expected-warning {{variable 'maybeEmpty' inferred to have type '[()]?'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: [()]?}} + +var shouldWarnWithoutSugar = (arrayOfEmptyTuples as Array<()>) // expected-warning {{variable 'shouldWarnWithoutSugar' inferred to have type 'Array<()>'}} \ + // expected-note {{add an explicit type annotation to silence this warning}} {{27-27=: Array<()>}} + class SomeClass {} // weak let's should be rejected