Skip to content

Commit

Permalink
Auto merge of #65661 - JohnTitor:rollup-68la1fq, r=JohnTitor
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #65544 (Added doc on keyword break)
 - #65620 (Correctly note code as Ok not error for E0573)
 - #65624 ([mir-opt] Improve SimplifyLocals pass so it can remove unused consts)
 - #65650 (use unwrap_or in lint code)
 - #65652 (Fix `canonicalize_const_var` leaking inference variables)

Failed merges:

r? @ghost
  • Loading branch information
bors committed Oct 21, 2019
2 parents b7a9c28 + 1c94a44 commit 10f12fe
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 57 deletions.
2 changes: 1 addition & 1 deletion src/librustc/infer/canonical/canonicalizer.rs
Expand Up @@ -701,7 +701,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
self.tcx().mk_const(
ty::Const {
val: ConstValue::Infer(InferConst::Canonical(self.binder_index, var.into())),
ty: const_var.ty,
ty: self.fold_ty(const_var.ty),
}
)
}
Expand Down
6 changes: 1 addition & 5 deletions src/librustc/lint/levels.rs
Expand Up @@ -202,11 +202,7 @@ impl<'a> LintLevelsBuilder<'a> {
let meta = unwrap_or!(attr.meta(), continue);
attr::mark_used(attr);

let mut metas = if let Some(metas) = meta.meta_item_list() {
metas
} else {
continue;
};
let mut metas = unwrap_or!(meta.meta_item_list(), continue);

if metas.is_empty() {
// FIXME (#55112): issue unused-attributes lint for `#[level()]`
Expand Down
26 changes: 9 additions & 17 deletions src/librustc_mir/transform/const_prop.rs
Expand Up @@ -431,7 +431,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
place_layout: TyLayout<'tcx>,
source_info: SourceInfo,
place: &Place<'tcx>,
) -> Option<Const<'tcx>> {
) -> Option<()> {
let span = source_info.span;

let overflow_check = self.tcx.sess.overflow_checks();
Expand Down Expand Up @@ -540,20 +540,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
}

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

_ => { }
}

self.use_ecx(source_info, |this| {
trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place);
this.ecx.eval_rvalue_into_place(rvalue, place)?;
this.ecx.eval_place_to_op(place, Some(place_layout))
Ok(())
})
}

