8000 Rollup of 5 pull requests by Centril · Pull Request #64955 · rust-lang/rust · GitHub
[go: up one dir, main page]

Skip to content

Rollup of 5 pull requests #64955

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 37 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a3639c6
Make all alt builders produce parallel-enabled compilers
Mark-Simulacrum Sep 23, 2019
d2c0d10
[const-prop] Handle MIR Rvalue::Repeat
wesleywiser Sep 14, 2019
f290467
syntax: cleanup method parsing.
Centril Sep 29, 2019
378cc98
syntax: `is_named_argument` -> `is_named_param`.
Centril Sep 29, 2019
4fa9c3b
syntax refactor `parse_fn_params`
Centril Sep 29, 2019
40dc9da
syntax refactor `parse_self_param` (1)
Centril Sep 29, 2019
f688f8a
syntax refactor `parse_self_param` (2)
Centril Sep 29, 2019
ac454e9
syntax refactor `parse_self_param` (3)
Centril Sep 30, 2019
4306d00
syntax refactor `parse_self_param` (4)
Centril Sep 30, 2019
0492302
syntax refactor `parse_self_param` (5)
Centril Sep 30, 2019
347deac
syntax: reorder param parsing to make more sense.
Centril Sep 30, 2019
d9d0e5d
syntax: cleanup `parse_fn_decl`.
Centril Sep 30, 2019
5b80ead
syntax: misc cleanup
Centril Sep 30, 2019
66bf323
syntax: cleanup `parse_visibility`.
Centril Sep 30, 2019
573a8d8
syntax: extract `error_on_invalid_abi`.
Centril Sep 30, 2019
258e86a
syntax: fuse more code paths together.
Centril Sep 30, 2019
bea404f
syntax: stylistic cleanup in item parsing.
Centril Sep 30, 2019
151ce96
syntax: reduce repetition in fn parsing.
Centril Sep 30, 2019
b0b073c
Self-Profiling: Refactor SelfProfiler API to be RAII based where poss…
michaelwoerister Sep 27, 2019
d942622
Self-Profiling: Make names of existing events more consistent and use…
michaelwoerister Sep 27, 2019
85f2945
[const-prop] Handle MIR Rvalue::Aggregates
wesleywiser Sep 14, 2019
ea78010
[const-prop] Handle MIR Rvalue::Discriminant
wesleywiser Sep 15, 2019
b3234a3
[const-prop] Handle MIR Rvalue::Box
wesleywiser Sep 15, 2019
5804c3b
Cleanup const_prop() some
wesleywiser Sep 15, 2019
1a1067d
Make the default parallelism 1
Mark-Simulacrum Sep 30, 2019
df298b4
syntax: document some methods.
Centril Oct 1, 2019
30647d1
syntax: put helpers of `parse_self_param` in the method.
Centril Oct 1, 2019
49780d2
syntax: merge things back into `parse_visibility`.
Centril Oct 1, 2019
e046904
syntax: de-closure-ify `check_or_expected`.
Centril Oct 1, 2019
5c5dd80
syntax: reformat passing of `FnHeader` to `parse_item_fn`.
Centril Oct 1, 2019
3237ded
Add long error explanation for E0495
GuillaumeGomez Sep 12, 2019
be89e52
update ui tests
GuillaumeGomez Sep 12, 2019
5ac7e21
Rollup merge of #64404 - GuillaumeGomez:err-E0495, r=cramertj
Centril Oct 1, 2019
525159b
Rollup merge of #64722 - Mark-Simulacrum:alt-parallel, r=alexcrichton
Centril Oct 1, 2019
e5bef70
Rollup merge of #64840 - michaelwoerister:self-profiling-raii-refacto…
Centril Oct 1, 2019
4707702
Rollup merge of #64890 - wesleywiser:const_prop_rvalue, r=oli-obk
Centril Oct 1, 2019
35e8755
Rollup merge of #64910 - Centril:params-cleanup, r=petrochenkov
Centril Oct 1, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 78 additions & 86 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc::hir::def::DefKind;
use rustc::hir::def_id::DefId;
use rustc::mir::{
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
Local, NullOp, UnOp, StatementKind, Statement, LocalKind,
Local, UnOp, StatementKind, Statement, LocalKind,
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp,
SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock,
};
Expand Down Expand Up @@ -118,7 +118,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
struct ConstPropMachine;

impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
type MemoryKinds= !;
type MemoryKinds = !;
type PointerTag = ();
type ExtraFnVal = !;

Expand Down Expand Up @@ -459,97 +459,81 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
) -> Option<Const<'tcx>> {
let span = source_info.span;

