Skip to content

Commit f5f214d

Browse files
jdertheblixguy
authored andcommitted
Improve warning for inferring an undesirable type (#27797)
* [Sema][Diagnostics] Add fixit for warning when inferring an undesirable type * [Sema][Diagnostics] Generalize undesirable type warning to include arrays of empty tuples https://bugs.swift.org/browse/SR-11511
1 parent 47aa977 commit f5f214d

File tree

6 files changed

+53
-18
lines changed

6 files changed

+53
-18
lines changed

lib/Sema/TypeCheckPattern.cpp

+9-8
Original file line numberDiff line numberDiff line change
@@ -978,12 +978,10 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
978978
TypeChecker::checkForForbiddenPrefix(Context, var->getBaseName());
979979

980980
// If we are inferring a variable to have type AnyObject.Type,
981-
// "()", an uninhabited type, or optional thereof, emit a diagnostic.
982-
// In the first 2 cases, the coder probably forgot a cast and expected a
983-
// concrete type. In the later case, they probably didn't mean to bind to
984-
// a variable, or there is some other bug. We always tell them that they
985-
// can silence the warning with an explicit type annotation
986-
// (and provide a fixit) as a note.
981+
// "()", "[()]", an uninhabited type, or optional thereof, emit a diagnostic.
982+
// They are probably missing a cast or didn't mean to bind to a variable.
983+
// We always tell them that they can silence the warning with an
984+
// explicit type annotation (and provide a fixit) as a note.
987985
Type diagTy = type->lookThroughAllOptionalTypes();
988986
bool isOptional = !type->getOptionalObjectType().isNull();
989987
if (!diagTy) diagTy = type;
@@ -1010,6 +1008,9 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
10101008
assert((diagTy->is<EnumType>() || diagTy->is<BoundGenericEnumType>()) &&
10111009
"unknown structurally uninhabited type");
10121010
}
1011+
} else if (auto *BST = diagTy->getAs<BoundGenericStructType>()) {
1012+
if (BST->getDecl() == Context.getArrayDecl())
1013+
shouldRequireType = BST->getGenericArgs()[0]->isEqual(Context.TheEmptyTupleType);
10131014
}
10141015

10151016
if (shouldRequireType &&
@@ -1018,8 +1019,8 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
10181019
!(options & TypeResolutionFlags::FromNonInferredPattern)) {
10191020
diags.diagnose(NP->getLoc(), diag, NP->getDecl()->getName(), type,
10201021
NP->getDecl()->isLet());
1021-
diags.diagnose(NP->getLoc(),
1022-
diag::add_explicit_type_annotation_to_silence);
1022+
diags.diagnose(NP->getLoc(), diag::add_explicit_type_annotation_to_silence)
1023+
.fixItInsertAfter(var->getNameLoc(), ": " + type->getWithoutParens()->getString());
10231024
}
10241025

10251026
return false;

test/SourceKit/Sema/placeholders.swift.placeholders.response

+24
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,29 @@
2727
key.length: 9
2828
}
2929
]
30+
},
31+
{
32+
key.line: 8,
33+
key.column: 5,
34+
key.filepath: placeholders.swift,
35+
key.severity: source.diagnostic.severity.warning,
36+
key.description: "constant 'myArray' inferred to have type '[()]', which may be unexpected",
37+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
38+
key.diagnostics: [
39+
{
40+
key.line: 8,
41+
key.column: 5,
42+
key.filepath: placeholders.swift,
43+
key.severity: source.diagnostic.severity.note,
44+
key.description: "add an explicit type annotation to silence this warning",
45+
key.fixits: [
46+
{
47+
key.offset: 236,
48+
key.length: 0,
49+
key.sourcetext: ": [()]"
50+
}
51+
]
52+
}
53+
]
3054
}
3155
]

test/decl/var/lazy_properties.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ struct Outer {
112112

113113
lazy var y = {_ = 3}()
114114
// expected-warning@-1 {{variable 'y' inferred to have type '()', which may be unexpected}}
115-
// expected-note@-2 {{add an explicit type annotation to silence this warning}}
115+
// expected-note@-2 {{add an explicit type annotation to silence this warning}} {{15-15=: ()}}
116116
}
117117
}
118118

test/decl/var/properties.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -1272,11 +1272,11 @@ class WeakFixItTest {
12721272

12731273
// SR-8811 (Warning)
12741274

1275-
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}}
1275+
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}}
12761276

