Auto merge of #75016 - Manishearth:rollup-x553g7j, r=Manishearth

Rollup of 6 pull requests

Successful merges:

 - #74977 (Clean up E0741 error explanation)
 - #74981 (Some fixes for `plugin.md` in unstable-book)
 - #74983 (Replace a recursive algorithm with an iterative one and a stack.)
 - #74995 (Update the WASI libc build to LLVM 10.)
 - #74996 (submodules: update cargo from 974eb438d to 2d5c2381e)
 - #75007 (Clean up E0743 explanation)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-08-01 18:52:30 +00:00
commit de10abf50c
6 changed files with 75 additions and 57 deletions

View file

@ -4,10 +4,10 @@
set -ex set -ex
# Originally from https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz # Originally from https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz
curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
tar xJf - tar xJf -
export PATH=`pwd`/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH export PATH=`pwd`/clang+llvm-10.0.0-x86_64-linux-gnu-ubuntu-18.04/bin:$PATH
git clone https://github.com/WebAssembly/wasi-libc git clone https://github.com/WebAssembly/wasi-libc

View file

@ -45,42 +45,40 @@ that warns about any item named `lintme`.
extern crate rustc_ast; extern crate rustc_ast;
// Load rustc as a plugin to get macros // Load rustc as a plugin to get macros
#[macro_use]
extern crate rustc;
extern crate rustc_driver; extern crate rustc_driver;
#[macro_use]
extern crate rustc_lint;
#[macro_use]
extern crate rustc_session;
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
EarlyLintPassObject, LintArray};
use rustc_driver::plugin::Registry; use rustc_driver::plugin::Registry;
use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc_ast::ast; use rustc_ast::ast;
declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
struct Pass; declare_lint_pass!(Pass => [TEST_LINT]);
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(TEST_LINT)
}
}
impl EarlyLintPass for Pass { impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.as_str() == "lintme" { if it.ident.name.as_str() == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); cx.lint(TEST_LINT, |lint| {
lint.build("item is named 'lintme'").set_span(it.span).emit()
});
} }
} }
} }
#[plugin_registrar] #[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) { pub fn plugin_registrar(reg: &mut Registry) {
reg.register_early_lint_pass(box Pass as EarlyLintPassObject); reg.lint_store.register_lints(&[&TEST_LINT]);
reg.lint_store.register_early_pass(|| box Pass);
} }
``` ```
Then code like Then code like
```rust,ignore ```rust,ignore
#![feature(plugin)]
#![plugin(lint_plugin_test)] #![plugin(lint_plugin_test)]
fn lintme() { } fn lintme() { }
@ -107,7 +105,7 @@ The components of a lint plugin are:
Lint passes are syntax traversals, but they run at a late stage of compilation Lint passes are syntax traversals, but they run at a late stage of compilation
where type information is available. `rustc`'s [built-in where type information is available. `rustc`'s [built-in
lints](https://github.com/rust-lang/rust/blob/master/src/librustc/lint/builtin.rs) lints](https://github.com/rust-lang/rust/blob/master/src/librustc_session/lint/builtin.rs)
mostly use the same infrastructure as lint plugins, and provide examples of how mostly use the same infrastructure as lint plugins, and provide examples of how
to access type information. to access type information.

View file

@ -1,5 +1,6 @@
Only structural-match types (that is, types that derive `PartialEq` and `Eq`) A non-structural-match type was used as the type of a const generic parameter.
may be used as the types of const generic parameters.
Erroneous code example:
```compile_fail,E0741 ```compile_fail,E0741
#![feature(const_generics)] #![feature(const_generics)]
@ -9,12 +10,15 @@ struct A;
struct B<const X: A>; // error! struct B<const X: A>; // error!
``` ```
To fix this example, we derive `PartialEq` and `Eq`. Only structural-match types (that is, types that derive `PartialEq` and `Eq`)
may be used as the types of const generic parameters.
To fix the previous code example, we derive `PartialEq` and `Eq`:
``` ```
#![feature(const_generics)] #![feature(const_generics)]
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)] // We derive both traits here.
struct A; struct A;
struct B<const X: A>; // ok! struct B<const X: A>; // ok!