Expand Down Expand Up @@ -717,24 +710,23 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
base: PlaceBase::Local(local),
projection: box [],
} = *place {
if let Some(value) = self.const_prop(rval,
place_layout,
statement.source_info,
place) {
trace!("checking whether {:?} can be stored to {:?}", value, local);
let source = statement.source_info;
if let Some(()) = self.const_prop(rval, place_layout, source, place) {
if self.can_const_prop[local] {
trace!("stored {:?} to {:?}", value, local);
assert_eq!(self.get_const(local), Some(value));
trace!("propagated into {:?}", local);

if self.should_const_prop() {
let value =
self.get_const(local).expect("local was dead/uninitialized");
trace!("replacing {:?} with {:?}", rval, value);
self.replace_with_const(
rval,
value,
statement.source_info,
);
}
} else {
trace!("can't propagate {:?} to {:?}", value, local);
trace!("can't propagate into {:?}", local);
self.remove_const(local);
}
}
Expand Down
76 changes: 54 additions & 22 deletions src/librustc_mir/transform/simplify.rs
Expand Up @@ -31,7 +31,7 @@ use rustc_index::bit_set::BitSet;
use rustc_index::vec::{Idx, IndexVec};
use rustc::ty::TyCtxt;
use rustc::mir::*;
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext};
use rustc::mir::visit::{MutVisitor, Visitor, PlaceContext, MutatingUseContext};
use rustc::session::config::DebugInfo;
use std::borrow::Cow;
use crate::transform::{MirPass, MirSource};
Expand Down Expand Up @@ -293,23 +293,31 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
pub struct SimplifyLocals;

impl<'tcx> MirPass<'tcx> for SimplifyLocals {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()) };
marker.visit_body(body);
// Return pointer and arguments are always live
marker.locals.insert(RETURN_PLACE);
for arg in body.args_iter() {
marker.locals.insert(arg);
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
trace!("running SimplifyLocals on {:?}", source);
let locals = {
let mut marker = DeclMarker {
locals: BitSet::new_empty(body.local_decls.len()),
body,
};
marker.visit_body(body);
// Return pointer and arguments are always live
marker.locals.insert(RETURN_PLACE);
for arg in body.args_iter() {
marker.locals.insert(arg);
}

// We may need to keep dead user variables live for debuginfo.
if tcx.sess.opts.debuginfo == DebugInfo::Full {
for local in body.vars_iter() {
marker.locals.insert(local);
// We may need to keep dead user variables live for debuginfo.
if tcx.sess.opts.debuginfo == DebugInfo::Full {
for local in body.vars_iter() {
marker.locals.insert(local);
}
}
}

let map = make_local_map(&mut body.local_decls, marker.locals);
marker.locals
};

let map = make_local_map(&mut body.local_decls, locals);
// Update references to all vars and tmps now
LocalUpdater { map }.visit_body(body);
body.local_decls.shrink_to_fit();
Expand All @@ -334,18 +342,35 @@ fn make_local_map<V>(
map
}

struct DeclMarker {
struct DeclMarker<'a, 'tcx> {
pub locals: BitSet<Local>,
pub body: &'a Body<'tcx>,
}

impl<'tcx> Visitor<'tcx> for DeclMarker {
fn visit_local(&mut self, local: &Local, ctx: PlaceContext, _: Location) {
impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
fn visit_local(&mut self, local: &Local, ctx: PlaceContext, location: Location) {
// Ignore storage markers altogether, they get removed along with their otherwise unused
// decls.
// FIXME: Extend this to all non-uses.
if !ctx.is_storage_marker() {
self.locals.insert(*local);
if ctx.is_storage_marker() {
return;
}

// Ignore stores of constants because `ConstProp` and `CopyProp` can remove uses of many
// of these locals. However, if the local is still needed, then it will be referenced in
// another place and we'll mark it as being used there.
if ctx == PlaceContext::MutatingUse(MutatingUseContext::Store) {
let stmt =
&self.body.basic_blocks()[location.block].statements[location.statement_index];
if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) = &stmt.kind {
if p.as_local().is_some() {
trace!("skipping store of const value {:?} to {:?}", c, local);
return;
}
}
}

self.locals.insert(*local);
}
}

Expand All @@ -357,9 +382,16 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater {
fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
// Remove unnecessary StorageLive and StorageDead annotations.
data.statements.retain(|stmt| {
match stmt.kind {
match &stmt.kind {
StatementKind::StorageLive(l) | StatementKind::StorageDead(l) => {
self.map[l].is_some()
self.map[*l].is_some()
}
StatementKind::Assign(box (place, _)) => {
if let Some(local) = place.as_local() {
self.map[local].is_some()
} else {
true
}
}
_ => true
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/error_codes.rs
Expand Up @@ -1682,7 +1682,7 @@ enum Wizard {
}
trait Isengard {
fn wizard(w: Wizard) { // error!
fn wizard(w: Wizard) { // ok!
match w {
Wizard::Saruman => {
// do something
Expand Down
67 changes: 65 additions & 2 deletions src/libstd/keyword_docs.rs
Expand Up @@ -33,9 +33,72 @@ mod as_keyword { }
//
/// Exit early from a loop.
///
/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
/// When `break` is encountered, execution of the associated loop body is
/// immediately terminated.
///
/// ```rust
/// let mut last = 0;
///
/// for x in 1..100 {
/// if x > 12 {
/// break;
/// }
/// last = x;
/// }
///
/// assert_eq!(last, 12);
/// println!("{}", last);
/// ```
///
/// A break expression is normally associated with the innermost loop enclosing the
/// `break` but a label can be used to specify which enclosing loop is affected.
///
///```rust
/// 'outer: for i in 1..=5 {
/// println!("outer iteration (i): {}", i);
///
/// 'inner: for j in 1..=200 {
/// println!(" inner iteration (j): {}", j);
/// if j >= 3 {
/// // breaks from inner loop, let's outer loop continue.
/// break;
/// }
/// if i >= 2 {
/// // breaks from outer loop, and directly to "Bye".
/// break 'outer;
/// }
/// }
/// }
/// println!("Bye.");
///```
///
/// When associated with `loop`, a break expression may be used to return a value from that loop.
/// This is only valid with `loop` and not with any other type of loop.
/// If no value is specified, `break;` returns `()`.
/// Every `break` within a loop must return the same type.
///
/// ```rust
/// let (mut a, mut b) = (1, 1);
/// let result = loop {
/// if b > 10 {
/// break b;
/// }
/// let c = a + b;
/// a = b;
/// b = c;
/// };
/// // first number in Fibonacci sequence over 10:
/// assert_eq!(result, 13);
/// println!("{}", result);
/// ```
///
/// For more details consult the [Reference on "break expression"] and the [Reference on "break and
/// loop values"].
///
/// [Reference on "break expression"]: ../reference/expressions/loop-expr.html#break-expressions
/// [Reference on "break and loop values"]:
/// ../reference/expressions/loop-expr.html#break-and-loop-values
///
/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
mod break_keyword { }

#[doc(keyword = "const")]
Expand Down
14 changes: 14 additions & 0 deletions src/test/incremental/const-generics/issue-61338.rs
@@ -0,0 +1,14 @@
// revisions:rpass1

#![feature(const_generics)]

struct Struct<T>(T);

impl<T, const N: usize> Struct<[T; N]> {
fn f() {}
fn g() { Self::f(); }
}

fn main() {
Struct::<[u32; 3]>::g();
}
16 changes: 16 additions & 0 deletions src/test/incremental/const-generics/issue-61516.rs
@@ -0,0 +1,16 @@
// revisions:rpass1

#![feature(const_generics)]

struct FakeArray<T, const N: usize>(T);

impl<T, const N: usize> FakeArray<T, { N }> {
fn len(&self) -> usize {
N
}
}

fn main() {
let fa = FakeArray::<u32, { 32 }>(1);
assert_eq!(fa.len(), 32);
}
12 changes: 12 additions & 0 deletions src/test/incremental/const-generics/issue-62536.rs
@@ -0,0 +1,12 @@
// revisions:cfail1
#![feature(const_generics)]
//[cfail1]~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

struct S<T, const N: usize>([T; N]);

fn f<T, const N: usize>(x: T) -> S<T, {N}> { panic!() }

fn main() {
f(0u8);
//[cfail1]~^ ERROR type annotations needed
}
11 changes: 11 additions & 0 deletions src/test/incremental/const-generics/issue-64087.rs
@@ -0,0 +1,11 @@
// revisions:cfail1
#![feature(const_generics)]
//[cfail1]~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash

fn combinator<T, const S: usize>() -> [T; S] {}
//[cfail1]~^ ERROR mismatched types

fn main() {
combinator().into_iter();
//[cfail1]~^ ERROR type annotations needed
}
14 changes: 14 additions & 0 deletions src/test/incremental/const-generics/issue-65623.rs
@@ -0,0 +1,14 @@
// revisions:rpass1
#![feature(const_generics)]

pub struct Foo<T, const N: usize>([T; 0]);

impl<T, const N: usize> Foo<T, {N}> {
pub fn new() -> Self {
Foo([])
}
}

fn main() {
let _: Foo<u32, 0> = Foo::new();
}
2 changes: 1 addition & 1 deletion src/test/incremental/hashes/for_loops.rs
Expand Up @@ -25,7 +25,7 @@ pub fn change_loop_body() {
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")]
#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")]
#[rustc_clean(cfg="cfail3")]
pub fn change_loop_body() {
let mut _x = 0;
Expand Down

0 comments on commit 10f12fe

Please sign in to comment.