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:
commit
de10abf50c
6 changed files with 75 additions and 57 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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!
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
self.basic_blocks[*start].terminator = terminator;
|
terminators.push((current, terminator));
|
||||||
|
current = target;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
*start = 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
|
Loading…
Add table
Reference in a new issue