Skip to content

Rollup of 6 pull requests #75016

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

Merged
merged 12 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

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
curl https://ci-mirrors.rust-lang.org/rustc/clang%2Bllvm-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-10.0.0-x86_64-linux-gnu-ubuntu-18.04.tar.xz | \
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

Expand Down
30 changes: 14 additions & 16 deletions src/doc/unstable-book/src/language-features/plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,42 +45,40 @@ that warns about any item named `lintme`.
extern crate rustc_ast;

// Load rustc as a plugin to get macros
#[macro_use]
extern crate rustc;
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_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
use rustc_ast::ast;

declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");

struct Pass;

impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(TEST_LINT)
}
}
declare_lint_pass!(Pass => [TEST_LINT]);

impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.as_str() == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
if it.ident.name.as_str() == "lintme" {
cx.lint(TEST_LINT, |lint| {
lint.build("item is named 'lintme'").set_span(it.span).emit()
});
}
}
}

#[plugin_registrar]
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

```rust,ignore
#![feature(plugin)]
#![plugin(lint_plugin_test)]

fn lintme() { }
Expand All @@ -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
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
to access type information.

Expand Down
12 changes: 8 additions & 4 deletions src/librustc_error_codes/error_codes/E0741.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Only structural-match types (that is, types that derive `PartialEq` and `Eq`)
may be used as the types of const generic parameters.
A non-structural-match type was used as the type of a const generic parameter.

Erroneous code example:

```compile_fail,E0741
#![feature(const_generics)]
Expand All @@ -9,12 +10,15 @@ struct A;
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)]

#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq)] // We derive both traits here.
struct A;

struct B<const X: A>; // ok!
Expand Down
11 changes: 5 additions & 6 deletions src/librustc_error_codes/error_codes/E0743.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ Erroneous code example:
fn foo2(x: u8, y: &...) {} // error!
```

Only foreign functions can use the C-variadic type (`...`).
In such functions, `...` may only occur non-nested.
That is, `y: &'a ...` is not allowed.
Only foreign functions can use the C-variadic type (`...`). In such functions,
`...` may only occur non-nested. That is, `y: &'a ...` is not allowed.

A C-variadic type is used to give an undefined number
of parameters to a given function (like `printf` in C).
The equivalent in Rust would be to use macros directly.
A C-variadic type is used to give an undefined number of parameters to a given
function (like `printf` in C). The equivalent in Rust would be to use macros
directly (like `println!` for example).
69 changes: 43 additions & 26 deletions src/librustc_mir/transform/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use smallvec::SmallVec;
use std::borrow::Cow;

pub struct SimplifyCfg {
Expand Down Expand Up @@ -172,9 +173,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
}
}

// Collapse a goto chain starting from `start`
fn collapse_goto_chain(&mut self, start: &mut BasicBlock, changed: &mut bool) {
let mut terminator = match self.basic_blocks[*start] {
/// This function will return `None` if
/// * the block has statements
/// * 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 {
ref statements,
terminator:
Expand All @@ -183,32 +187,45 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
} if statements.is_empty() => terminator.take(),
// if `terminator` is None, this means we are in a loop. In that
// case, let all the loop collapse to its entry.
_ => return,
};

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;
_ => None,
}
}

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;
/// 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);

*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
Expand Down