Skip to content

Commit b80a490

Browse files
committed
Empty diverging functions do not warn
1 parent 38c3e0d commit b80a490

File tree

8 files changed

+47
-16
lines changed

8 files changed

+47
-16
lines changed

src/libcore/num/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4210,7 +4210,6 @@ impl fmt::Display for TryFromIntError {
42104210

42114211
#[unstable(feature = "try_from", issue = "33417")]
42124212
impl From<!> for TryFromIntError {
4213-
#[allow(unreachable_code)]
42144213
fn from(never: !) -> TryFromIntError {
42154214
never
42164215
}

src/librustc_typeck/check/_match.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
609609
let diverges = match self.diverges.get() {
610610
Diverges::Maybe | Diverges::Always => Diverges::Always,
611611
Diverges::WarnedAlways => Diverges::WarnedAlways,
612+
Diverges::UnwarnedAlways => Diverges::UnwarnedAlways,
612613
};
613614
self.diverges.set(diverges);
614615
return tcx.types.never;
@@ -637,15 +638,17 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
637638
match all_pats_diverge {
638639
Diverges::Maybe => Diverges::Maybe,
639640
Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
641+
Diverges::UnwarnedAlways => Diverges::UnwarnedAlways,
640642
}
641643
}).collect();
642644

643645
// Now typecheck the blocks.
644646
//
645647
// The result of the match is the common supertype of all the
646-
// arms. We start the value as the logical bottom , since it's the,
647-
// well, bottom of the type lattice, and we'll be moving up the lattice
648-
// as we process each arm. (Note that any match with 0 arms is matching
648+
// arms. We start the value as the logical bottom (skipping
649+
// `UnwarnedAlways`, which is a special case), since it's the, well,
650+
// bottom of the type lattice, and we'll be moving up the lattice as
651+
// we process each arm. (Note that any match with 0 arms is matching
649652
// on any empty type and is therefore unreachable; should the flow
650653
// of execution reach it, we will panic, so bottom is an appropriate
651654
// type in that case.)

src/librustc_typeck/check/mod.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,13 @@ pub enum Diverges {
457457
/// Same as `Always` but with a reachability
458458
/// warning already emitted.
459459
WarnedAlways,
460+
461+
/// Same as `Always` but without a reachability
462+
/// warning emitted. Unlike `Always`, cannot be
463+
/// converted to `WarnedAlways`. Used when
464+
/// unreachable code is expected (e.g. in
465+
/// function parameters as part of trait impls).
466+
UnwarnedAlways,
460467
}
461468

462469
// Convenience impls for combining `Diverges`.
@@ -1062,7 +1069,16 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
10621069
// it must always diverge.
10631070
if fcx.tcx.features().exhaustive_patterns {
10641071
if arg_ty.conservative_is_uninhabited() {
1065-
fcx.diverges.set(fcx.diverges.get() | Diverges::Always);
1072+
let mut diverges = Diverges::Always;
1073+
if let hir::Expr_::ExprBlock(ref block) = body.value.node {
1074+
// If the function is completely empty, or has a single trailing
1075+
// expression, then we do not issue a warning (as it was likely
1076+
// mandated by a trait, rather than being an oversight).
1077+
if block.stmts.is_empty() {
1078+
diverges = Diverges::UnwarnedAlways;
1079+
}
1080+
}
1081+
fcx.diverges.set(fcx.diverges.get() | diverges);
10661082
}
10671083
}
10681084

src/libstd/error.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,8 @@ impl Error for string::FromUtf16Error {
309309

310310
#[stable(feature = "str_parse_error2", since = "1.8.0")]
311311
impl Error for string::ParseError {
312-
#[allow(unreachable_code)]
313312
fn description(&self) -> &str {
314-
match *self {}
313+
match self {}
315314
}
316315
}
317316

src/libstd/process.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,7 +1477,6 @@ impl<E: fmt::Debug> Termination for Result<(), E> {
14771477

14781478
#[unstable(feature = "termination_trait_lib", issue = "43301")]
14791479
impl Termination for ! {
1480-
#[allow(unreachable_code)]
14811480
fn report(self) -> i32 { self }
14821481
}
14831482

src/test/compile-fail/unreachable-try-pattern.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ enum Void {}
1717

1818
impl From<Void> for i32 {
1919
fn from(v: Void) -> i32 {
20-
//~^ WARN unreachable expression
2120
match v {}
2221
//~^ WARN unreachable expression
2322
}

src/test/ui/better_divergence_checking.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,27 @@
99
// except according to those terms.
1010

1111
#![feature(exhaustive_patterns)]
12+
#![feature(never_type)]
1213
#![deny(unreachable_code)]
1314

1415
pub enum Void {}
1516

16-
pub fn uninhabited_parameter(_v: Void) {
17-
//~^ ERROR unreachable expression
17+
pub fn uninhabited_parameter_i(_v: Void) {
18+
// A function with an uninhabited parameter
19+
// is permitted if its body is empty.
20+
}
21+
22+
pub fn uninhabited_parameter_ii(v: !) -> i32 {
23+
// A function with an uninhabited parameter
24+
// is permitted if it simply returns a value
25+
// as a trailing expression to satisfy the
26+
// return type.
27+
v
28+
}
29+
30+
pub fn uninhabited_parameter_iii(_v: Void, x: i32) -> i32 {
31+
println!("Call me if you can!"); //~^ ERROR unreachable expression
32+
x
1833
}
1934

2035
fn main() {}

src/test/ui/better_divergence_checking.stderr

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
error: unreachable expression
2-
--> $DIR/better_divergence_checking.rs:16:40
2+
--> $DIR/better_divergence_checking.rs:30:59
33
|
4-
LL | pub fn uninhabited_parameter(_v: Void) {
5-
| ________________________________________^
6-
LL | | //~^ ERROR unreachable expression
4+
LL | pub fn uninhabited_parameter_iii(_v: Void, x: i32) -> i32 {
5+
| ___________________________________________________________^
6+
LL | | println!("Call me if you can!"); //~^ ERROR unreachable expression
7+
LL | | x
78
LL | | }
89
| |_^
910
|
1011
note: lint level defined here
11-
--> $DIR/better_divergence_checking.rs:12:9
12+
--> $DIR/better_divergence_checking.rs:13:9
1213
|
1314
LL | #![deny(unreachable_code)]
1415
| ^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)