Auto merge of #63090 - Centril:rollup-xnjwm2h, r=Centril

Rollup of 8 pull requests

Successful merges:

 - #61856 (Lint attributes on function arguments)
 - #62360 (Document that ManuallyDrop::drop should not called more than once)
 - #62392 (Update minifier-rs version)
 - #62871 (Explicit error message for async recursion.)
 - #62995 (Avoid ICE when suggestion span is at Eof)
 - #63053 (SystemTime docs: recommend Instant for elapsed time)
 - #63081 (tidy: Cleanup the directory whitelist)
 - #63088 (Remove anonymous_parameters from unrelated test)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-07-28 20:22:42 +00:00
commit c7312fe4ff
44 changed files with 804 additions and 358 deletions

View File

@ -1700,7 +1700,7 @@ dependencies = [
[[package]]
name = "minifier"
version = "0.0.30"
version = "0.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3195,7 +3195,7 @@ dependencies = [
name = "rustdoc"
version = "0.0.0"
dependencies = [
"minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
"minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -4442,7 +4442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
"checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0"
"checksum minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332"
"checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649"
"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"

View File

@ -119,6 +119,8 @@ impl<T: ?Sized> ManuallyDrop<T> {
/// This function runs the destructor of the contained value and thus the wrapped value
/// now represents uninitialized data. It is up to the user of this method to ensure the
/// uninitialized data is not actually used.
/// In particular, this function can only be called called at most once
/// for a given instance of `ManuallyDrop<T>`.
///
/// [`ManuallyDrop::into_inner`]: #method.into_inner
#[stable(feature = "manually_drop", since = "1.20.0")]

View File

@ -210,6 +210,10 @@ pub trait Visitor<'v> : Sized {
}
}
fn visit_arg(&mut self, arg: &'v Arg) {
walk_arg(self, arg)
}
/// Visits the top-level item and (optionally) nested items / impl items. See
/// `visit_nested_item` for details.
fn visit_item(&mut self, i: &'v Item) {
@ -396,10 +400,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id
}
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
for argument in &body.arguments {
visitor.visit_id(argument.hir_id);
visitor.visit_pat(&argument.pat);
}
walk_list!(visitor, visit_arg, &body.arguments);
visitor.visit_expr(&body.value);
}
@ -452,6 +453,12 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
}
pub fn walk_arg<'v, V: Visitor<'v>>(visitor: &mut V, arg: &'v Arg) {
visitor.visit_id(arg.hir_id);
visitor.visit_pat(&arg.pat);
walk_list!(visitor, visit_attribute, &arg.attrs);
}
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_vis(&item.vis);
visitor.visit_ident(item.ident);

View File