// if this isn't a supported operation, then return None
match rvalue {
Rvalue::Repeat(..) |
Rvalue::Aggregate(..) |
Rvalue::NullaryOp(NullOp::Box, _) |
Rvalue::Discriminant(..) => return None,

Rvalue::Use(_) |
Rvalue::Len(_) |
Rvalue::Cast(..) |
Rvalue::NullaryOp(..) |
Rvalue::CheckedBinaryOp(..) |
Rvalue::Ref(..) |
Rvalue::UnaryOp(..) |
Rvalue::BinaryOp(..) => { }
}

// perform any special checking for specific Rvalue types
if let Rvalue::UnaryOp(op, arg) = rvalue {
trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
let overflow_check = self.tcx.sess.overflow_checks();

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

if ty.is_integral() {
let arg = this.ecx.eval_operand(arg, None)?;
let prim = this.ecx.read_immediate(arg)?;
// Need to do overflow check here: For actual CTFE, MIR
// generation emits code that does this before calling the op.
if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
throw_panic!(OverflowNeg)
match rvalue {
Rvalue::UnaryOp(UnOp::Neg, arg) => {
trace!("checking UnaryOp(op = Neg, arg = {:?})", arg);
let overflow_check = self.tcx.sess.overflow_checks();

self.use_ecx(source_info, |this| {
// We check overflow in debug mode already
// so should only check in release mode.
if !overflow_check {
let ty = arg.ty(&this.local_decls, this.tcx);

if ty.is_integral() {
let arg = this.ecx.eval_operand(arg, None)?;
let prim = this.ecx.read_immediate(arg)?;
// Need to do overflow check here: For actual CTFE, MIR
// generation emits code that does this before calling the op.
if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
throw_panic!(OverflowNeg)
}
}
}
}

Ok(())
})?;
} else if let Rvalue::BinaryOp(op, left, right) = rvalue {
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);

let r = self.use_ecx(source_info, |this| {
this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
})?;
if *op == BinOp::Shr || *op == BinOp::Shl {
let left_bits = place_layout.size.bits();
let right_size = r.layout.size;
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
let source_scope_local_data = match self.source_scope_local_data {
ClearCrossCrate::Set(ref data) => data,
ClearCrossCrate::Clear => return None,
};
let dir = if *op == BinOp::Shr {
"right"
} else {
"left"
};
let hir_id = source_scope_local_data[source_info.scope].lint_root;
self.tcx.lint_hir(
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
hir_id,
span,
&format!("attempt to shift {} with overflow", dir));
return None;
}
Ok(())
})?;
}
self.use_ecx(source_info, |this| {
let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;

// We check overflow in debug mode already
// so should only check in release mode.
if !this.tcx.sess.overflow_checks() && overflow {
let err = err_panic!(Overflow(*op)).into();
return Err(err);

Rvalue::BinaryOp(op, left, right) => {
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);

let r = self.use_ecx(source_info, |this| {
this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
})?;
if *op == BinOp::Shr || *op == BinOp::Shl {
let left_bits = place_layout.size.bits();
let right_size = r.layout.size;
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
if r_bits.ok().map_or(false, |b| b >= left_bits as u128) {
let source_scope_local_data = match self.source_scope_local_data {
ClearCrossCrate::Set(ref data) => data,
ClearCrossCrate::Clear => return None,
};
let dir = if *op == BinOp::Shr {
"right"
} else {
"left"
};
let hir_id = source_scope_local_data[source_info.scope].lint_root;
self.tcx.lint_hir(
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
hir_id,
span,
&format!("attempt to shift {} with overflow", dir));
return None;
}
}
self.use_ecx(source_info, |this| {
let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?;

// We check overflow in debug mode already
// so should only check in release mode.
if !this.tcx.sess.overflow_checks() && overflow {
let err = err_panic!(Overflow(*op)).into();
return Err(err);
}

Ok(())
})?;
} else if let Rvalue::Ref(_, _, place) = rvalue {
trace!("checking Ref({:?})", place);
// FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
// from a function argument that hasn't been assigned to in this function.
if let Place {
base: PlaceBase::Local(local),
projection: box []
} = place {
Ok(())
})?;
}

Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => {
trace!("checking Ref({:?})", place);
// FIXME(wesleywiser) we don't currently handle the case where we try to make a ref
// from a function argument that hasn't been assigned to in this function.
let alive =
if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value {
true
Expand All @@ -560,6 +544,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
}

Rvalue::Aggregate(_, operands) if operands.len() == 0 => {
// FIXME(wesleywiser): const eval will turn this into a `const Scalar(<ZST>)` that
// `SimplifyLocals` doesn't know it can remove.
return None;
}

_ => { }
}

self.use_ecx(source_info, |this| {
Expand Down
1 change: 1 addition & 0 deletions src/test/compile-fail/consts/const-err3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ fn main() {
//~^ ERROR const_err
let _e = [5u8][1];
//~^ ERROR const_err
//~| ERROR this expression will panic at runtime
black_box(b);
black_box(c);
black_box(d);
Expand Down
25 changes: 25 additions & 0 deletions src/test/mir-opt/const_prop/aggregate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// compile-flags: -O

fn main() {
let x = (0, 1, 2).1 + 0;
}

// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _3 = (const 0i32, const 1i32, const 2i32);
// _2 = (_3.1: i32);
// _1 = Add(move _2, const 0i32);
// ...
// }
// END rustc.main.ConstProp.before.mir
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _3 = (const 0i32, const 1i32, const 2i32);
// _2 = const 1i32;
// _1 = Add(move _2, const 0i32);
// ...
// }
// END rustc.main.ConstProp.after.mir
53 changes: 53 additions & 0 deletions src/test/mir-opt/const_prop/boxes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// compile-flags: -O

#![feature(box_syntax)]

// Note: this test verifies that we, in fact, do not const prop `box`

fn main() {
let x = *(box 42) + 0;
}

// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _4 = Box(i32);
// (*_4) = const 42i32;
// _3 = move _4;
// ...
// _2 = (*_3);
// _1 = Add(move _2, const 0i32);
// ...
// drop(_3) -> [return: bb2, unwind: bb1];
// }
// bb1 (cleanup): {
// resume;
// }
// bb2: {
// ...
// _0 = ();
// ...
// }
// END rustc.main.ConstProp.before.mir
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _4 = Box(i32);
// (*_4) = const 42i32;
// _3 = move _4;
// ...
// _2 = (*_3);
// _1 = Add(move _2, const 0i32);
// ...
// drop(_3) -> [return: bb2, unwind: bb1];
// }
// bb1 (cleanup): {
// resume;
// }
// bb2: {
// ...
// _0 = ();
// ...
// }
// END rustc.main.ConstProp.after.mir
53 changes: 53 additions & 0 deletions src/test/mir-opt/const_prop/discriminant.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// compile-flags: -O

fn main() {
let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
}

// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _3 = std::option::Option::<bool>::Some(const true,);
// _4 = discriminant(_3);
// switchInt(move _4) -> [1isize: bb3, otherwise: bb2];
// }
// bb1: {
// _2 = const 42i32;
// goto -> bb4;
// }
// bb2: {
// _2 = const 10i32;
// goto -> bb4;
// }
// bb3: {
// switchInt(((_3 as Some).0: bool)) -> [false: bb2, otherwise: bb1];
// }
// bb4: {
// _1 = Add(move _2, const 0i32);
// ...
// }
// END rustc.main.ConstProp.before.mir
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _3 = const Scalar(0x01) : std::option::Option<bool>;
// _4 = const 1isize;
// switchInt(const 1isize) -> [1isize: bb3, otherwise: bb2];
// }
// bb1: {
// _2 = const 42i32;
// goto -> bb4;
// }
// bb2: {
// _2 = const 10i32;
// goto -> bb4;
// }
// bb3: {
// switchInt(const true) -> [false: bb2, otherwise: bb1];
// }
// bb4: {
// _1 = Add(move _2, const 0i32);
// ...
// }
// END rustc.main.ConstProp.after.mir
37 changes: 37 additions & 0 deletions src/test/mir-opt/const_prop/repeat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// compile-flags: -O

fn main() {
let x: u32 = [42; 8][2] + 0;
}

// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _3 = [const 42u32; 8];
// ...
// _4 = const 2usize;
// _5 = const 8usize;
// _6 = Lt(_4, _5);
// assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
// }
// bb1: {
// _2 = _3[_4];
// _1 = Add(move _2, const 0u32);
// ...
// return;
// }
// END rustc.main.ConstProp.before.mir
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _6 = const true;
// assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1;
// }
// bb1: {
// _2 = const 42u32;
// _1 = Add(move _2, const 0u32);
// ...
// return;
// }
// END rustc.main.ConstProp.after.mir
1 change: 1 addition & 0 deletions src/test/run-fail/overflowing-rsh-5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// compile-flags: -C debug-assertions

#![warn(exceeding_bitshifts)]
#![warn(const_err)]

fn main() {
let _n = 1i64 >> [64][0];
Expand Down
1 change: 1 addition & 0 deletions src/test/run-fail/overflowing-rsh-6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// compile-flags: -C debug-assertions

#![warn(exceeding_bitshifts)]
#![warn(const_err)]
#![feature(const_indexing)]

fn main() {
Expand Down
Loading
0