Skip to content

Commit ea83638

Browse files
committed
Suppress warnings about Never error types in catch clauses
Enabling typed throws has introduced some spurious warnings about error values of `Never` type on top of the custom "unreachable" diagnostics for catch clauses, so suppress the new warnings---they aren't helpful.
1 parent b7fd439 commit ea83638

File tree

7 files changed

+35
-11
lines changed

7 files changed

+35
-11
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ void ConstraintSystem::recordPotentialThrowSite(
373373
ConstraintLocatorBuilder locator) {
374374
ASTContext &ctx = getASTContext();
375375

376+
// Only record potential throw sites when typed throws is enabled.
377+
if (!ctx.LangOpts.hasFeature(Feature::FullTypedThrows))
378+
return;
379+
376380
// Catch node location is determined by the source location.
377381
auto sourceLoc = locator.getAnchor().getStartLoc();
378382
if (!sourceLoc)
@@ -428,6 +432,9 @@ Type ConstraintSystem::getCaughtErrorType(CatchNode catchNode) {
428432
return getClosureType(closure)->getEffectiveThrownErrorTypeOrNever();
429433
}
430434

435+
if (!ctx.LangOpts.hasFeature(Feature::FullTypedThrows))
436+
return ctx.getErrorExistentialType();
437+
431438
// Handle inference of caught error types.
432439

433440
// Collect all of the potential throw sites for this catch node.

lib/Sema/TypeCheckPattern.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,9 @@ Pattern *TypeChecker::coercePatternToType(
12391239
} else if (auto MTT = diagTy->getAs<AnyMetatypeType>()) {
12401240
if (MTT->getInstanceType()->isAnyObject())
12411241
shouldRequireType = true;
1242-
} else if (diagTy->isStructurallyUninhabited()) {
1242+
} else if (diagTy->isStructurallyUninhabited() &&
1243+
!(options.contains(TypeResolutionFlags::SilenceNeverWarnings) &&
1244+
type->isNever())) {
12431245
shouldRequireType = true;
12441246
diag = isOptional ? diag::type_inferred_to_undesirable_type
12451247
: diag::type_inferred_to_uninhabited_type;
@@ -1428,11 +1430,15 @@ Pattern *TypeChecker::coercePatternToType(
14281430
if (type->hasError()) {
14291431
return nullptr;
14301432
}
1431-
diags
1432-
.diagnose(IP->getLoc(), diag::downcast_to_unrelated, type,
1433-
IP->getCastType())
1434-
.highlight(IP->getLoc())
1435-
.highlight(IP->getCastTypeRepr()->getSourceRange());
1433+
1434+
if (!(options.contains(TypeResolutionFlags::SilenceNeverWarnings) &&
1435+
type->isNever())) {
1436+
diags
1437+
.diagnose(IP->getLoc(), diag::downcast_to_unrelated, type,
1438+
IP->getCastType())
1439+
.highlight(IP->getLoc())
1440+
.highlight(IP->getCastTypeRepr()->getSourceRange());
1441+
}
14361442

14371443
IP->setCastKind(CheckedCastKind::ValueCast);
14381444
break;

lib/Sema/TypeCheckStmt.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
14681468
}
14691469

14701470
void checkCaseLabelItemPattern(CaseStmt *caseBlock, CaseLabelItem &labelItem,
1471+
CaseParentKind parentKind,
14711472
bool &limitExhaustivityChecks,
14721473
Type subjectType) {
14731474
Pattern *pattern = labelItem.getPattern();
@@ -1484,6 +1485,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
14841485
if (subjectType) {
14851486
auto contextualPattern = ContextualPattern::forRawPattern(pattern, DC);
14861487
TypeResolutionOptions patternOptions(TypeResolverContext::InExpression);
1488+
if (parentKind == CaseParentKind::DoCatch)
1489+
patternOptions |= TypeResolutionFlags::SilenceNeverWarnings;
1490+
14871491
auto coercedPattern = TypeChecker::coercePatternToType(
14881492
contextualPattern, subjectType, patternOptions);
14891493
if (coercedPattern)
@@ -1584,8 +1588,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
15841588
for (auto &labelItem : caseLabelItemArray) {
15851589
// Resolve the pattern in our case label if it has not been resolved and
15861590
// check that our var decls follow invariants.
1587-
checkCaseLabelItemPattern(caseBlock, labelItem, limitExhaustivityChecks,
1588-
subjectType);
1591+
checkCaseLabelItemPattern(caseBlock, labelItem, parentKind,
1592+
limitExhaustivityChecks, subjectType);
15891593

15901594
// Check the guard expression, if present.
15911595
if (auto *guard = labelItem.getGuardExpr()) {

lib/Sema/TypeCheckType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ enum class TypeResolutionFlags : uint16_t {
8282

8383
/// Whether this is a resolution based on a pack reference.
8484
FromPackReference = 1 << 12,
85+
86+
/// Whether to suppress warnings about conversions from and bindings of type
87+
/// Never
88+
SilenceNeverWarnings = 1 << 13,
8589
};
8690

8791
/// Type resolution contexts that require special handling.

test/Parse/errors.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ func one() {
1919
do {
2020

2121
} catch { // expected-warning {{'catch' block is unreachable because no errors are thrown in 'do' block}}
22-
let error2 = error
22+
let error2 = error // expected-warning{{constant 'error2' inferred to have type 'Never', which is an enum with no cases}}
23+
// expected-note@-1{{add an explicit type annotation to silence this warning}}
2324
}
2425

2526
do {
2627
} catch where true { // expected-warning {{'catch' block is unreachable because no errors are thrown in 'do' block}}
27-
let error2 = error
28+
let error2 = error // expected-warning{{constant 'error2' inferred to have type 'Never', which is an enum with no cases}}
29+
// expected-note@-1{{add an explicit type annotation to silence this warning}}
2830
} catch {
2931
}
3032

test/Sema/redeclaration-checking.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func stmtTest() {
8787
// expected-note@-1 {{'x' previously declared here}}
8888
// expected-error@-2 {{invalid redeclaration of 'x'}}
8989
// expected-warning@-3 {{unreachable}}
90+
// expected-error@-4{{pattern of type 'MyError' cannot match 'Never'}}
9091
}
9192

9293
func fullNameTest() {

test/StringProcessing/Parse/forward-slash-regex.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ default:
262262
}
263263

264264
do {} catch /x/ {}
265-
// expected-error@-1 {{expression pattern of type 'Regex<Substring>' cannot match values of type 'any Error'}}
265+
// expected-error@-1 {{expression pattern of type 'Regex<Substring>' cannot match values of type 'Never'}}
266266
// expected-warning@-2 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
267267

268268
switch /x/ {

0 commit comments

Comments
 (0)