mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
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:
commit
c7312fe4ff
@ -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"
|
||||
|
@ -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")]
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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 :(
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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(_) |
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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")
|
||||
}
|
||||
)
|
||||
|
@ -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
|
||||
///
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -966,6 +966,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
attrs: ThinVec::default(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
pat: arg_pat,
|
||||
span,
|
||||
ty,
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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`.
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
64
src/test/ui/lint/lint-unused-variables.rs
Normal file
64
src/test/ui/lint/lint-unused-variables.rs
Normal 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);
|
||||
}
|
56
src/test/ui/lint/lint-unused-variables.stderr
Normal file
56
src/test/ui/lint/lint-unused-variables.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
8
src/test/ui/parser/issue-62973.rs
Normal file
8
src/test/ui/parser/issue-62973.rs
Normal 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 { [) {) }
|
||||
|
||||
|
61
src/test/ui/parser/issue-62973.stderr
Normal file
61
src/test/ui/parser/issue-62973.stderr
Normal 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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
) {}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
) {
|
||||
|
@ -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());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user