View file

@ -8,10 +8,9 @@ Erroneous code example:
fn foo2(x: u8, y: &...) {} // error! fn foo2(x: u8, y: &...) {} // error!
``` ```
Only foreign functions can use the C-variadic type (`...`). Only foreign functions can use the C-variadic type (`...`). In such functions,
In such functions, `...` may only occur non-nested. `...` may only occur non-nested. That is, `y: &'a ...` is not allowed.
That is, `y: &'a ...` is not allowed.
A C-variadic type is used to give an undefined number A C-variadic type is used to give an undefined number of parameters to a given
of parameters to a given function (like `printf` in C). function (like `printf` in C). The equivalent in Rust would be to use macros
The equivalent in Rust would be to use macros directly. directly (like `println!` for example).

View file

@ -33,6 +33,7 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use smallvec::SmallVec;
use std::borrow::Cow; use std::borrow::Cow;
pub struct SimplifyCfg { pub struct SimplifyCfg {
@ -172,9 +173,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
} }
} }
// Collapse a goto chain starting from `start` /// This function will return `None` if
fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) { /// * the block has statements
let mut terminator = match self.basic_blocks[*start] { /// * the block has a terminator other than `goto`
/// * the block has no terminator (meaning some other part of the current optimization stole it)
fn take_terminator_if_simple_goto(&mut self, bb: BasicBlock) -> Option<Terminator<'tcx>> {
match self.basic_blocks[bb] {
BasicBlockData { BasicBlockData {
ref statements, ref statements,
terminator: terminator:
@ -183,32 +187,45 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
} if statements.is_empty() => terminator.take(), } if statements.is_empty() => terminator.take(),
// if `terminator` is None, this means we are in a loop. In that // if `terminator` is None, this means we are in a loop. In that
// case, let all the loop collapse to its entry. // case, let all the loop collapse to its entry.
_ => return, _ => None,
};
let target = match terminator {
Some(Terminator { kind: TerminatorKind::Goto { ref mut target }, .. }) => {
self.collapse_goto_chain(target, changed);
*target
}
_ => unreachable!(),
};
self.basic_blocks[*start].terminator = terminator;
debug!("collapsing goto chain from {:?} to {:?}", *start, target);
*changed |= *start != target;
if self.pred_count[*start] == 1 {
// This is the last reference to *start, so the pred-count to
// to target is moved into the current block.
self.pred_count[*start] = 0;
} else {
self.pred_count[target] += 1;
self.pred_count[*start] -= 1;
} }
}
*start = target; /// Collapse a goto chain starting from `start`
fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
// Using `SmallVec` here, because in some logs on libcore oli-obk saw many single-element
// goto chains. We should probably benchmark different sizes.
let mut terminators: SmallVec<[_; 1]> = Default::default();
let mut current = *start;
while let Some(terminator) = self.take_terminator_if_simple_goto(current) {
let target = match terminator {
Terminator { kind: TerminatorKind::Goto { target }, .. } => target,
_ => unreachable!(),
};
terminators.push((current, terminator));
current = target;
}
let last = current;
*start = last;
while let Some((current, mut terminator)) = terminators.pop() {
let target = match terminator {
Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } => target,
_ => unreachable!(),
};
*target = last;
debug!("collapsing goto chain from {:?} to {:?}", current, target);
if self.pred_count[current] == 1 {
// This is the last reference to current, so the pred-count to
// to target is moved into the current block.
self.pred_count[current] = 0;
} else {
self.pred_count[*target] += 1;
self.pred_count[current] -= 1;
}
*changed = true;
self.basic_blocks[current].terminator = Some(terminator);
}
} }
// merge a block with 1 `goto` predecessor to its parent // merge a block with 1 `goto` predecessor to its parent

@ -1 +1 @@
Subproject commit 974eb438da8ced6e3becda2bbf63d9b643eacdeb Subproject commit 2d5c2381e4e50484bf281fc1bfe19743aa9eb37a