12771277
let sr8811b: Never = fatalError() // Ok
12781278

1279-
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}}
1279+
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)}}
12801280

12811281
let sr8811d: (Int, Never) = (16, fatalError()) // Ok
12821282

@@ -1292,11 +1292,11 @@ class SR_10995 {
12921292
}
12931293

12941294
func sr_10995_foo() {
1295-
let doubleOptionalNever = makeDoubleOptionalNever() // expected-warning {{constant 'doubleOptionalNever' inferred to have type 'Never??', which may be unexpected}}
1296-
// expected-note@-1 {{add an explicit type annotation to silence this warning}}
1295+
let doubleOptionalNever = makeDoubleOptionalNever() // expected-warning {{constant 'doubleOptionalNever' inferred to have type 'Never??', which may be unexpected}}
1296+
// expected-note@-1 {{add an explicit type annotation to silence this warning}} {{28-28=: Never??}}
12971297
// expected-warning@-2 {{initialization of immutable value 'doubleOptionalNever' was never used; consider replacing with assignment to '_' or removing it}}
12981298
let singleOptionalNever = makeSingleOptionalNever() // expected-warning {{constant 'singleOptionalNever' inferred to have type 'Never?', which may be unexpected}}
1299-
// expected-note@-1 {{add an explicit type annotation to silence this warning}}
1299+
// expected-note@-1 {{add an explicit type annotation to silence this warning}} {{28-28=: Never?}}
13001300
// expected-warning@-2 {{initialization of immutable value 'singleOptionalNever' was never used; consider replacing with assignment to '_' or removing it}}
13011301
}
13021302
}

test/decl/var/variables.swift

+12-2
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ struct Broken {
3636

3737
// rdar://16252090 - Warning when inferring empty tuple type for declarations
3838
var emptyTuple = testShadowing() // expected-warning {{variable 'emptyTuple' inferred to have type '()'}} \
39-
// expected-note {{add an explicit type annotation to silence this warning}}
39+
// expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: ()}}
4040

4141
// rdar://15263687 - Diagnose variables inferenced to 'AnyObject'
4242
var ao1 : AnyObject
4343
var ao2 = ao1
4444

4545
var aot1 : AnyObject.Type
4646
var aot2 = aot1 // expected-warning {{variable 'aot2' inferred to have type 'AnyObject.Type', which may be unexpected}} \
47-
// expected-note {{add an explicit type annotation to silence this warning}}
47+
// expected-note {{add an explicit type annotation to silence this warning}} {{9-9=: AnyObject.Type}}
4848

4949

5050
for item in [AnyObject]() { // No warning in for-each loop.
@@ -60,6 +60,16 @@ func testAnyObjectOptional() -> AnyObject? {
6060
return x
6161
}
6262

63+
// SR-11511 Warning for inferring an array of empty tuples
64+
var arrayOfEmptyTuples = [""].map { print($0) } // expected-warning {{variable 'arrayOfEmptyTuples' inferred to have type '[()]'}} \
65+
// expected-note {{add an explicit type annotation to silence this warning}} {{23-23=: [()]}}
66+
67+
var maybeEmpty = Optional(arrayOfEmptyTuples) // expected-warning {{variable 'maybeEmpty' inferred to have type '[()]?'}} \
68+
// expected-note {{add an explicit type annotation to silence this warning}} {{15-15=: [()]?}}
69+
70+
var shouldWarnWithoutSugar = (arrayOfEmptyTuples as Array<()>) // expected-warning {{variable 'shouldWarnWithoutSugar' inferred to have type 'Array<()>'}} \
71+
// expected-note {{add an explicit type annotation to silence this warning}} {{27-27=: Array<()>}}
72+
6373
class SomeClass {}
6474

6575
// <rdar://problem/16877304> weak let's should be rejected

test/expr/expressions.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -588,9 +588,9 @@ func conversionTest(_ a: inout Double, b: inout Int) {
588588
var pi_f3 = float.init(getPi()) // expected-error {{ambiguous use of 'init(_:)'}}
589589
var pi_f4 = float.init(pi_f)
590590

591-
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}}
591+
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}}
592592
var e2 = Empty(d) // expected-error{{cannot convert value of type 'Double' to expected argument type 'Float'}}
593-
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}}
593+
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}}
594594
}
595595

596596
struct Rule {

0 commit comments

Comments
 (0)