@ -2461,8 +2461,10 @@ impl<'a> LoweringContext<'a> {
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
hir::Arg {
attrs: self.lower_attrs(&arg.attrs),
hir_id: self.lower_node_id(arg.id),
pat: self.lower_pat(&arg.pat),
span: arg.span,
}
}
@ -3279,19 +3281,29 @@ impl<'a> LoweringContext<'a> {
//
// If this is the simple case, this argument will end up being the same as the
// original argument, but with a different pattern id.
let mut stmt_attrs = ThinVec::new();
stmt_attrs.extend(argument.attrs.iter().cloned());
let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
let new_argument = hir::Arg {
attrs: argument.attrs,
hir_id: argument.hir_id,
pat: new_argument_pat,
span: argument.span,
};
if is_simple_argument {
// If this is the simple case, then we only insert one statement that is
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
// `HirId`s are densely assigned.
let expr = this.expr_ident(desugared_span, ident, new_argument_id);
let stmt = this.stmt_let_pat(
desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn);
stmt_attrs,
desugared_span,
Some(P(expr)),
argument.pat,
hir::LocalSource::AsyncFn
);
statements.push(stmt);
} else {
// If this is not the simple case, then we construct two statements:
@ -3313,14 +3325,23 @@ impl<'a> LoweringContext<'a> {
desugared_span, ident, hir::BindingAnnotation::Mutable);
let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
let move_stmt = this.stmt_let_pat(
desugared_span, Some(P(move_expr)), move_pat, hir::LocalSource::AsyncFn);
ThinVec::new(),
desugared_span,
Some(P(move_expr)),
move_pat,
hir::LocalSource::AsyncFn
);
// Construct the `let <pat> = __argN;` statement. We re-use the original
// argument's pattern so that `HirId`s are densely assigned.
let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
let pattern_stmt = this.stmt_let_pat(
desugared_span, Some(P(pattern_expr)), argument.pat,
hir::LocalSource::AsyncFn);
stmt_attrs,
desugared_span,
Some(P(pattern_expr)),
argument.pat,
hir::LocalSource::AsyncFn
);
statements.push(move_stmt);
statements.push(pattern_stmt);
@ -5030,6 +5051,7 @@ impl<'a> LoweringContext<'a> {
// `let mut __next`
let next_let = self.stmt_let_pat(
ThinVec::new(),
desugared_span,
None,
next_pat,
@ -5039,6 +5061,7 @@ impl<'a> LoweringContext<'a> {
// `let <pat> = __next`
let pat = self.lower_pat(pat);
let pat_let = self.stmt_let_pat(
ThinVec::new(),
head_sp,
Some(next_expr),
pat,
@ -5533,19 +5556,20 @@ impl<'a> LoweringContext<'a> {
fn stmt_let_pat(
&mut self,
attrs: ThinVec<Attribute>,
span: Span,
init: Option<P<hir::Expr>>,
pat: P<hir::Pat>,
source: hir::LocalSource,
) -> hir::Stmt {
let local = hir::Local {
pat,
ty: None,
init,
attrs,
hir_id: self.next_id(),
span,
init,
pat,
source,
attrs: ThinVec::new()
span,
ty: None,
};
self.stmt(span, hir::StmtKind::Local(P(local)))
}
@ -5959,6 +5983,7 @@ impl<'a> LoweringContext<'a> {
hir::BindingAnnotation::Mutable,
);
let pinned_let = self.stmt_let_pat(
ThinVec::new(),
span,
Some(expr),
pinned_pat,

View File

@ -363,6 +363,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
self.currently_in_body = prev_in_body;
}
fn visit_arg(&mut self, arg: &'hir Arg) {
let node = Node::Arg(arg);
self.insert(arg.pat.span, arg.hir_id, node);
self.with_parent(arg.hir_id, |this| {
intravisit::walk_arg(this, arg);
});
}
fn visit_item(&mut self, i: &'hir Item) {
debug!("visit_item: {:?}", i);
debug_assert_eq!(i.hir_id.owner,

View File

@ -360,6 +360,7 @@ impl<'hir> Map<'hir> {
Node::Pat(_) |
Node::Binding(_) |
Node::Local(_) |
Node::Arg(_) |
Node::Arm(_) |
Node::Lifetime(_) |
Node::Visibility(_) |
@ -932,6 +933,7 @@ impl<'hir> Map<'hir> {
pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
self.read(id); // reveals attributes on the node
let attrs = match self.find_entry(id).map(|entry| entry.node) {
Some(Node::Arg(a)) => Some(&a.attrs[..]),
Some(Node::Local(l)) => Some(&l.attrs[..]),
Some(Node::Item(i)) => Some(&i.attrs[..]),
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
@ -995,6 +997,7 @@ impl<'hir> Map<'hir> {
pub fn span(&self, hir_id: HirId) -> Span {
self.read(hir_id); // reveals span from node
match self.find_entry(hir_id).map(|entry| entry.node) {
Some(Node::Arg(arg)) => arg.span,
Some(Node::Item(item)) => item.span,
Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
Some(Node::TraitItem(trait_method)) => trait_method.span,
@ -1197,6 +1200,7 @@ impl<'hir> print::PpAnn for Map<'hir> {
impl<'a> print::State<'a> {
pub fn print_node(&mut self, node: Node<'_>) {
match node {
Node::Arg(a) => self.print_arg(&a),
Node::Item(a) => self.print_item(&a),
Node::ForeignItem(a) => self.print_foreign_item(&a),
Node::TraitItem(a) => self.print_trait_item(a),
@ -1338,6 +1342,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
Some(Node::Pat(_)) => {
format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
}
Some(Node::Arg(_)) => {
format!("arg {}{}", map.hir_to_pretty_string(id), id_str)
}
Some(Node::Arm(_)) => {
format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
}

View File

@ -2010,8 +2010,10 @@ pub struct InlineAsm {
/// Represents an argument in a function header.
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
pub struct Arg {
pub pat: P<Pat>,
pub attrs: HirVec<Attribute>,
pub hir_id: HirId,
pub pat: P<Pat>,
pub span: Span,
}
/// Represents the header (not the body) of a function declaration.
@ -2701,6 +2703,7 @@ impl CodegenFnAttrs {
#[derive(Copy, Clone, Debug)]
pub enum Node<'hir> {
Arg(&'hir Arg),
Item(&'hir Item),
ForeignItem(&'hir ForeignItem),
TraitItem(&'hir TraitItem),

View File

@ -1767,6 +1767,11 @@ impl<'a> State<'a> {
self.ann.post(self, AnnNode::Pat(pat))
}
pub fn print_arg(&mut self, arg: &hir::Arg) {
self.print_outer_attributes(&arg.attrs);
self.print_pat(&arg.pat);
}
pub fn print_arm(&mut self, arm: &hir::Arm) {
// I have no idea why this check is necessary, but here it
// is :(

View File

@ -966,6 +966,13 @@ for LateContextAndPass<'a, 'tcx, T> {
self.context.tables = old_tables;
}
fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
self.with_lint_attrs(arg.hir_id, &arg.attrs, |cx| {
lint_callback!(cx, check_arg, arg);
hir_visit::walk_arg(cx, arg);
});
}
fn visit_body(&mut self, body: &'tcx hir::Body) {
lint_callback!(self, check_body, body);
hir_visit::walk_body(self, body);
@ -1156,6 +1163,13 @@ for LateContextAndPass<'a, 'tcx, T> {
}
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
fn visit_arg(&mut self, arg: &'a ast::Arg) {
self.with_lint_attrs(arg.id, &arg.attrs, |cx| {
run_early_pass!(cx, check_arg, arg);
ast_visit::walk_arg(cx, arg);
});
}
fn visit_item(&mut self, it: &'a ast::Item) {
self.with_lint_attrs(it.id, &it.attrs, |cx| {
run_early_pass!(cx, check_item, it);

View File

@ -206,6 +206,7 @@ macro_rules! declare_lint_pass {
macro_rules! late_lint_methods {
($macro:path, $args:tt, [$hir:tt]) => (
$macro!($args, [$hir], [
fn check_arg(a: &$hir hir::Arg);
fn check_body(a: &$hir hir::Body);
fn check_body_post(a: &$hir hir::Body);
fn check_name(a: Span, b: ast::Name);
@ -358,6 +359,7 @@ macro_rules! declare_combined_late_lint_pass {
macro_rules! early_lint_methods {
($macro:path, $args:tt) => (
$macro!($args, [
fn check_arg(a: &ast::Arg);
fn check_ident(a: ast::Ident);
fn check_crate(a: &ast::Crate);
fn check_crate_post(a: &ast::Crate);
@ -495,8 +497,6 @@ pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync +
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
+ sync::Sync + 'static>;
/// Identifies a lint known to the compiler.
#[derive(Clone, Copy, Debug)]
pub struct LintId {
@ -812,6 +812,12 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
intravisit::NestedVisitorMap::All(&self.tcx.hir())
}
fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
self.with_lint_attrs(arg.hir_id, &arg.attrs, |builder| {
intravisit::walk_arg(builder, arg);
});
}
fn visit_item(&mut self, it: &'tcx hir::Item) {
self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
intravisit::walk_item(builder, it);

View File

@ -10,7 +10,7 @@ This allows moving and dropping of a `OwningRef` without needing to recreate the
This can sometimes be useful because Rust borrowing rules normally prevent
moving a type that has been moved from. For example, this kind of code gets rejected:
```rust,ignore
```compile_fail,E0515
fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
let v = vec![1, 2, 3, 4];
let s = &v[1..3];
@ -43,7 +43,8 @@ and preventing mutable access to root containers, which in practice requires hea
as provided by `Box<T>`, `Rc<T>`, etc.
Also provided are typedefs for common owner type combinations,
which allow for less verbose type signatures. For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
which allow for less verbose type signatures.
For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
The crate also provides the more advanced `OwningHandle` type,
which allows more freedom in bundling a dependent handle object
@ -498,7 +499,8 @@ impl<O, T: ?Sized> OwningRef<O, T> {
}
}
/// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`.
/// Erases the concrete base type of the owner with a trait object
/// which implements `Send` and `Sync`.
///
/// This allows mixing of owned references with different owner base types.
pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T>
@ -510,7 +512,7 @@ impl<O, T: ?Sized> OwningRef<O, T> {
}
}
// TODO: wrap_owner
// UNIMPLEMENTED: wrap_owner
// FIXME: Naming convention?
/// A getter for the underlying owner.
@ -756,7 +758,7 @@ impl<O, T: ?Sized> OwningRefMut<O, T> {
}
}
// TODO: wrap_owner
// UNIMPLEMENTED: wrap_owner
// FIXME: Naming convention?
/// A getter for the underlying owner.

View File

@ -274,7 +274,9 @@ mod owning_handle {
use std::cell::RefCell;
let cell = Rc::new(RefCell::new(2));
let cell_ref = RcRef::new(cell);
let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
let mut handle = OwningHandle::new_with_fn(cell_ref, |x| {
unsafe { x.as_ref() }.unwrap().borrow_mut()
});
assert_eq!(*handle, 2);
*handle = 3;
assert_eq!(*handle, 3);
@ -319,8 +321,12 @@ mod owning_handle {
let result = {
let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
let curr = RcRef::new(complex);
let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
let curr = OwningHandle::new_with_fn(curr, |x| {
unsafe { x.as_ref() }.unwrap().borrow_mut()
});
let mut curr = OwningHandle::new_with_fn(curr, |x| {
unsafe { x.as_ref() }.unwrap().try_write().unwrap()
});
assert_eq!(*curr, "someString");
*curr = "someOtherString";
curr
@ -353,8 +359,12 @@ mod owning_handle {
let result = {
let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
let curr = RcRef::new(complex);
let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap());
let curr = OwningHandle::new_with_fn(curr, |x| {
unsafe { x.as_ref() }.unwrap().borrow_mut()
});
let mut curr = OwningHandle::new_with_fn(curr, |x| {
unsafe { x.as_ref() }.unwrap().try_write().unwrap()
});
assert_eq!(*curr, "someString");
*curr = "someOtherString";
curr

View File

@ -223,7 +223,8 @@ impl CodeSuggestion {
}
}
if let Some(cur_line) = fm.get_line(cur_lo.line - 1) {
buf.push_str(&cur_line[..cur_lo.col.to_usize()]);
let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize());
buf.push_str(&cur_line[..end]);
}
}
buf.push_str(&part.snippet);

View File

@ -121,7 +121,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
self_arg = None;
}
ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&arg), self_arg)
});
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
@ -511,7 +511,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
///////////////////////////////////////////////////////////////////////////
/// the main entry point for building MIR for a function
struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Pat>, Option<ImplicitSelfKind>);
struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Arg>, Option<ImplicitSelfKind>);
fn construct_fn<'a, 'tcx, A>(
hir: Cx<'a, 'tcx>,
@ -782,13 +782,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
-> BlockAnd<()>
{
// Allocate locals for the function arguments
for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
// If this is a simple binding pattern, give the local a name for
// debuginfo and so that error reporting knows that this is a user
// variable. For any other pattern the pattern introduces new
// variables which will be named instead.
let (name, span) = if let Some(pat) = pattern {
(pat.simple_ident().map(|ident| ident.name), pat.span)
let (name, span) = if let Some(arg) = arg_opt {
(arg.pat.simple_ident().map(|ident| ident.name), arg.pat.span)
} else {
(None, self.fn_span)
};
@ -813,18 +813,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Function arguments always get the first Local indices after the return place
let local = Local::new(index + 1);
let place = Place::from(local);
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
let &ArgInfo(ty, opt_ty_info, arg_opt, ref self_binding) = arg_info;
// Make sure we drop (parts of) the argument even when not matched on.
self.schedule_drop(
pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span),
argument_scope, local, ty, DropKind::Value,
);
if let Some(pattern) = pattern {
let pattern = self.hir.pattern_from_hir(pattern);
if let Some(arg) = arg_opt {
let pattern = self.hir.pattern_from_hir(&arg.pat);
let original_source_scope = self.source_scope;
let span = pattern.span;
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
match *pattern.kind {
// Don't introduce extra copies for simple bindings
PatternKind::Binding {
@ -835,6 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
..
} => {
self.local_decls[local].mutability = mutability;
self.local_decls[local].source_info.scope = self.source_scope;
self.local_decls[local].is_user_variable =
if let Some(kind) = self_binding {
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
@ -860,6 +862,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
unpack!(block = self.place_into_pattern(block, pattern, &place, false));
}
}
self.source_scope = original_source_scope;
}
}
@ -872,6 +875,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.into(&Place::RETURN_PLACE, block, body)
}
fn set_correct_source_scope_for_arg(
&mut self,
arg_hir_id: hir::HirId,
original_source_scope: SourceScope,
pattern_span: Span
) {
let tcx = self.hir.tcx();
let current_root = tcx.maybe_lint_level_root_bounded(
arg_hir_id,
self.hir.root_lint_level
);
let parent_root = tcx.maybe_lint_level_root_bounded(
self.source_scope_local_data[original_source_scope].lint_root,
self.hir.root_lint_level,
);
if current_root != parent_root {
self.source_scope = self.new_source_scope(
pattern_span,
LintLevel::Explicit(current_root),
None
);
}
}
fn get_unit_temp(&mut self) -> Place<'tcx> {
match self.unit_temp {
Some(ref tmp) => tmp.clone(),

View File

@ -94,6 +94,11 @@ impl<'k> StatCollector<'k> {
}
impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_arg(&mut self, arg: &'v hir::Arg) {
self.record("Arg", Id::Node(arg.hir_id), arg);
hir_visit::walk_arg(self, arg)
}
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
panic!("visit_nested_xxx must be manually implemented in this visitor")
}

View File

@ -555,21 +555,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let tcx = self.tcx;
if let PatKind::Binding(..) = inner.node {
let parent_id = tcx.hir().get_parent_node(pat.hir_id);
let parent = tcx.hir().get(parent_id);
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
match parent {
hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
hir::Node::ForeignItem(hir::ForeignItem {
node: hir::ForeignItemKind::Fn(..), ..
}) |
hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
// this pat is likely an argument
let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
let binding_parent = tcx.hir().get(binding_parent_id);
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
match binding_parent {
hir::Node::Arg(hir::Arg { span, .. }) => {
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
// FIXME: turn into structured suggestion, will need a span that also
// includes the the arg's type.
err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
err.span_suggestion(
*span,
&format!("did you mean `{}`", snippet),
format!(" &{}", expected),
Applicability::MachineApplicable,
);
}
}
hir::Node::Arm(_) |

View File

@ -235,40 +235,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
expr: &hir::Expr,
) -> Option<(Span, &'static str, String)> {
if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
if let hir::def::Res::Local(id) = path.res {
let parent = self.tcx.hir().get_parent_node(id);
if let Some(Node::Expr(hir::Expr {
hir_id,
node: hir::ExprKind::Closure(_, decl, ..),
..
})) = self.tcx.hir().find(parent) {
let parent = self.tcx.hir().get_parent_node(*hir_id);
if let (Some(Node::Expr(hir::Expr {
node: hir::ExprKind::MethodCall(path, span, expr),
..
})), 1) = (self.tcx.hir().find(parent), decl.inputs.len()) {
let self_ty = self.tables.borrow().node_type(expr[0].hir_id);
let self_ty = format!("{:?}", self_ty);
let name = path.ident.as_str();
let is_as_ref_able = (
self_ty.starts_with("&std::option::Option") ||
self_ty.starts_with("&std::result::Result") ||
self_ty.starts_with("std::option::Option") ||
self_ty.starts_with("std::result::Result")
) && (name == "map" || name == "and_then");
match (is_as_ref_able, self.sess().source_map().span_to_snippet(*span)) {
(true, Ok(src)) => {
return Some((*span, "consider using `as_ref` instead",
format!("as_ref().{}", src)));
},
_ => ()
}
}
}
}
let path = match expr.node {
hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => path,
_ => return None
};
let local_id = match path.res {
hir::def::Res::Local(id) => id,
_ => return None
};
let local_parent = self.tcx.hir().get_parent_node(local_id);
let arg_hir_id = match self.tcx.hir().find(local_parent) {
Some(Node::Arg(hir::Arg { hir_id, .. })) => hir_id,
_ => return None
};
let arg_parent = self.tcx.hir().get_parent_node(*arg_hir_id);
let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(arg_parent) {
Some(Node::Expr(
hir::Expr { hir_id, node: hir::ExprKind::Closure(_, decl, ..), .. }
)) => (hir_id, decl),
_ => return None
};
let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id);
let hir = self.tcx.hir().find(expr_parent);
let closure_params_len = closure_fn_decl.inputs.len();
let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
(Some(Node::Expr(
hir::Expr { node: hir::ExprKind::MethodCall(path, span, expr), .. }
)), 1) => (path, span, expr),
_ => return None
};
let self_ty = self.tables.borrow().node_type(method_expr[0].hir_id);
let self_ty = format!("{:?}", self_ty);
let name = method_path.ident.as_str();
let is_as_ref_able = (
self_ty.starts_with("&std::option::Option") ||
self_ty.starts_with("&std::result::Result") ||
self_ty.starts_with("std::option::Option") ||
self_ty.starts_with("std::result::Result")
) && (name == "map" || name == "and_then");
match (is_as_ref_able, self.sess().source_map().span_to_snippet(*method_span)) {
(true, Ok(src)) => {
let suggestion = format!("as_ref().{}", src);
Some((*method_span, "consider using `as_ref` instead", suggestion))
},
_ => None
}
None
}
crate fn is_hir_id_from_struct_pattern_shorthand_field(

View File

@ -1325,19 +1325,35 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) {
check_packed(tcx, span, def_id);
}
fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, span: Span) {
fn check_opaque<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
span: Span,
origin: &hir::ExistTyOrigin
) {
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) {
let mut err = struct_span_err!(
tcx.sess, span, E0720,
"opaque type expands to a recursive type",
);
err.span_label(span, "expands to a recursive type");
if let ty::Opaque(..) = partially_expanded_type.sty {
err.note("type resolves to itself");
if let hir::ExistTyOrigin::AsyncFn = origin {
struct_span_err!(
tcx.sess, span, E0733,
"recursion in an `async fn` requires boxing",
)
.span_label(span, "an `async fn` cannot invoke itself directly")
.note("a recursive `async fn` must be rewritten to return a boxed future.")
.emit();
} else {
err.note(&format!("expanded type is `{}`", partially_expanded_type));
let mut err = struct_span_err!(
tcx.sess, span, E0720,
"opaque type expands to a recursive type",
);
err.span_label(span, "expands to a recursive type");
if let ty::Opaque(..) = partially_expanded_type.sty {
err.note("type resolves to itself");
} else {
err.note(&format!("expanded type is `{}`", partially_expanded_type));
}
err.emit();
}
err.emit();
}
}
@ -1387,11 +1403,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) {
hir::ItemKind::Union(..) => {
check_union(tcx, it.hir_id, it.span);
}
hir::ItemKind::Existential(..) => {
hir::ItemKind::Existential(hir::ExistTy{origin, ..}) => {
let def_id = tcx.hir().local_def_id(it.hir_id);
let substs = InternalSubsts::identity_for_item(tcx, def_id);
check_opaque(tcx, def_id, substs, it.span);
check_opaque(tcx, def_id, substs, it.span, &origin);
}
hir::ItemKind::Ty(..) => {
let def_id = tcx.hir().local_def_id(it.hir_id);

View File

@ -4763,7 +4763,53 @@ assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11}));
```
"##,
E0733: r##"
Recursion in an `async fn` requires boxing. For example, this will not compile:
```edition2018,compile_fail,E0733
#![feature(async_await)]
async fn foo(n: usize) {
if n > 0 {
foo(n - 1).await;
}
}
```
To achieve async recursion, the `async fn` needs to be desugared
such that the `Future` is explicit in the return type:
```edition2018,compile_fail,E0720
# #![feature(async_await)]
use std::future::Future;
fn foo_desugered(n: usize) -> impl Future<Output = ()> {
async move {
if n > 0 {
foo_desugered(n - 1).await;
}
}
}
```
Finally, the future is wrapped in a pinned box:
```edition2018
# #![feature(async_await)]
use std::future::Future;
use std::pin::Pin;
fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> {
Box::pin(async move {
if n > 0 {
foo_recursive(n - 1).await;
}
})
}
```
The `Box<...>` ensures that the result is of known size,
and the pin is required to keep it in the same place in memory.
"##,
} // (end of detailed error messages)
register_diagnostics! {
// E0035, merged into E0087/E0089

View File

@ -10,7 +10,7 @@ path = "lib.rs"
[dependencies]
pulldown-cmark = { version = "0.5.3", default-features = false }
minifier = "0.0.30"
minifier = "0.0.33"
rayon = { version = "0.2.0", package = "rustc-rayon" }
tempfile = "3"
parking_lot = "0.7"

View File

@ -1322,13 +1322,13 @@ fn write_minify_replacer<W: Write>(
{
let tokens: Tokens<'_> = simple_minify(contents)
.into_iter()
.filter(|f| {
.filter(|(f, next)| {
// We keep backlines.
minifier::js::clean_token_except(f, &|c: &Token<'_>| {
minifier::js::clean_token_except(f, next, &|c: &Token<'_>| {
c.get_char() != Some(ReservedChar::Backline)
})
})
.map(|f| {
.map(|(f, _)| {
minifier::js::replace_token_with(f, &|t: &Token<'_>| {
match *t {
Token::Keyword(Keyword::Null) => Some(Token::Other("N")),
@ -1363,7 +1363,7 @@ fn write_minify_replacer<W: Write>(
// shouldn't be aggregated.
|tokens, pos| {
pos < 2 ||
!tokens[pos - 1].is_char(ReservedChar::OpenBracket) ||
!tokens[pos - 1].eq_char(ReservedChar::OpenBracket) ||
tokens[pos - 2].get_other() != Some("searchIndex")
}
)

View File

@ -396,6 +396,7 @@ impl SystemTime {
/// This function may fail because measurements taken earlier are not
/// guaranteed to always be before later measurements (due to anomalies such
/// as the system clock being adjusted either forwards or backwards).
/// [`Instant`] can be used to measure elapsed time without this risk of failure.
///
/// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
/// the amount of time elapsed from the specified measurement to this one.
@ -406,6 +407,7 @@ impl SystemTime {
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`Instant`]: ../../std/time/struct.Instant.html
///
/// # Examples
///
@ -414,7 +416,7 @@ impl SystemTime {
///
/// let sys_time = SystemTime::now();
/// let difference = sys_time.duration_since(sys_time)
/// .expect("SystemTime::duration_since failed");
/// .expect("Clock may have gone backwards");
/// println!("{:?}", difference);
/// ```
#[stable(feature = "time2", since = "1.8.0")]
@ -423,7 +425,8 @@ impl SystemTime {
self.0.sub_time(&earlier.0).map_err(SystemTimeError)
}
/// Returns the amount of time elapsed since this system time was created.
/// Returns the difference between the clock time when this
/// system time was created, and the current clock time.
///
/// This function may fail as the underlying system clock is susceptible to
/// drift and updates (e.g., the system clock could go backwards), so this
@ -431,12 +434,15 @@ impl SystemTime {
/// returned where the duration represents the amount of time elapsed from
/// this time measurement to the current time.
///
/// To measure elapsed time reliably, use [`Instant`] instead.
///
/// Returns an [`Err`] if `self` is later than the current system time, and
/// the error contains how far from the current system time `self` is.
///
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`Instant`]: ../../std/time/struct.Instant.html
///
/// # Examples
///

View File

@ -1796,6 +1796,7 @@ pub struct Arg {
pub ty: P<Ty>,
pub pat: P<Pat>,
pub id: NodeId,
pub span: Span,
}
/// Alternative representation for `Arg`s describing `self` parameter of methods.
@ -1854,6 +1855,7 @@ impl Arg {
node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
span,
}),
span,
ty,
id: DUMMY_NODE_ID,
};

View File

@ -966,6 +966,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
attrs: ThinVec::default(),
id: ast::DUMMY_NODE_ID,
pat: arg_pat,
span,
ty,
}
}

View File

@ -558,10 +558,11 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
vis.visit_span(span);
}
pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) {
pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) {
vis.visit_id(id);
visit_thin_attrs(attrs, vis);
vis.visit_pat(pat);
vis.visit_span(span);
vis.visit_ty(ty);
}

View File

@ -30,7 +30,7 @@ crate fn dummy_arg(ident: Ident) -> Arg {
span: ident.span,
id: ast::DUMMY_NODE_ID
};
Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, ty: P(ty) }
Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) }
}
pub enum Error {

View File

@ -1515,6 +1515,7 @@ impl<'a> Parser<'a> {
where
F: Fn(&token::Token) -> bool
{
let lo = self.token.span;
let attrs = self.parse_arg_attributes()?;
if let Some(mut arg) = self.parse_self_arg()? {
arg.attrs = attrs.into();
@ -1578,11 +1579,14 @@ impl<'a> Parser<'a> {
}
};
Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, ty })
let span = lo.to(self.token.span);
Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty })
}
/// Parses an argument in a lambda header (e.g., `|arg, arg|`).
fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
let lo = self.token.span;
let attrs = self.parse_arg_attributes()?;
let pat = self.parse_pat(Some("argument name"))?;
let t = if self.eat(&token::Colon) {
@ -1594,10 +1598,12 @@ impl<'a> Parser<'a> {
span: self.prev_span,
})
};
let span = lo.to(self.token.span);
Ok(Arg {
attrs: attrs.into(),
ty: t,
pat,
span,
id: ast::DUMMY_NODE_ID
})
}

View File

@ -66,6 +66,7 @@ pub trait Visitor<'ast>: Sized {
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
fn visit_arg(&mut self, arg: &'ast Arg) { walk_arg(self, arg) }
fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
@ -547,12 +548,10 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
}
pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
for argument in &function_declaration.inputs {
walk_list!(visitor, visit_attribute, argument.attrs.iter());
visitor.visit_pat(&argument.pat);
visitor.visit_ty(&argument.ty);
for arg in &function_declaration.inputs {
visitor.visit_arg(arg);
}
visitor.visit_fn_ret_ty(&function_declaration.output)
visitor.visit_fn_ret_ty(&function_declaration.output);
}
pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
@ -822,6 +821,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr_post(expression)
}
pub fn walk_arg<'a, V: Visitor<'a>>(visitor: &mut V, arg: &'a Arg) {
walk_list!(visitor, visit_attribute, arg.attrs.iter());
visitor.visit_pat(&arg.pat);
visitor.visit_ty(&arg.ty);
}
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
walk_list!(visitor, visit_pat, &arm.pats);
if let Some(ref e) = &arm.guard {

View File

@ -1,11 +1,11 @@
error[E0720]: opaque type expands to a recursive type
error[E0733]: recursion in an `async fn` requires boxing
--> $DIR/recursive-async-impl-trait-type.rs:7:40
|
LL | async fn recursive_async_function() -> () {
| ^^ expands to a recursive type
| ^^ an `async fn` cannot invoke itself directly
|
= note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
= note: a recursive `async fn` must be rewritten to return a boxed future.
error: aborting due to previous error
For more information about this error, try `rustc --explain E0720`.
For more information about this error, try `rustc --explain E0733`.

View File

@ -9,7 +9,7 @@ pub trait LolInto<T>: Sized {
}
pub trait LolFrom<T> {
fn from(T) -> Self;
fn from(_: T) -> Self;
}
impl<'a, T: ?Sized, U> LolInto<U> for &'a T where T: LolTo<U> {

View File

@ -1,12 +1,70 @@
// edition:2018
// Exercise the unused_mut attribute in some positive and negative cases
#![allow(unused_assignments)]
#![allow(unused_variables)]
#![allow(dead_code)]
#![deny(unused_mut)]
#![feature(async_await, async_closure, param_attrs)]
async fn baz_async(
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
) {}
fn baz(
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
#[allow(unused_mut)] (mut c, d): (i32, i32)
) {}
struct RefStruct {}
impl RefStruct {
async fn baz_async(
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
) {}
fn baz(
&self,
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
#[allow(unused_mut)] (mut c, d): (i32, i32)
) {}
}
trait RefTrait {
fn baz(
&self,
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
#[allow(unused_mut)] (mut c, d): (i32, i32)
) {}
}
impl RefTrait for () {
fn baz(
&self,
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
#[allow(unused_mut)] (mut c, d): (i32, i32)
) {}
}
fn main() {
let _ = async move |
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
| {};
let _ = |
mut a: i32,
//~^ ERROR: variable does not need to be mutable
#[allow(unused_mut)] mut b: i32,
#[allow(unused_mut)] (mut c, d): (i32, i32)
| {};
// negative cases
let mut a = 3; //~ ERROR: variable does not need to be mutable

View File

@ -1,19 +1,83 @@
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:46:14
--> $DIR/lint-unused-mut-variables.rs:9:5
|
LL | let x = |mut y: isize| 10;
| ----^
| |
| help: remove this `mut`
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
|
note: lint level defined here
--> $DIR/lint-unused-mut-variables.rs:6:9
--> $DIR/lint-unused-mut-variables.rs:5:9
|
LL | #![deny(unused_mut)]
| ^^^^^^^^^^
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:11:9
--> $DIR/lint-unused-mut-variables.rs:14:5
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:23:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:29:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:39:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:48:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:57:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:62:9
|
LL | mut a: i32,
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:104:14
|
LL | let x = |mut y: isize| 10;
| ----^
| |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:69:9
|
LL | let mut a = 3;
| ----^
@ -21,7 +85,7 @@ LL | let mut a = 3;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:13:9
--> $DIR/lint-unused-mut-variables.rs:71:9
|
LL | let mut a = 2;
| ----^
@ -29,7 +93,7 @@ LL | let mut a = 2;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:15:9
--> $DIR/lint-unused-mut-variables.rs:73:9
|
LL | let mut b = 3;
| ----^
@ -37,7 +101,7 @@ LL | let mut b = 3;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:17:9
--> $DIR/lint-unused-mut-variables.rs:75:9
|
LL | let mut a = vec![3];
| ----^
@ -45,7 +109,7 @@ LL | let mut a = vec![3];
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:19:10
--> $DIR/lint-unused-mut-variables.rs:77:10
|
LL | let (mut a, b) = (1, 2);
| ----^
@ -53,7 +117,7 @@ LL | let (mut a, b) = (1, 2);
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:21:9
--> $DIR/lint-unused-mut-variables.rs:79:9
|
LL | let mut a;
| ----^
@ -61,7 +125,7 @@ LL | let mut a;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:25:9
--> $DIR/lint-unused-mut-variables.rs:83:9
|
LL | let mut b;
| ----^
@ -69,7 +133,7 @@ LL | let mut b;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:34:9
--> $DIR/lint-unused-mut-variables.rs:92:9
|
LL | mut x => {}
| ----^
@ -77,7 +141,7 @@ LL | mut x => {}
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:38:8
--> $DIR/lint-unused-mut-variables.rs:96:8
|
LL | (mut x, 1) |
| ----^
@ -85,7 +149,7 @@ LL | (mut x, 1) |
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:51:9
--> $DIR/lint-unused-mut-variables.rs:109:9
|
LL | let mut a = &mut 5;
| ----^
@ -93,7 +157,7 @@ LL | let mut a = &mut 5;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:56:9
--> $DIR/lint-unused-mut-variables.rs:114:9
|
LL | let mut b = (&mut a,);
| ----^
@ -101,7 +165,7 @@ LL | let mut b = (&mut a,);
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:59:9
--> $DIR/lint-unused-mut-variables.rs:117:9
|
LL | let mut x = &mut 1;
| ----^
@ -109,7 +173,7 @@ LL | let mut x = &mut 1;
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:71:9
--> $DIR/lint-unused-mut-variables.rs:129:9
|
LL | let mut v : &mut Vec<()> = &mut vec![];
| ----^
@ -117,7 +181,7 @@ LL | let mut v : &mut Vec<()> = &mut vec![];
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:48:13
--> $DIR/lint-unused-mut-variables.rs:106:13
|
LL | fn what(mut foo: isize) {}
| ----^^^
@ -125,7 +189,7 @@ LL | fn what(mut foo: isize) {}
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:66:20
--> $DIR/lint-unused-mut-variables.rs:124:20
|
LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
| ----^^^
@ -133,7 +197,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
| help: remove this `mut`
error: variable does not need to be mutable
--> $DIR/lint-unused-mut-variables.rs:138:9
--> $DIR/lint-unused-mut-variables.rs:196:9
|
LL | let mut b = vec![2];
| ----^
@ -141,10 +205,10 @@ LL | let mut b = vec![2];
| help: remove this `mut`
|
note: lint level defined here
--> $DIR/lint-unused-mut-variables.rs:134:8
--> $DIR/lint-unused-mut-variables.rs:192:8
|
LL | #[deny(unused_mut)]
| ^^^^^^^^^^
error: aborting due to 17 previous errors
error: aborting due to 25 previous errors

View File

@ -0,0 +1,64 @@
// compile-flags: --cfg something
// edition:2018
#![feature(async_await, async_closure, param_attrs)]
#![deny(unused_variables)]
async fn foo_async(
a: i32,
//~^ ERROR unused variable: `a`
#[allow(unused_variables)] b: i32,
) {}
fn foo(
#[allow(unused_variables)] a: i32,
b: i32,
//~^ ERROR unused variable: `b`
) {}
struct RefStruct {}
impl RefStruct {
async fn bar_async(
&self,
a: i32,
//~^ ERROR unused variable: `a`
#[allow(unused_variables)] b: i32,
) {}
fn bar(
&self,
#[allow(unused_variables)] a: i32,
b: i32,
//~^ ERROR unused variable: `b`
) {}
}
trait RefTrait {
fn bar(
&self,
#[allow(unused_variables)] a: i32,
b: i32,
//~^ ERROR unused variable: `b`
) {}
}
impl RefTrait for RefStruct {
fn bar(
&self,
#[allow(unused_variables)] a: i32,
b: i32,
//~^ ERROR unused variable: `b`
) {}
}
fn main() {
let _: fn(_, _) = foo;
let a = async move |
a: i32,
//~^ ERROR unused variable: `a`
#[allow(unused_variables)] b: i32,
| {};
let b = |
#[allow(unused_variables)] a: i32,
b: i32,
//~^ ERROR unused variable: `b`
| {};
let _ = a(1, 2);
let _ = b(1, 2);
}

View File

@ -0,0 +1,56 @@
error: unused variable: `a`
--> $DIR/lint-unused-variables.rs:8:5
|
LL | a: i32,
| ^ help: consider prefixing with an underscore: `_a`
|
note: lint level defined here
--> $DIR/lint-unused-variables.rs:5:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^
error: unused variable: `b`
--> $DIR/lint-unused-variables.rs:14:5
|
LL | b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `a`
--> $DIR/lint-unused-variables.rs:53:9
|
LL | a: i32,
| ^ help: consider prefixing with an underscore: `_a`
error: unused variable: `b`
--> $DIR/lint-unused-variables.rs:59:9
|
LL | b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `b`
--> $DIR/lint-unused-variables.rs:37:9
|
LL | b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `a`
--> $DIR/lint-unused-variables.rs:22:9
|
LL | a: i32,
| ^ help: consider prefixing with an underscore: `_a`
error: unused variable: `b`
--> $DIR/lint-unused-variables.rs:29:9
|
LL | b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `b`
--> $DIR/lint-unused-variables.rs:45:9
|
LL | b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: aborting due to 8 previous errors

View File

@ -2,11 +2,13 @@ error[E0308]: mismatched types
--> $DIR/issue-38371.rs:4:8
|
LL | fn foo(&foo: Foo) {
| ^^^^ expected struct `Foo`, found reference
| ^^^^------
| |
| expected struct `Foo`, found reference
| help: did you mean `foo`: `&Foo`
|
= note: expected type `Foo`
found type `&_`
= help: did you mean `foo: &Foo`?
error[E0308]: mismatched types
--> $DIR/issue-38371.rs:18:9

View File

@ -0,0 +1,8 @@
// ignore-tidy-trailing-newlines
// error-pattern: aborting due to 6 previous errors
fn main() {}
fn p() { match s { v, E { [) {) }

View File

@ -0,0 +1,61 @@
error: this file contains an un-closed delimiter
--> $DIR/issue-62973.rs:8:2
|
LL | fn p() { match s { v, E { [) {) }
| - - un-closed delimiter
| |
| un-closed delimiter
LL |
LL |
| ^
error: expected one of `,` or `}`, found `{`
--> $DIR/issue-62973.rs:6:25
|
LL | fn p() { match s { v, E { [) {) }
| - ^ expected one of `,` or `}` here
| |
| while parsing this struct
error: struct literals are not allowed here
--> $DIR/issue-62973.rs:6:16
|
LL | fn p() { match s { v, E { [) {) }
| ________________^
LL | |
LL | |
| |_^
help: surround the struct literal with parentheses
|
LL | fn p() { match (s { v, E { [) {) }
LL |
LL | )
|
error: expected one of `.`, `?`, `{`, or an operator, found `}`
--> $DIR/issue-62973.rs:8:1
|
LL | fn p() { match s { v, E { [) {) }
| ----- while parsing this match expression
LL |
LL |
| ^ expected one of `.`, `?`, `{`, or an operator here
error: incorrect close delimiter: `)`
--> $DIR/issue-62973.rs:6:28
|
LL | fn p() { match s { v, E { [) {) }
| -^ incorrect close delimiter
| |
| un-closed delimiter
error: incorrect close delimiter: `)`
--> $DIR/issue-62973.rs:6:31
|
LL | fn p() { match s { v, E { [) {) }
| -^ incorrect close delimiter
| |
| un-closed delimiter
error: aborting due to 6 previous errors

View File

@ -1,189 +1,66 @@
// check-pass
// compile-flags: --cfg something
// build-pass (FIXME(62277): could be check-pass?)
#![deny(unused_mut)]
#![feature(param_attrs)]
extern "C" {
fn ffi(
#[allow(C)] a: i32,
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(C)] d: i32,
#[forbid(C)] #[warn(C)] ...
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] ...
);
}
type FnType = fn(
#[allow(C)] a: i32,
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(C)] d: i32,
#[forbid(C)] #[warn(C)] e: i32
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] e: i32
);
pub fn foo(
#[allow(C)] a: i32,
#[allow(unused_mut)] a: i32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))] c: i32,
#[deny(C)] d: i32,
#[forbid(C)] #[warn(C)] e: i32
#[deny(unused_mut)] d: i32,
#[forbid(unused_mut)] #[warn(unused_mut)] _e: i32
) {}
// self, &self and &mut self
// self
struct SelfStruct {}
impl SelfStruct {
fn foo(
#[allow(C)] self,
#[allow(unused_mut)] self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
#[deny(unused_mut)] b: i32,
) {}
}
struct RefStruct {}
impl RefStruct {
fn foo(
#[allow(C)] &self,
#[allow(unused_mut)] &self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
#[deny(unused_mut)] b: i32,
) {}
}
trait RefTrait {
fn foo(
#[forbid(C)] &self,
#[warn(C)] a: i32
#[forbid(unused_mut)] &self,
#[warn(unused_mut)] a: i32
) {}
}
impl RefTrait for RefStruct {
fn foo(
#[forbid(C)] &self,
#[warn(C)] a: i32
) {}
}
struct MutStruct {}
impl MutStruct {
fn foo(
#[allow(C)] &mut self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait MutTrait {
fn foo(
#[forbid(C)] &mut self,
#[warn(C)] a: i32
) {}
}
impl MutTrait for MutStruct {
fn foo(
#[forbid(C)] &mut self,
#[warn(C)] a: i32
) {}
}
// self: Self, self: &Self and self: &mut Self
struct NamedSelfSelfStruct {}
impl NamedSelfSelfStruct {
fn foo(
#[allow(C)] self: Self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
struct NamedSelfRefStruct {}
impl NamedSelfRefStruct {
fn foo(
#[allow(C)] self: &Self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait NamedSelfRefTrait {
fn foo(
#[forbid(C)] self: &Self,
#[warn(C)] a: i32
) {}
}
impl NamedSelfRefTrait for NamedSelfRefStruct {
fn foo(
#[forbid(C)] self: &Self,
#[warn(C)] a: i32
) {}
}
struct NamedSelfMutStruct {}
impl NamedSelfMutStruct {
fn foo(
#[allow(C)] self: &mut Self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait NamedSelfMutTrait {
fn foo(
#[forbid(C)] self: &mut Self,
#[warn(C)] a: i32
) {}
}
impl NamedSelfMutTrait for NamedSelfMutStruct {
fn foo(
#[forbid(C)] self: &mut Self,
#[warn(C)] a: i32
) {}
}
// &'a self and &'a mut self
struct NamedLifetimeRefStruct {}
impl NamedLifetimeRefStruct {
fn foo<'a>(
#[allow(C)] self: &'a Self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait NamedLifetimeRefTrait {
fn foo<'a>(
#[forbid(C)] &'a self,
#[warn(C)] a: i32
) {}
}
impl NamedLifetimeRefTrait for NamedLifetimeRefStruct {
fn foo<'a>(
#[forbid(C)] &'a self,
#[warn(C)] a: i32
) {}
}
struct NamedLifetimeMutStruct {}
impl NamedLifetimeMutStruct {
fn foo<'a>(
#[allow(C)] self: &'a mut Self,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
) {}
}
trait NamedLifetimeMutTrait {
fn foo<'a>(
#[forbid(C)] &'a mut self,
#[warn(C)] a: i32
) {}
}
impl NamedLifetimeMutTrait for NamedLifetimeMutStruct {
fn foo<'a>(
#[forbid(C)] &'a mut self,
#[warn(C)] a: i32
#[forbid(unused_mut)] &self,
#[warn(unused_mut)] a: i32
) {}
}
@ -192,22 +69,22 @@ impl NamedLifetimeMutTrait for NamedLifetimeMutStruct {
struct BoxSelfStruct {}
impl BoxSelfStruct {
fn foo(
#[allow(C)] self: Box<Self>,
#[allow(unused_mut)] self: Box<Self>,
#[cfg(something)] a: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] b: i32,
#[deny(unused_mut)] b: i32,
) {}
}
trait BoxSelfTrait {
fn foo(
#[forbid(C)] self: Box<Self>,
#[warn(C)] a: i32
#[forbid(unused_mut)] self: Box<Self>,
#[warn(unused_mut)] a: i32
) {}
}
impl BoxSelfTrait for BoxSelfStruct {
fn foo(
#[forbid(C)] self: Box<Self>,
#[warn(C)] a: i32
#[forbid(unused_mut)] self: Box<Self>,
#[warn(unused_mut)] a: i32
) {}
}
@ -216,10 +93,10 @@ fn main() {
let _: fn(_, _, _, _) = foo;
let _: FnType = |_, _, _, _| {};
let c = |
#[allow(C)] a: u32,
#[allow(unused_mut)] a: u32,
#[cfg(something)] b: i32,
#[cfg_attr(something, cfg(nothing))]
#[deny(C)] c: i32,
#[deny(unused_mut)] c: i32,
| {};
let _ = c(1, 2);
}

View File

@ -1,6 +1,7 @@
// compile-flags: --cfg something
// edition:2018
#![feature(param_attrs)]
#![feature(async_await, async_closure, param_attrs)]
#![deny(unused_variables)]
extern "C" {
@ -19,24 +20,35 @@ type FnType = fn(
#[cfg_attr(something, cfg(nothing))] d: i32,
);
async fn foo_async(
#[cfg(something)] a: i32,
//~^ ERROR unused variable: `a`
#[cfg(nothing)] b: i32,
) {}
fn foo(
#[cfg(nothing)] a: i32,
#[cfg(something)] b: i32,
//~^ ERROR unused variable: `b` [unused_variables]
//~^ ERROR unused variable: `b`
#[cfg_attr(nothing, cfg(nothing))] c: i32,
//~^ ERROR unused variable: `c` [unused_variables]
//~^ ERROR unused variable: `c`
#[cfg_attr(something, cfg(nothing))] d: i32,
) {}
struct RefStruct {}
impl RefStruct {
async fn bar_async(
&self,
#[cfg(something)] a: i32,
//~^ ERROR unused variable: `a`
#[cfg(nothing)] b: i32,
) {}
fn bar(
&self,
#[cfg(nothing)] a: i32,
#[cfg(something)] b: i32,
//~^ ERROR unused variable: `b` [unused_variables]
//~^ ERROR unused variable: `b`
#[cfg_attr(nothing, cfg(nothing))] c: i32,
//~^ ERROR unused variable: `c` [unused_variables]
//~^ ERROR unused variable: `c`
#[cfg_attr(something, cfg(nothing))] d: i32,
) {}
}
@ -45,9 +57,9 @@ trait RefTrait {
&self,
#[cfg(nothing)] a: i32,
#[cfg(something)] b: i32,
//~^ ERROR unused variable: `b` [unused_variables]
//~^ ERROR unused variable: `b`
#[cfg_attr(nothing, cfg(nothing))] c: i32,
//~^ ERROR unused variable: `c` [unused_variables]
//~^ ERROR unused variable: `c`
#[cfg_attr(something, cfg(nothing))] d: i32,
) {}
}
@ -56,9 +68,9 @@ impl RefTrait for RefStruct {
&self,
#[cfg(nothing)] a: i32,
#[cfg(something)] b: i32,
//~^ ERROR unused variable: `b` [unused_variables]
//~^ ERROR unused variable: `b`
#[cfg_attr(nothing, cfg(nothing))] c: i32,
//~^ ERROR unused variable: `c` [unused_variables]
//~^ ERROR unused variable: `c`
#[cfg_attr(something, cfg(nothing))] d: i32,
) {}
}
@ -67,13 +79,19 @@ fn main() {
let _: unsafe extern "C" fn(_, ...) = ffi;
let _: fn(_, _) = foo;
let _: FnType = |_, _| {};
let a = async move |
#[cfg(something)] a: i32,
//~^ ERROR unused variable: `a`
#[cfg(nothing)] b: i32,
| {};
let c = |
#[cfg(nothing)] a: i32,
#[cfg(something)] b: i32,
//~^ ERROR unused variable: `b` [unused_variables]
//~^ ERROR unused variable: `b`
#[cfg_attr(nothing, cfg(nothing))] c: i32,
//~^ ERROR unused variable: `c` [unused_variables]
//~^ ERROR unused variable: `c`
#[cfg_attr(something, cfg(nothing))] d: i32,
| {};
let _ = a(1);
let _ = c(1, 2);
}

View File

@ -1,68 +1,86 @@
error: unused variable: `b`
error: unused variable: `a`
--> $DIR/param-attrs-cfg.rs:24:23
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
LL | #[cfg(something)] a: i32,
| ^ help: consider prefixing with an underscore: `_a`
|
note: lint level defined here
--> $DIR/param-attrs-cfg.rs:4:9
--> $DIR/param-attrs-cfg.rs:5:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:30:23
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:26:40
--> $DIR/param-attrs-cfg.rs:32:40
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: unused variable: `a`
--> $DIR/param-attrs-cfg.rs:83:27
|
LL | #[cfg(something)] a: i32,
| ^ help: consider prefixing with an underscore: `_a`
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:72:27
--> $DIR/param-attrs-cfg.rs:89:27
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:74:44
--> $DIR/param-attrs-cfg.rs:91:44
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:47:27
--> $DIR/param-attrs-cfg.rs:59:27
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:49:44
--> $DIR/param-attrs-cfg.rs:61:44
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: unused variable: `a`
--> $DIR/param-attrs-cfg.rs:41:27
|
LL | #[cfg(something)] a: i32,
| ^ help: consider prefixing with an underscore: `_a`
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:48:27
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:50:44
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:36:27
--> $DIR/param-attrs-cfg.rs:70:27
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:38:44
--> $DIR/param-attrs-cfg.rs:72:44
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: unused variable: `b`
--> $DIR/param-attrs-cfg.rs:58:27
|
LL | #[cfg(something)] b: i32,
| ^ help: consider prefixing with an underscore: `_b`
error: unused variable: `c`
--> $DIR/param-attrs-cfg.rs:60:44
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
| ^ help: consider prefixing with an underscore: `_c`
error: aborting due to 10 previous errors
error: aborting due to 13 previous errors

View File

@ -1,12 +1,14 @@
// gate-test-param_attrs
#![deny(unused_variables)]
fn foo(
/// Foo
//~^ ERROR documentation comments cannot be applied to function parameters
//~| NOTE doc comments are not allowed here
//~| ERROR attributes on function parameters are unstable
//~| NOTE https://github.com/rust-lang/rust/issues/60406
#[allow(C)] a: u8
#[allow(unused_variables)] a: u8
//~^ ERROR attributes on function parameters are unstable
//~| NOTE https://github.com/rust-lang/rust/issues/60406
) {}

View File

@ -1,11 +1,11 @@
error: documentation comments cannot be applied to function parameters
--> $DIR/param-attrs-feature-gate.rs:4:5
--> $DIR/param-attrs-feature-gate.rs:6:5
|
LL | /// Foo
| ^^^^^^^ doc comments are not allowed here
error[E0658]: attributes on function parameters are unstable
--> $DIR/param-attrs-feature-gate.rs:4:5
--> $DIR/param-attrs-feature-gate.rs:6:5
|
LL | /// Foo
| ^^^^^^^
@ -14,10 +14,10 @@ LL | /// Foo
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
error[E0658]: attributes on function parameters are unstable
--> $DIR/param-attrs-feature-gate.rs:9:5
--> $DIR/param-attrs-feature-gate.rs:11:5
|
LL | #[allow(C)] a: u8
| ^^^^^^^^^^^
LL | #[allow(unused_variables)] a: u8
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60406
= help: add `#![feature(param_attrs)]` to the crate attributes to enable

View File

@ -43,31 +43,19 @@ pub mod unstable_book;
fn filter_dirs(path: &Path) -> bool {
let skip = [
"src/llvm",
"src/llvm-project",
"src/llvm-emscripten",
"src/libbacktrace",
"src/librustc_data_structures/owning_ref",
"src/vendor",
"src/llvm-project",
"src/stdarch",
"src/tools/cargo",
"src/tools/clang",
"src/tools/rls",
"src/tools/clippy",
"src/tools/miri",
"src/tools/rls",
"src/tools/rust-installer",
"src/tools/rustfmt",
"src/tools/miri",
"src/tools/lld",
"src/tools/lldb",
"src/target",
"src/stdarch",
"src/rust-sgx",
"target",
"vendor",
];
skip.iter().any(|p| path.ends_with(p))
}
fn walk_many(
paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str)
) {

View File

@ -152,6 +152,8 @@ pub fn check(path: &Path, bad: &mut bool) {
let mut skip_file_length = contains_ignore_directive(can_contain, &contents, "filelength");
let mut skip_end_whitespace =
contains_ignore_directive(can_contain, &contents, "end-whitespace");
let mut skip_trailing_newlines =
contains_ignore_directive(can_contain, &contents, "trailing-newlines");
let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright");
let mut leading_new_lines = false;
let mut trailing_new_lines = 0;
@ -214,10 +216,17 @@ pub fn check(path: &Path, bad: &mut bool) {
if leading_new_lines {
tidy_error!(bad, "{}: leading newline", file.display());
}
let mut err = |msg: &str| {
tidy_error!(bad, "{}: {}", file.display(), msg);
};
match trailing_new_lines {
0 => tidy_error!(bad, "{}: missing trailing newline", file.display()),
0 => suppressible_tidy_err!(err, skip_trailing_newlines, "missing trailing newline"),
1 => {}
n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n),
n => suppressible_tidy_err!(
err,
skip_trailing_newlines,
&format!("too many trailing newlines ({})", n)
),
};
if lines > LINES {
let mut err = |_| {
@ -247,6 +256,9 @@ pub fn check(path: &Path, bad: &mut bool) {
if let Directive::Ignore(false) = skip_end_whitespace {
tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display());
}
if let Directive::Ignore(false) = skip_trailing_newlines {
tidy_error!(bad, "{}: ignoring trailing newlines unnecessarily", file.display());
}
if let Directive::Ignore(false) = skip_copyright {
tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display());
}