Skip to content

Commit 0e88f43

Browse files
committed
Unrolled build for #165497 in rollup 165510
Rollup merge of #165497 - WaffleLapkin:_, r=BoxyUwU fix unsoundness when compiling `[diverging_const; _]` Follow up to #165416, because I [missed a case](#165416 (comment)). r? @BoxyUwU
2 parents 712e1d3 + 8dfb82d commit 0e88f43

9 files changed

Lines changed: 154 additions & 13 deletions

‎compiler/rustc_hir_typeck/src/expr.rs‎

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use rustc_infer::traits::WellFormedLoc;
3131
use rustc_infer::traits::query::NoSolution;
3232
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase};
3333
use rustc_middle::ty::error::{ExpectedFound, TypeError};
34-
use rustc_middle::ty::{self, AdtKind, GenericArgs, Ty, TypeVisitableExt, Unnormalized};
34+
use rustc_middle::ty::{self, AdtKind, ConstKind, GenericArgs, Ty, TypeVisitableExt, Unnormalized};
3535
use rustc_session::diagnostics::feature_err;
3636
use rustc_span::edit_distance::find_best_match_for_name;
3737
use rustc_span::hygiene::DesugaringKind;
@@ -1774,17 +1774,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17741774
),
17751775
);
17761776

1777-
let count_is_zero = {
1778-
if let Ok(count) = tcx.try_normalize_erasing_regions(
1779-
self.typing_env(self.param_env),
1780-
Unnormalized::new_wip(count),
1781-
) {
1782-
count.try_to_value().and_then(|c| c.try_to_target_usize(tcx)) == Some(0)
1783-
} else {
1784-
false
1785-
}
1786-
};
1787-
17881777
let uty = match expected {
17891778
ExpectHasType(uty) => uty.builtin_index(),
17901779
_ => None,
@@ -1811,6 +1800,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18111800
// This is a problem, because it means if `CONST` is `const { panic!() }`, the side effect
18121801
// of panic / failing compilation never happens. In such cases we need to ignore divergence
18131802
// from the `CONST`, as otherwise we can end up executing code that was assumed unreachable.
1803+
let count_is_zero = match count.kind() {
1804+
// This is the exact check that mir building does
1805+
ConstKind::Value(v) => v.try_to_target_usize(tcx) == Some(0),
1806+
1807+
// An infer const can get inferred to 0.
1808+
//
1809+
// We could check the expectation here to do ad-hoc inference, but that feels quite
1810+
// error prone and annoying.
1811+
ConstKind::Infer(_) => true,
1812+
1813+
// While const generic params can be substituted with 0, mir building specifically
1814+
// checks for value 0 before monomorphization, so they (alongside aliases, etc) cannot
1815+
// trigger the bug.
1816+
ConstKind::Param(_)
1817+
| ConstKind::Placeholder(_)
1818+
| ConstKind::Alias(..)
1819+
| ConstKind::Error(_)
1820+
| ConstKind::Expr(_) => false,
1821+
1822+
ConstKind::Bound(..) => bug!(),
1823+
};
1824+
18141825
if count_is_zero && element.is_constant_for_zero_repeat() {
18151826
self.diverges.set(old_diverges);
18161827
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Check that repeating a diverging constant 0 times doesn't lead to unsoundness.
2+
//
3+
// This specific test checks that using an associated const that evaluates to 0, rather than just
4+
// plain literal 0, doesn't allow the unsoundness either.
5+
//
6+
// Issue: <https://github.com/rust-lang/rust/issues/165323>
7+
//
8+
//@ build-fail
9+
#![feature(generic_const_exprs)]
10+
11+
trait Trait {
12+
const ZERO: usize;
13+
}
14+
15+
impl Trait for () {
16+
const ZERO: usize = 0;
17+
}
18+
19+
fn ex_nihilo<T: Trait>() -> u32
20+
where
21+
[(); T::ZERO]:,
22+
{
23+
[const { panic!() } as !; T::ZERO];
24+
//~^ error: evaluation panicked: explicit panic
25+
}
26+
27+
fn main() {
28+
dbg!(ex_nihilo::<()>());
29+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0080]: evaluation panicked: explicit panic
2+
--> $DIR/zero_assoc_diverging_consts.rs:23:14
3+
|
4+
LL | fn ex_nihilo<T: Trait>() -> u32
5+
...
6+
LL | [const { panic!() } as !; T::ZERO];
7+
| ^^^^^^^^ evaluation of `ex_nihilo::<()>::{constant#1}` failed here
8+
9+
note: erroneous constant encountered
10+
--> $DIR/zero_assoc_diverging_consts.rs:23:6
11+
|
12+
LL | [const { panic!() } as !; T::ZERO];
13+
| ^^^^^^^^^^^^^^^^^^
14+
15+
note: the above error was encountered while instantiating `fn ex_nihilo::<()>`
16+
--> $DIR/zero_assoc_diverging_consts.rs:28:10
17+
|
18+
LL | dbg!(ex_nihilo::<()>());
19+
| ^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 1 previous error
22+
23+
For more information about this error, try `rustc --explain E0080`.

tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.rs renamed to tests/ui/repeat-expr/zero_diverging_type_relative_consts.rs

File renamed without changes.

tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.stderr renamed to tests/ui/repeat-expr/zero_diverging_type_relative_consts.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/zero_diverging_type_relative_consts_consts.rs:14:19
2+
--> $DIR/zero_diverging_type_relative_consts.rs:14:19
33
|
44
LL | fn ex_nihilo() -> u32 {
55
| --------- ^^^ expected `u32`, found `()`
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Check that repeating a diverging constant 0 times (inferred via `_`)
2+
// doesn't lead to unsoundness.
3+
//
4+
// Issue: <https://github.com/rust-lang/rust/issues/165323>
5+
6+
fn ex_nihilo() -> u32 {
7+
//~^ error: mismatched types
8+
let _: [_; 0] = [const { panic!() } as !; _];
9+
}
10+
11+
fn ex_nihilo2() -> u32 {
12+
//~^ error: mismatched types
13+
let a = [const { panic!() } as !; _];
14+
let _: [_; 0] = a;
15+
}
16+
17+
fn main() {
18+
dbg!(ex_nihilo());
19+
dbg!(ex_nihilo2());
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/zero_infer_diverging_consts.rs:6:19
3+
|
4+
LL | fn ex_nihilo() -> u32 {
5+
| --------- ^^^ expected `u32`, found `()`
6+
| |
7+
| implicitly returns `()` as its body has no tail or `return` expression
8+
9+
error[E0308]: mismatched types
10+
--> $DIR/zero_infer_diverging_consts.rs:11:20
11+
|
12+
LL | fn ex_nihilo2() -> u32 {
13+
| ---------- ^^^ expected `u32`, found `()`
14+
| |
15+
| implicitly returns `()` as its body has no tail or `return` expression
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Check that repeating a diverging constant 0 times doesn't lead to unsoundness.
2+
//
3+
// This specific test checks that using a generic const argument that is substited with 0, rather
4+
// than just plain literal 0, doesn't allow the unsoundness either.
5+
//
6+
// Issue: <https://github.com/rust-lang/rust/issues/165323>
7+
//
8+
//@ build-fail
9+
10+
fn ex_nihilo<const N: usize>() -> u32 {
11+
[const { panic!() } as !; N];
12+
//~^ error: evaluation panicked: explicit panic
13+
}
14+
15+
fn main() {
16+
dbg!(ex_nihilo::<0>());
17+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0080]: evaluation panicked: explicit panic
2+
--> $DIR/zero_param_diverging_consts.rs:11:14
3+
|
4+
LL | fn ex_nihilo<const N: usize>() -> u32 {
5+
LL | [const { panic!() } as !; N];
6+
| ^^^^^^^^ evaluation of `ex_nihilo::<0>::{constant#0}` failed here
7+
8+
note: erroneous constant encountered
9+
--> $DIR/zero_param_diverging_consts.rs:11:6
10+
|
11+
LL | [const { panic!() } as !; N];
12+
| ^^^^^^^^^^^^^^^^^^
13+
14+
note: the above error was encountered while instantiating `fn ex_nihilo::<0>`
15+
--> $DIR/zero_param_diverging_consts.rs:16:10
16+
|
17+
LL | dbg!(ex_nihilo::<0>());
18+
| ^^^^^^^^^^^^^^^^
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)