Skip to content

Commit e5b8c11

Browse files
committedOct 19, 2019
Auto merge of #64890 - wesleywiser:const_prop_rvalue, r=oli-obk
[const-prop] Handle remaining MIR Rvalue cases r? @oli-obk
2 parents 9578272 + fd20dbe commit e5b8c11

23 files changed

+354
-94
lines changed
 

‎src/librustc/mir/interpret/error.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ pub enum UndefinedBehaviorInfo {
363363
UbExperimental(String),
364364
/// Unreachable code was executed.
365365
Unreachable,
366+
/// An enum discriminant was set to a value which was outside the range of valid values.
367+
InvalidDiscriminant(ScalarMaybeUndef),
366368
}
367369

368370
impl fmt::Debug for UndefinedBehaviorInfo {
@@ -373,6 +375,8 @@ impl fmt::Debug for UndefinedBehaviorInfo {
373375
write!(f, "{}", msg),
374376
Unreachable =>
375377
write!(f, "entered unreachable code"),
378+
InvalidDiscriminant(val) =>
379+
write!(f, "encountered invalid enum discriminant {}", val),
376380
}
377381
}
378382
}
@@ -400,7 +404,6 @@ pub enum UnsupportedOpInfo<'tcx> {
400404
InvalidMemoryAccess,
401405
InvalidFunctionPointer,
402406
InvalidBool,
403-
InvalidDiscriminant(ScalarMaybeUndef),
404407
PointerOutOfBounds {
405408
ptr: Pointer,
406409
msg: CheckInAllocMsg,
@@ -485,8 +488,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
485488
write!(f, "incorrect alloc info: expected size {} and align {}, \
486489
got size {} and align {}",
487490
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
488-
InvalidDiscriminant(val) =>
489-
write!(f, "encountered invalid enum discriminant {}", val),
490491
InvalidMemoryAccess =>
491492
write!(f, "tried to access memory through an invalid pointer"),
492493
DanglingPointerDeref =>

‎src/librustc_mir/interpret/operand.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
647647
let bits_discr = raw_discr
648648
.not_undef()
649649
.and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
650-
.map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?;
650+
.map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?;
651651
let real_discr = if discr_val.layout.ty.is_signed() {
652652
// going from layout tag type to typeck discriminant type
653653
// requires first sign extending with the discriminant layout
@@ -677,7 +677,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
677677
_ => bug!("tagged layout for non-adt non-generator"),
678678

679679
}.ok_or_else(
680-
|| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag()))
680+
|| err_ub!(InvalidDiscriminant(raw_discr.erase_tag()))
681681
)?;
682682
(real_discr, index.0)
683683
},
@@ -689,15 +689,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
689689
let variants_start = niche_variants.start().as_u32();
690690
let variants_end = niche_variants.end().as_u32();
691691
let raw_discr = raw_discr.not_undef().map_err(|_| {
692-
err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
692+
err_ub!(InvalidDiscriminant(ScalarMaybeUndef::Undef))
693693
})?;
694694
match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
695695
Err(ptr) => {
696696
// The niche must be just 0 (which an inbounds pointer value never is)
697697
let ptr_valid = niche_start == 0 && variants_start == variants_end &&
698698
!self.memory.ptr_may_be_null(ptr);
699699
if !ptr_valid {
700-
throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag().into()))
700+
throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into()))
701701
}
702702
(dataful_variant.as_u32() as u128, dataful_variant)
703703
},

‎src/librustc_mir/interpret/place.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,17 +1031,23 @@ where
10311031
variant_index: VariantIdx,
10321032
dest: PlaceTy<'tcx, M::PointerTag>,
10331033
) -> InterpResult<'tcx> {
1034+
let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into();
1035+
10341036
match dest.layout.variants {
10351037
layout::Variants::Single { index } => {
1036-
assert_eq!(index, variant_index);
1038+
if index != variant_index {
1039+
throw_ub!(InvalidDiscriminant(variant_scalar));
1040+
}
10371041
}
10381042
layout::Variants::Multiple {
10391043
discr_kind: layout::DiscriminantKind::Tag,
10401044
discr: ref discr_layout,
10411045
discr_index,
10421046
..
10431047
} => {
1044-
assert!(dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index));
1048+
if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) {
1049+
throw_ub!(InvalidDiscriminant(variant_scalar));
1050+
}
10451051
let discr_val =
10461052
dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
10471053

@@ -1064,9 +1070,9 @@ where
10641070
discr_index,
10651071
..
10661072
} => {
1067-
assert!(
1068-
variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(),
1069-
);
1073+
if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() {
1074+
throw_ub!(InvalidDiscriminant(variant_scalar));
1075+
}
10701076
if variant_index != dataful_variant {
10711077
let variants_start = niche_variants.start().as_u32();
10721078
let variant_index_relative = variant_index.as_u32()

‎src/librustc_mir/interpret/validity.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
344344
match self.walk_value(op) {
345345
Ok(()) => Ok(()),
346346
Err(err) => match err.kind {
347-
err_unsup!(InvalidDiscriminant(val)) =>
347+
err_ub!(InvalidDiscriminant(val)) =>
348348
throw_validation_failure!(
349349
val, self.path, "a valid enum discriminant"
350350
),

‎src/librustc_mir/transform/const_prop.rs

Lines changed: 84 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc::hir::def::DefKind;
88
use rustc::hir::def_id::DefId;
99
use rustc::mir::{
1010
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
11-
Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
11+
Local, UnOp, StatementKind, Statement, LocalKind,
1212
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp,
1313
SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
1414
};
@@ -118,7 +118,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
118118
struct ConstPropMachine;
119119

120120
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
121-
type MemoryKinds= !;
121+
type MemoryKinds = !;
122122
type PointerTag = ();
123123
type ExtraFnVal = !;
124124

@@ -434,32 +434,23 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
434434
) -> Option<Const<'tcx>> {
435435
let span = source_info.span;
436436

437-
// if this isn't a supported operation, then return None
438-
match rvalue {
439-
Rvalue::Repeat(..) |
440-
Rvalue::Aggregate(..) |
441-
Rvalue::NullaryOp(NullOp::Box, _) |
442-
Rvalue::Discriminant(..) => return None,
443-
444-
Rvalue::Use(_) |
445-
Rvalue::Len(_) |
446-
Rvalue::Cast(..) |
447-
Rvalue::NullaryOp(..) |
448-
Rvalue::CheckedBinaryOp(..) |
449-
Rvalue::Ref(..) |
450-
Rvalue::UnaryOp(..) |
451-
Rvalue::BinaryOp(..) => { }
452-
}
437+
let overflow_check = self.tcx.sess.overflow_checks();
453438

454-
// perform any special checking for specific Rvalue types
455-
if let Rvalue::UnaryOp(op, arg) = rvalue {
456-
trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
457-
let overflow_check = self.tcx.sess.overflow_checks();
439+
// Perform any special handling for specific Rvalue types.
440+
// Generally, checks here fall into one of two categories:
441+
// 1. Additional checking to provide useful lints to the user
442+
// - In this case, we will do some validation and then fall through to the
443+
// end of the function which evals the assignment.
444+
// 2. Working around bugs in other parts of the compiler
445+
// - In this case, we'll return `None` from this function to stop evaluation.
446+
match rvalue {
447+
// Additional checking: if overflow checks are disabled (which is usually the case in
448+
// release mode), then we need to do additional checking here to give lints to the user
449+
// if an overflow would occur.
450+
Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => {
451+
trace!("checking UnaryOp(op = Neg, arg = {:?})", arg);
458452

459-
self.use_ecx(source_info, |this| {
460-
// We check overflow in debug mode already
461-
// so should only check in release mode.
462-
if *op == UnOp::Neg && !overflow_check {
453+
self.use_ecx(source_info, |this| {
463454
let ty = arg.ty(&this.local_decls, this.tcx);
464455

465456
if ty.is_integral() {
@@ -471,60 +462,70 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
471462
throw_panic!(OverflowNeg)
472463
}
473464
}
465+
466+
Ok(())
467+
})?;
468+
}
469+
470+
// Additional checking: check for overflows on integer binary operations and report
471+
// them to the user as lints.
472+
Rvalue::BinaryOp(op, left, right) => {
473+
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
474+
475+
let r = self.use_ecx(source_info, |this| {
476+
this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
477+
})?;
478+
if *op == BinOp::Shr || *op == BinOp::Shl {
479+
let left_bits = place_layout.size.bits();
480+
let right_size = r.layout.size;
481+
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
482+
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
483+
let source_scope_local_data = match self.source_scope_local_data {
484+
ClearCrossCrate::Set(ref data) => data,
485+
ClearCrossCrate::Clear => return None,
486+
};
487+
let dir = if *op == BinOp::Shr {
488+
"right"
489+
} else {
490+
"left"
491+
};
492+
let hir_id = source_scope_local_data[source_info.scope].lint_root;
493+
self.tcx.lint_hir(
494+
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
495+
hir_id,
496+
span,
497+
&format!("attempt to shift {} with overflow", dir));
498+
return None;
499+
}
474500
}
475501

476-
Ok(())
477-
})?;
478-
} else if let Rvalue::BinaryOp(op, left, right) = rvalue {
479-
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
480-
481-
let r = self.use_ecx(source_info, |this| {
482-
this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
483-
})?;
484-
if *op == BinOp::Shr || *op == BinOp::Shl {
485-
let left_bits = place_layout.size.bits();
486-
let right_size = r.layout.size;
487-
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
488-
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
489-
let source_scope_local_data = match self.source_scope_local_data {
490-
ClearCrossCrate::Set(ref data) => data,
491-
ClearCrossCrate::Clear => return None,
492-
};
493-
let dir = if *op == BinOp::Shr {
494-
"right"
495-
} else {
496-
"left"
497-
};
498-
let hir_id = source_scope_local_data[source_info.scope].lint_root;
499-
self.tcx.lint_hir(
500-
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
501-
hir_id,
502-
span,
503-
&format!("attempt to shift {} with overflow", dir));
504-
return None;
502+
// If overflow checking is enabled (like in debug mode by default),
503+
// then we'll already catch overflow when we evaluate the `Assert` statement
504+
// in MIR. However, if overflow checking is disabled, then there won't be any
505+
// `Assert` statement and so we have to do additional checking here.
506+
if !overflow_check {
507+
self.use_ecx(source_info, |this| {
508+
let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
509+
let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
510+
511+
if overflow {
512+
let err = err_panic!(Overflow(*op)).into();
513+
return Err(err);
514+
}
515+
516+
Ok(())
517+
})?;
505518
}
506519
}
507-
self.use_ecx(source_info, |this| {
508-
let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
509-
let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;
510-
511-
// We check overflow in debug mode already
512-
// so should only check in release mode.
513-
if !this.tcx.sess.overflow_checks() && overflow {
514-
let err = err_panic!(Overflow(*op)).into();
515-
return Err(err);
516-
}
517520

518-
Ok(())
519-
})?;
520-
} else if let Rvalue::Ref(_, _, place) = rvalue {
521-
trace!("checking Ref({:?})", place);
521+
// Work around: avoid ICE in miri.
522522
// FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
523-
// from a function argument that hasn't been assigned to in this function.
524-
if let Place {
525-
base: PlaceBase::Local(local),
526-
projection: box []
527-
} = place {
523+
// from a function argument that hasn't been assigned to in this function. The main
524+
// issue is if an arg is a fat-pointer, miri `expects()` to be able to read the value
525+
// of that pointer to get size info. However, since this is `ConstProp`, that argument
526+
// doesn't actually have a backing value and so this causes an ICE.
527+
Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => {
528+
trace!("checking Ref({:?})", place);
528529
let alive =
529530
if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
530531
true
@@ -535,6 +536,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
535536
return None;
536537
}
537538
}
539+
540+
// Work around: avoid extra unnecessary locals.
541+
// FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
542+
// `SimplifyLocals` doesn't know it can remove.
543+
Rvalue::Aggregate(_, operands) if operands.len() == 0 => {
544+
return None;
545+
}
546+
547+
_ => { }
538548
}
539549

540550
self.use_ecx(source_info, |this| {

‎src/test/compile-fail/consts/const-err3.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ fn main() {
1414
//~^ ERROR const_err
1515
let _e = [5u8][1];
1616
//~^ ERROR const_err
17+
//~| ERROR this expression will panic at runtime
1718
black_box(b);
1819
black_box(c);
1920
black_box(d);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// compile-flags: -O
2+
3+
fn main() {
4+
let x = (0, 1, 2).1 + 0;
5+
}
6+
7+
// END RUST SOURCE
8+
// START rustc.main.ConstProp.before.mir
9+
// bb0: {
10+
// ...
11+
// _3 = (const 0i32, const 1i32, const 2i32);
12+
// _2 = (_3.1: i32);
13+
// _1 = Add(move _2, const 0i32);
14+
// ...
15+
// }
16+
// END rustc.main.ConstProp.before.mir
17+
// START rustc.main.ConstProp.after.mir
18+
// bb0: {
19+
// ...
20+
// _3 = (const 0i32, const 1i32, const 2i32);
21+
// _2 = const 1i32;
22+
// _1 = Add(move _2, const 0i32);
23+
// ...
24+
// }
25+
// END rustc.main.ConstProp.after.mir

‎src/test/mir-opt/const_prop/boxes.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// compile-flags: -O
2+
// ignore-emscripten compiled with panic=abort by default
3+
// ignore-wasm32
4+
// ignore-wasm64
5+
6+
#![feature(box_syntax)]
7+
8+
// Note: this test verifies that we, in fact, do not const prop `box`
9+
10+
fn main() {
11+
let x = *(box 42) + 0;
12+
}
13+
14+
// END RUST SOURCE
15+
// START rustc.main.ConstProp.before.mir
16+
// bb0: {
17+
// ...
18+
// _4 = Box(i32);
19+
// (*_4) = const 42i32;
20+
// _3 = move _4;
21+
// ...
22+
// _2 = (*_3);
23+
// _1 = Add(move _2, const 0i32);
24+
// ...
25+
// drop(_3) -> [return: bb2, unwind: bb1];
26+
// }
27+
// bb1 (cleanup): {
28+
// resume;
29+
// }
30+
// bb2: {
31+
// ...
32+
// _0 = ();
33+
// ...
34+
// }
35+
// END rustc.main.ConstProp.before.mir
36+
// START rustc.main.ConstProp.after.mir
37+
// bb0: {
38+
// ...
39+
// _4 = Box(i32);
40+
// (*_4) = const 42i32;
41+
// _3 = move _4;
42+
// ...
43+
// _2 = (*_3);
44+
// _1 = Add(move _2, const 0i32);
45+
// ...
46+
// drop(_3) -> [return: bb2, unwind: bb1];
47+
// }
48+
// bb1 (cleanup): {
49+
// resume;
50+
// }
51+
// bb2: {
52+
// ...
53+
// _0 = ();
54+
// ...
55+
// }
56+
// END rustc.main.ConstProp.after.mir
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// compile-flags: -O
2+
3+
fn main() {
4+
let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
5+
}
6+
7+
// END RUST SOURCE
8+
// START rustc.main.ConstProp.before.mir
9+
// bb0: {
10+
// ...
11+
// _3 = std::option::Option::<bool>::Some(const true,);
12+
// _4 = discriminant(_3);
13+
// switchInt(move _4) -> [1isize: bb3, otherwise: bb2];
14+
// }
15+
// bb1: {
16+
// _2 = const 42i32;
17+
// goto -> bb4;
18+
// }
19+
// bb2: {
20+
// _2 = const 10i32;
21+
// goto -> bb4;
22+
// }
23+
// bb3: {
24+
// switchInt(((_3 as Some).0: bool)) -> [false: bb2, otherwise: bb1];
25+
// }
26+
// bb4: {
27+
// _1 = Add(move _2, const 0i32);
28+
// ...
29+
// }
30+
// END rustc.main.ConstProp.before.mir
31+
// START rustc.main.ConstProp.after.mir
32+
// bb0: {
33+
// ...
34+
// _3 = const Scalar(0x01) : std::option::Option<bool>;
35+
// _4 = const 1isize;
36+
// switchInt(const 1isize) -> [1isize: bb3, otherwise: bb2];
37+
// }
38+
// bb1: {
39+
// _2 = const 42i32;
40+
// goto -> bb4;
41+
// }
42+
// bb2: {
43+
// _2 = const 10i32;
44+
// goto -> bb4;
45+
// }
46+
// bb3: {
47+
// switchInt(const true) -> [false: bb2, otherwise: bb1];
48+
// }
49+
// bb4: {
50+
// _1 = Add(move _2, const 0i32);
51+
// ...
52+
// }
53+
// END rustc.main.ConstProp.after.mir

‎src/test/mir-opt/const_prop/repeat.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// compile-flags: -O
2+
3+
fn main() {
4+
let x: u32 = [42; 8][2] + 0;
5+
}
6+
7+
// END RUST SOURCE
8+
// START rustc.main.ConstProp.before.mir
9+
// bb0: {
10+
// ...
11+
// _3 = [const 42u32; 8];
12+
// ...
13+
// _4 = const 2usize;
14+
// _5 = const 8usize;
15+
// _6 = Lt(_4, _5);
16+
// assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
17+
// }
18+
// bb1: {
19+
// _2 = _3[_4];
20+
// _1 = Add(move _2, const 0u32);
21+
// ...
22+
// return;
23+
// }
24+
// END rustc.main.ConstProp.before.mir
25+
// START rustc.main.ConstProp.after.mir
26+
// bb0: {
27+
// ...
28+
// _6 = const true;
29+
// assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
30+
// }
31+
// bb1: {
32+
// _2 = const 42u32;
33+
// _1 = Add(move _2, const 0u32);
34+
// ...
35+
// return;
36+
// }
37+
// END rustc.main.ConstProp.after.mir

‎src/test/run-fail/overflowing-rsh-5.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// compile-flags: -C debug-assertions
33

44
#![warn(exceeding_bitshifts)]
5+
#![warn(const_err)]
56

67
fn main() {
78
let _n = 1i64 >> [64][0];

‎src/test/run-fail/overflowing-rsh-6.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// compile-flags: -C debug-assertions
33

44
#![warn(exceeding_bitshifts)]
5+
#![warn(const_err)]
56
#![feature(const_indexing)]
67

78
fn main() {

‎src/test/ui/consts/const-err2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ fn main() {
2323
//~^ ERROR const_err
2424
let _e = [5u8][1];
2525
//~^ ERROR index out of bounds
26+
//~| ERROR this expression will panic at runtime
2627
black_box(a);
2728
black_box(b);
2829
black_box(c);

‎src/test/ui/consts/const-err2.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1
3434
LL | let _e = [5u8][1];
3535
| ^^^^^^^^
3636

37-
error: aborting due to 5 previous errors
37+
error: this expression will panic at runtime
38+
--> $DIR/const-err2.rs:24:14
39+
|
40+
LL | let _e = [5u8][1];
41+
| ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
42+
43+
error: aborting due to 6 previous errors
3844

‎src/test/ui/consts/const-err3.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ fn main() {
2323
//~^ ERROR const_err
2424
let _e = [5u8][1];
2525
//~^ ERROR const_err
26+
//~| ERROR this expression will panic at runtime
2627
black_box(a);
2728
black_box(b);
2829
black_box(c);

‎src/test/ui/consts/const-err3.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1
3434
LL | let _e = [5u8][1];
3535
| ^^^^^^^^
3636

37-
error: aborting due to 5 previous errors
37+
error: this expression will panic at runtime
38+
--> $DIR/const-err3.rs:24:14
39+
|
40+
LL | let _e = [5u8][1];
41+
| ^^^^^^^^ index out of bounds: the len is 1 but the index is 1
42+
43+
error: aborting due to 6 previous errors
3844

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// run-pass
2+
3+
#![allow(dead_code)]
4+
5+
enum Empty { }
6+
enum Test1 {
7+
A(u8),
8+
B(Empty),
9+
}
10+
enum Test2 {
11+
A(u8),
12+
B(Empty),
13+
C,
14+
}
15+
16+
fn bar() -> Option<Empty> {
17+
None
18+
}
19+
20+
fn main() {
21+
if let Some(x) = bar() {
22+
Test1::B(x);
23+
}
24+
25+
if let Some(x) = bar() {
26+
Test2::B(x);
27+
}
28+
}

‎src/test/ui/consts/const-prop-ice.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
fn main() {
22
[0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
3+
//~| ERROR this expression will panic at runtime
34
}

‎src/test/ui/consts/const-prop-ice.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ LL | [0; 3][3u64 as usize];
66
|
77
= note: `#[deny(const_err)]` on by default
88

9-
error: aborting due to previous error
9+
error: this expression will panic at runtime
10+
--> $DIR/const-prop-ice.rs:2:5
11+
|
12+
LL | [0; 3][3u64 as usize];
13+
| ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3
14+
15+
error: aborting due to 2 previous errors
1016

‎src/test/ui/issues/issue-54348.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
fn main() {
22
[1][0u64 as usize];
33
[1][1.5 as usize]; //~ ERROR index out of bounds
4+
//~| ERROR this expression will panic at runtime
45
[1][1u64 as usize]; //~ ERROR index out of bounds
6+
//~| ERROR this expression will panic at runtime
57
}

‎src/test/ui/issues/issue-54348.stderr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,23 @@ LL | [1][1.5 as usize];
66
|
77
= note: `#[deny(const_err)]` on by default
88

9+
error: this expression will panic at runtime
10+
--> $DIR/issue-54348.rs:3:5
11+
|
12+
LL | [1][1.5 as usize];
13+
| ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
14+
915
error: index out of bounds: the len is 1 but the index is 1
10-
--> $DIR/issue-54348.rs:4:5
16+
--> $DIR/issue-54348.rs:5:5
1117
|
1218
LL | [1][1u64 as usize];
1319
| ^^^^^^^^^^^^^^^^^^
1420

15-
error: aborting due to 2 previous errors
21+
error: this expression will panic at runtime
22+
--> $DIR/issue-54348.rs:5:5
23+
|
24+
LL | [1][1u64 as usize];
25+
| ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1
26+
27+
error: aborting due to 4 previous errors
1628

‎src/test/ui/lint/lint-exceeding-bitshifts2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() {
88
let n = 1u8 << (4+3);
99
let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow
1010
let n = 1i64 >> [63][0];
11-
let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation
11+
let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow
1212

1313
#[cfg(target_pointer_width = "32")]
1414
const BITS: usize = 32;

‎src/test/ui/lint/lint-exceeding-bitshifts2.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ note: lint level defined here
1010
LL | #![deny(exceeding_bitshifts, const_err)]
1111
| ^^^^^^^^^^^^^^^^^^^
1212

13+
error: attempt to shift right with overflow
14+
--> $DIR/lint-exceeding-bitshifts2.rs:11:15
15+
|
16+
LL | let n = 1i64 >> [64][0];
17+
| ^^^^^^^^^^^^^^^
18+
1319
error: attempt to shift left with overflow
1420
--> $DIR/lint-exceeding-bitshifts2.rs:17:15
1521
|
@@ -22,5 +28,5 @@ error: attempt to shift left with overflow
2228
LL | let n = 1_usize << BITS;
2329
| ^^^^^^^^^^^^^^^
2430

25-
error: aborting due to 3 previous errors
31+
error: aborting due to 4 previous errors
2632

0 commit comments

Comments
 (0)
Please sign in to comment.