Auto merge of #96745 - ehuss:even-more-attribute-validation, r=cjgillot
Visit attributes in more places. This adds 3 loosely related changes (I can split PRs if desired): - Attribute checking on pattern struct fields. - Attribute checking on struct expression fields. - Lint level visiting on pattern struct fields, struct expression fields, and generic parameters. There are still some lints which ignore lint levels in various positions. This is a consequence of how the lints themselves are implemented. For example, lint levels on associated consts don't work with `unused_braces`.
This commit is contained in:
commit
6ce76091c7
23 changed files with 1520 additions and 141 deletions
|
@ -1406,8 +1406,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
|
||||
fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
|
||||
let hir_id = self.lower_node_id(f.id);
|
||||
self.lower_attrs(hir_id, &f.attrs);
|
||||
hir::ExprField {
|
||||
hir_id: self.next_id(),
|
||||
hir_id,
|
||||
ident: self.lower_ident(f.ident),
|
||||
expr: self.lower_expr(&f.expr),
|
||||
span: self.lower_span(f.span),
|
||||
|
|
|
@ -199,6 +199,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) {
|
||||
self.insert(field.span, field.hir_id, Node::PatField(field));
|
||||
self.with_parent(field.hir_id, |this| {
|
||||
intravisit::walk_pat_field(this, field);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, arm: &'hir Arm<'hir>) {
|
||||
let node = Node::Arm(arm);
|
||||
|
||||
|
@ -225,6 +232,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, field: &'hir ExprField<'hir>) {
|
||||
self.insert(field.span, field.hir_id, Node::ExprField(field));
|
||||
self.with_parent(field.hir_id, |this| {
|
||||
intravisit::walk_expr_field(this, field);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
|
||||
self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt));
|
||||
|
||||
|
|
|
@ -64,12 +64,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
|
||||
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField {
|
||||
hir_id: self.next_id(),
|
||||
ident: self.lower_ident(f.ident),
|
||||
pat: self.lower_pat(&f.pat),
|
||||
is_shorthand: f.is_shorthand,
|
||||
span: self.lower_span(f.span),
|
||||
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
|
||||
let hir_id = self.lower_node_id(f.id);
|
||||
self.lower_attrs(hir_id, &f.attrs);
|
||||
|
||||
hir::PatField {
|
||||
hir_id,
|
||||
ident: self.lower_ident(f.ident),
|
||||
pat: self.lower_pat(&f.pat),
|
||||
is_shorthand: f.is_shorthand,
|
||||
span: self.lower_span(f.span),
|
||||
}
|
||||
}));
|
||||
break hir::PatKind::Struct(qpath, fs, etc);
|
||||
}
|
||||
|
|
|
@ -3332,12 +3332,14 @@ pub enum Node<'hir> {
|
|||
Field(&'hir FieldDef<'hir>),
|
||||
AnonConst(&'hir AnonConst),
|
||||
Expr(&'hir Expr<'hir>),
|
||||
ExprField(&'hir ExprField<'hir>),
|
||||
Stmt(&'hir Stmt<'hir>),
|
||||
PathSegment(&'hir PathSegment<'hir>),
|
||||
Ty(&'hir Ty<'hir>),
|
||||
TypeBinding(&'hir TypeBinding<'hir>),
|
||||
TraitRef(&'hir TraitRef<'hir>),
|
||||
Pat(&'hir Pat<'hir>),
|
||||
PatField(&'hir PatField<'hir>),
|
||||
Arm(&'hir Arm<'hir>),
|
||||
Block(&'hir Block<'hir>),
|
||||
Local(&'hir Local<'hir>),
|
||||
|
@ -3388,6 +3390,8 @@ impl<'hir> Node<'hir> {
|
|||
| Node::Block(..)
|
||||
| Node::Ctor(..)
|
||||
| Node::Pat(..)
|
||||
| Node::PatField(..)
|
||||
| Node::ExprField(..)
|
||||
| Node::Arm(..)
|
||||
| Node::Local(..)
|
||||
| Node::Crate(..)
|
||||
|
|
|
@ -325,6 +325,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_pat(&mut self, p: &'v Pat<'v>) {
|
||||
walk_pat(self, p)
|
||||
}
|
||||
fn visit_pat_field(&mut self, f: &'v PatField<'v>) {
|
||||
walk_pat_field(self, f)
|
||||
}
|
||||
fn visit_array_length(&mut self, len: &'v ArrayLen) {
|
||||
walk_array_len(self, len)
|
||||
}
|
||||
|
@ -337,6 +340,9 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_let_expr(&mut self, lex: &'v Let<'v>) {
|
||||
walk_let_expr(self, lex)
|
||||
}
|
||||
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) {
|
||||
walk_expr_field(self, field)
|
||||
}
|
||||
fn visit_ty(&mut self, t: &'v Ty<'v>) {
|
||||
walk_ty(self, t)
|
||||
}
|
||||
|
@ -761,11 +767,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
|
|||
}
|
||||
PatKind::Struct(ref qpath, fields, _) => {
|
||||
visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
|
||||
for field in fields {
|
||||
visitor.visit_id(field.hir_id);
|
||||
visitor.visit_ident(field.ident);
|
||||
visitor.visit_pat(&field.pat)
|
||||
}
|
||||
walk_list!(visitor, visit_pat_field, fields);
|
||||
}
|
||||
PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats),
|
||||
PatKind::Tuple(tuple_elements, _) => {
|
||||
|
@ -792,6 +794,12 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'v>) {
|
||||
visitor.visit_id(field.hir_id);
|
||||
visitor.visit_ident(field.ident);
|
||||
visitor.visit_pat(&field.pat)
|
||||
}
|
||||
|
||||
pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
|
||||
visitor.visit_id(foreign_item.hir_id());
|
||||
visitor.visit_ident(foreign_item.ident);
|
||||
|
@ -1059,6 +1067,12 @@ pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>)
|
|||
walk_list!(visitor, visit_ty, let_expr.ty);
|
||||
}
|
||||
|
||||
pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField<'v>) {
|
||||
visitor.visit_id(field.hir_id);
|
||||
visitor.visit_ident(field.ident);
|
||||
visitor.visit_expr(&field.expr)
|
||||
}
|
||||
|
||||
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
|
||||
visitor.visit_id(expression.hir_id);
|
||||
match expression.kind {
|
||||
|
@ -1073,11 +1087,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
}
|
||||
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
|
||||
visitor.visit_qpath(qpath, expression.hir_id, expression.span);
|
||||
for field in fields {
|
||||
visitor.visit_id(field.hir_id);
|
||||
visitor.visit_ident(field.ident);
|
||||
visitor.visit_expr(&field.expr)
|
||||
}
|
||||
walk_list!(visitor, visit_expr_field, fields);
|
||||
walk_list!(visitor, visit_expr, optional_base);
|
||||
}
|
||||
ExprKind::Tup(subexpressions) => {
|
||||
|
|
|
@ -56,6 +56,8 @@ pub enum Target {
|
|||
GenericParam(GenericParamKind),
|
||||
MacroDef,
|
||||
Param,
|
||||
PatField,
|
||||
ExprField,
|
||||
}
|
||||
|
||||
impl Display for Target {
|
||||
|
@ -183,6 +185,8 @@ impl Target {
|
|||
},
|
||||
Target::MacroDef => "macro def",
|
||||
Target::Param => "function param",
|
||||
Target::PatField => "pattern field",
|
||||
Target::ExprField => "struct field",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,12 +83,14 @@ impl<'a> State<'a> {
|
|||
Node::Variant(a) => self.print_variant(a),
|
||||
Node::AnonConst(a) => self.print_anon_const(a),
|
||||
Node::Expr(a) => self.print_expr(a),
|
||||
Node::ExprField(a) => self.print_expr_field(&a),
|
||||
Node::Stmt(a) => self.print_stmt(a),
|
||||
Node::PathSegment(a) => self.print_path_segment(a),
|
||||
Node::Ty(a) => self.print_type(a),
|
||||
Node::TypeBinding(a) => self.print_type_binding(a),
|
||||
Node::TraitRef(a) => self.print_trait_ref(a),
|
||||
Node::Pat(a) => self.print_pat(a),
|
||||
Node::PatField(a) => self.print_patfield(&a),
|
||||
Node::Arm(a) => self.print_arm(a),
|
||||
Node::Infer(_) => self.word("_"),
|
||||
Node::Block(a) => {
|
||||
|
@ -1127,20 +1129,7 @@ impl<'a> State<'a> {
|
|||
) {
|
||||
self.print_qpath(qpath, true);
|
||||
self.word("{");
|
||||
self.commasep_cmnt(
|
||||
Consistent,
|
||||
fields,
|
||||
|s, field| {
|
||||
s.ibox(INDENT_UNIT);
|
||||
if !field.is_shorthand {
|
||||
s.print_ident(field.ident);
|
||||
s.word_space(":");
|
||||
}
|
||||
s.print_expr(field.expr);
|
||||
s.end()
|
||||
},
|
||||
|f| f.span,
|
||||
);
|
||||
self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
|
||||
if let Some(expr) = wth {
|
||||
self.ibox(INDENT_UNIT);
|
||||
if !fields.is_empty() {
|
||||
|
@ -1157,6 +1146,20 @@ impl<'a> State<'a> {
|
|||
self.word("}");
|
||||
}
|
||||
|
||||
fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
|
||||
if self.attrs(field.hir_id).is_empty() {
|
||||
self.space();
|
||||
}
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.print_outer_attributes(&self.attrs(field.hir_id));
|
||||
if !field.is_shorthand {
|
||||
self.print_ident(field.ident);
|
||||
self.word_space(":");
|
||||
}
|
||||
self.print_expr(&field.expr);
|
||||
self.end()
|
||||
}
|
||||
|
||||
fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
|
||||
self.popen();
|
||||
self.commasep_exprs(Inconsistent, exprs);
|
||||
|
@ -1803,20 +1806,7 @@ impl<'a> State<'a> {
|
|||
if !empty {
|
||||
self.space();
|
||||
}
|
||||
self.commasep_cmnt(
|
||||
Consistent,
|
||||
fields,
|
||||
|s, f| {
|
||||
s.cbox(INDENT_UNIT);
|
||||
if !f.is_shorthand {
|
||||
s.print_ident(f.ident);
|
||||
s.word_nbsp(":");
|
||||
}
|
||||
s.print_pat(f.pat);
|
||||
s.end()
|
||||
},
|
||||
|f| f.pat.span,
|
||||
);
|
||||
self.commasep_cmnt(Consistent, &fields, |s, f| s.print_patfield(f), |f| f.pat.span);
|
||||
if etc {
|
||||
if !fields.is_empty() {
|
||||
self.word_space(",");
|
||||
|
@ -1911,6 +1901,20 @@ impl<'a> State<'a> {
|
|||
self.ann.post(self, AnnNode::Pat(pat))
|
||||
}
|
||||
|
||||
pub fn print_patfield(&mut self, field: &hir::PatField<'_>) {
|
||||
if self.attrs(field.hir_id).is_empty() {
|
||||
self.space();
|
||||
}
|
||||
self.cbox(INDENT_UNIT);
|
||||
self.print_outer_attributes(&self.attrs(field.hir_id));
|
||||
if !field.is_shorthand {
|
||||
self.print_ident(field.ident);
|
||||
self.word_nbsp(":");
|
||||
}
|
||||
self.print_pat(field.pat);
|
||||
self.end();
|
||||
}
|
||||
|
||||
pub fn print_param(&mut self, arg: &hir::Param<'_>) {
|
||||
self.print_outer_attributes(self.attrs(arg.hir_id));
|
||||
self.print_pat(arg.pat);
|
||||
|
|
|
@ -101,6 +101,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
run_early_pass!(self, check_pat_post, p);
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'a ast::PatField) {
|
||||
self.with_lint_attrs(field.id, &field.attrs, |cx| {
|
||||
ast_visit::walk_pat_field(cx, field);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
|
||||
self.check_id(c.id);
|
||||
ast_visit::walk_anon_const(self, c);
|
||||
|
@ -219,9 +225,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
|
||||
run_early_pass!(self, check_generic_param, param);
|
||||
self.check_id(param.id);
|
||||
ast_visit::walk_generic_param(self, param);
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
run_early_pass!(cx, check_generic_param, param);
|
||||
ast_visit::walk_generic_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, g: &'a ast::Generics) {
|
||||
|
|
|
@ -766,6 +766,12 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
|
||||
self.with_lint_attrs(field.hir_id, |builder| {
|
||||
intravisit::walk_expr_field(builder, field);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
|
||||
self.with_lint_attrs(s.hir_id, |builder| {
|
||||
intravisit::walk_field_def(builder, s);
|
||||
|
@ -801,6 +807,18 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
|
|||
intravisit::walk_impl_item(builder, impl_item);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) {
|
||||
self.with_lint_attrs(field.hir_id, |builder| {
|
||||
intravisit::walk_pat_field(builder, field);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
|
||||
self.with_lint_attrs(p.hir_id, |builder| {
|
||||
intravisit::walk_generic_param(builder, p);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
|
@ -437,19 +437,14 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
|
|||
|
||||
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
|
||||
if let PatKind::Binding(_, hid, ident, _) = p.kind {
|
||||
if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
|
||||
if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
|
||||
{
|
||||
if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
|
||||
if field_pats
|
||||
.iter()
|
||||
.any(|field| !field.is_shorthand && field.pat.hir_id == p.hir_id)
|
||||
{
|
||||
// Only check if a new name has been introduced, to avoid warning
|
||||
// on both the struct definition and this pattern.
|
||||
self.check_snake_case(cx, "variable", &ident);
|
||||
}
|
||||
return;
|
||||
if !field.is_shorthand {
|
||||
// Only check if a new name has been introduced, to avoid warning
|
||||
// on both the struct definition and this pattern.
|
||||
self.check_snake_case(cx, "variable", &ident);
|
||||
}
|
||||
return;
|
||||
}
|
||||
self.check_snake_case(cx, "variable", &ident);
|
||||
}
|
||||
|
|
|
@ -125,45 +125,51 @@ fn lint_overflowing_range_endpoint<'tcx>(
|
|||
lit_val: u128,
|
||||
max: u128,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
parent_expr: &'tcx hir::Expr<'tcx>,
|
||||
ty: &str,
|
||||
) -> bool {
|
||||
// We only want to handle exclusive (`..`) ranges,
|
||||
// which are represented as `ExprKind::Struct`.
|
||||
let par_id = cx.tcx.hir().get_parent_node(expr.hir_id);
|
||||
let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false };
|
||||
let field_par_id = cx.tcx.hir().get_parent_node(field.hir_id);
|
||||
let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false };
|
||||
if !is_range_literal(struct_expr) {
|
||||
return false;
|
||||
};
|
||||
let ExprKind::Struct(_, eps, _) = &struct_expr.kind else { return false };
|
||||
if eps.len() != 2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut overwritten = false;
|
||||
if let ExprKind::Struct(_, eps, _) = &parent_expr.kind {
|
||||
if eps.len() != 2 {
|
||||
return false;
|
||||
}
|
||||
// We can suggest using an inclusive range
|
||||
// (`..=`) instead only if it is the `end` that is
|
||||
// overflowing and only by 1.
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, parent_expr.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
|
||||
err.set_arg("ty", ty);
|
||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
||||
use ast::{LitIntType, LitKind};
|
||||
// We need to preserve the literal's suffix,
|
||||
// as it may determine typing information.
|
||||
let suffix = match lit.node {
|
||||
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
|
||||
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
|
||||
LitKind::Int(_, LitIntType::Unsuffixed) => "",
|
||||
_ => bug!(),
|
||||
};
|
||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||
err.span_suggestion(
|
||||
parent_expr.span,
|
||||
fluent::lint::suggestion,
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
overwritten = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
// We can suggest using an inclusive range
|
||||
// (`..=`) instead only if it is the `end` that is
|
||||
// overflowing and only by 1.
|
||||
if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
|
||||
let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
|
||||
err.set_arg("ty", ty);
|
||||
if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
|
||||
use ast::{LitIntType, LitKind};
|
||||
// We need to preserve the literal's suffix,
|
||||
// as it may determine typing information.
|
||||
let suffix = match lit.node {
|
||||
LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
|
||||
LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
|
||||
LitKind::Int(_, LitIntType::Unsuffixed) => "",
|
||||
_ => bug!(),
|
||||
};
|
||||
let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
|
||||
err.span_suggestion(
|
||||
struct_expr.span,
|
||||
fluent::lint::suggestion,
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
overwritten = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
overwritten
|
||||
}
|
||||
|
@ -339,16 +345,9 @@ fn lint_int_literal<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
let par_id = cx.tcx.hir().get_parent_node(e.hir_id);
|
||||
if let Node::Expr(par_e) = cx.tcx.hir().get(par_id) {
|
||||
if let hir::ExprKind::Struct(..) = par_e.kind {
|
||||
if is_range_literal(par_e)
|
||||
&& lint_overflowing_range_endpoint(cx, lit, v, max, e, par_e, t.name_str())
|
||||
{
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
}
|
||||
if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
|
||||
cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
|
||||
|
@ -408,16 +407,13 @@ fn lint_uint_literal<'tcx>(
|
|||
return;
|
||||
}
|
||||
}
|
||||
hir::ExprKind::Struct(..) if is_range_literal(par_e) => {
|
||||
let t = t.name_str();
|
||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, par_e, t) {
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
|
||||
// The overflowing literal lint was overridden.
|
||||
return;
|
||||
}
|
||||
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
|
||||
report_bin_hex_error(
|
||||
cx,
|
||||
|
|
|
@ -297,6 +297,8 @@ impl<'hir> Map<'hir> {
|
|||
| Node::Infer(_)
|
||||
| Node::TraitRef(_)
|
||||
| Node::Pat(_)
|
||||
| Node::PatField(_)
|
||||
| Node::ExprField(_)
|
||||
| Node::Local(_)
|
||||
| Node::Param(_)
|
||||
| Node::Arm(_)
|
||||
|
@ -1020,6 +1022,7 @@ impl<'hir> Map<'hir> {
|
|||
Node::Field(field) => field.span,
|
||||
Node::AnonConst(constant) => self.body(constant.body).value.span,
|
||||
Node::Expr(expr) => expr.span,
|
||||
Node::ExprField(field) => field.span,
|
||||
Node::Stmt(stmt) => stmt.span,
|
||||
Node::PathSegment(seg) => {
|
||||
let ident_span = seg.ident.span;
|
||||
|
@ -1030,6 +1033,7 @@ impl<'hir> Map<'hir> {
|
|||
Node::TypeBinding(tb) => tb.span,
|
||||
Node::TraitRef(tr) => tr.path.span,
|
||||
Node::Pat(pat) => pat.span,
|
||||
Node::PatField(field) => field.span,
|
||||
Node::Arm(arm) => arm.span,
|
||||
Node::Block(block) => block.span,
|
||||
Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)),
|
||||
|
@ -1241,12 +1245,14 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
}
|
||||
Some(Node::AnonConst(_)) => node_str("const"),
|
||||
Some(Node::Expr(_)) => node_str("expr"),
|
||||
Some(Node::ExprField(_)) => node_str("expr field"),
|
||||
Some(Node::Stmt(_)) => node_str("stmt"),
|
||||
Some(Node::PathSegment(_)) => node_str("path segment"),
|
||||
Some(Node::Ty(_)) => node_str("type"),
|
||||
Some(Node::TypeBinding(_)) => node_str("type binding"),
|
||||
Some(Node::TraitRef(_)) => node_str("trait ref"),
|
||||
Some(Node::Pat(_)) => node_str("pat"),
|
||||
Some(Node::PatField(_)) => node_str("pattern field"),
|
||||
Some(Node::Param(_)) => node_str("param"),
|
||||
Some(Node::Arm(_)) => node_str("arm"),
|
||||
Some(Node::Block(_)) => node_str("block"),
|
||||
|
|
|
@ -652,7 +652,9 @@ impl CheckAttrVisitor<'_> {
|
|||
| Target::ForeignStatic
|
||||
| Target::ForeignTy
|
||||
| Target::GenericParam(..)
|
||||
| Target::MacroDef => None,
|
||||
| Target::MacroDef
|
||||
| Target::PatField
|
||||
| Target::ExprField => None,
|
||||
} {
|
||||
tcx.sess.emit_err(errors::DocAliasBadLocation { span, attr_str, location });
|
||||
return false;
|
||||
|
@ -2066,6 +2068,11 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
|||
intravisit::walk_expr(self, expr)
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
|
||||
self.check_attributes(field.hir_id, field.span, Target::ExprField, None);
|
||||
intravisit::walk_expr_field(self, field)
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, variant: &'tcx hir::Variant<'tcx>) {
|
||||
self.check_attributes(variant.id, variant.span, Target::Variant, None);
|
||||
intravisit::walk_variant(self, variant)
|
||||
|
@ -2076,6 +2083,11 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
|||
|
||||
intravisit::walk_param(self, param);
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) {
|
||||
self.check_attributes(field.hir_id, field.span, Target::PatField, None);
|
||||
intravisit::walk_pat_field(self, field);
|
||||
}
|
||||
}
|
||||
|
||||
fn is_c_like_enum(item: &Item<'_>) -> bool {
|
||||
|
|
|
@ -638,11 +638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}?;
|
||||
|
||||
match hir.find(hir.get_parent_node(expr.hir_id))? {
|
||||
Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) => {
|
||||
for field in *fields {
|
||||
if field.ident.name == local.name && field.is_shorthand {
|
||||
return Some(local.name);
|
||||
}
|
||||
Node::ExprField(field) => {
|
||||
if field.ident.name == local.name && field.is_shorthand {
|
||||
return Some(local.name);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1073,21 +1071,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let mut sugg = vec![];
|
||||
|
||||
if let Some(hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Struct(_, fields, _), ..
|
||||
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||
if let Some(hir::Node::ExprField(field)) =
|
||||
self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
|
||||
{
|
||||
// `expr` is a literal field for a struct, only suggest if appropriate
|
||||
match (*fields)
|
||||
.iter()
|
||||
.find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand)
|
||||
{
|
||||
if field.is_shorthand {
|
||||
// This is a field literal
|
||||
Some(field) => {
|
||||
sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
|
||||
}
|
||||
sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
|
||||
} else {
|
||||
// Likely a field was meant, but this field wasn't found. Do not suggest anything.
|
||||
None => return false,
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -256,6 +256,8 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
|
|||
| hir::Node::TypeBinding(..)
|
||||
| hir::Node::TraitRef(..)
|
||||
| hir::Node::Pat(..)
|
||||
| hir::Node::PatField(..)
|
||||
| hir::Node::ExprField(..)
|
||||
| hir::Node::Arm(..)
|
||||
| hir::Node::Local(..)
|
||||
| hir::Node::Ctor(..)
|
||||
|
|
|
@ -927,7 +927,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
),
|
||||
);
|
||||
match self.tcx.hir().get(self.tcx.hir().get_parent_node(pat.hir_id)) {
|
||||
hir::Node::Pat(Pat { kind: hir::PatKind::Struct(..), .. }) => {
|
||||
hir::Node::PatField(..) => {
|
||||
e.span_suggestion_verbose(
|
||||
ident.span.shrink_to_hi(),
|
||||
"bind the struct field to a different name instead",
|
||||
|
|
176
src/test/ui/lint/lint-attr-everywhere-early.rs
Normal file
176
src/test/ui/lint/lint-attr-everywhere-early.rs
Normal file
|
@ -0,0 +1,176 @@
|
|||
// Tests that lint levels can be set for early lints.
|
||||
#![allow(non_camel_case_types, unsafe_code, while_true, unused_parens)]
|
||||
|
||||
// The following is a check of the lints used here to verify they do not warn
|
||||
// when allowed.
|
||||
fn verify_no_warnings() {
|
||||
type non_camel_type = i32; // non_camel_case_types
|
||||
struct NON_CAMEL_IS_ALLOWED; // non_camel_case_types
|
||||
unsafe {} // unsafe_code
|
||||
enum Enum {
|
||||
VARIANT_CAMEL // non_camel_case_types
|
||||
}
|
||||
fn generics<foo>() {} // non_camel_case_types
|
||||
while true {} // while_true
|
||||
type T = (i32); // unused_parens
|
||||
}
|
||||
|
||||
|
||||
// ################## Types
|
||||
|
||||
#[deny(non_camel_case_types)]
|
||||
type type_outer = i32; //~ ERROR type `type_outer` should have an upper camel case name
|
||||
|
||||
type BareFnPtr = fn(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type
|
||||
// There aren't any early lints that currently apply to the variadic spot.
|
||||
// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...);
|
||||
|
||||
// ################## Items
|
||||
#[deny(non_camel_case_types)]
|
||||
struct ITEM_OUTER; //~ ERROR type `ITEM_OUTER` should have an upper camel case name
|
||||
|
||||
mod module_inner {
|
||||
#![deny(unsafe_code)]
|
||||
fn f() {
|
||||
unsafe {} //~ ERROR usage of an `unsafe` block
|
||||
}
|
||||
}
|
||||
|
||||
struct Associated;
|
||||
impl Associated {
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
fn inherent_denied_from_inner() { unsafe {} } //~ usage of an `unsafe` block
|
||||
|
||||
#[deny(while_true)]
|
||||
fn inherent_fn() { while true {} } //~ ERROR denote infinite loops with
|
||||
|
||||
#[deny(while_true)]
|
||||
const INHERENT_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with
|
||||
}
|
||||
|
||||
trait trait_inner { //~ ERROR trait `trait_inner` should have an upper camel case name
|
||||
#![deny(non_camel_case_types)]
|
||||
}
|
||||
|
||||
trait AssociatedTrait {
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block
|
||||
|
||||
#[deny(while_true)]
|
||||
fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with
|
||||
|
||||
#[deny(while_true)]
|
||||
const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with
|
||||
|
||||
#[deny(non_camel_case_types)]
|
||||
type assoc_type; //~ ERROR associated type `assoc_type` should have an upper camel case name
|
||||
}
|
||||
|
||||
impl AssociatedTrait for Associated {
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block
|
||||
|
||||
#[deny(while_true)]
|
||||
fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with
|
||||
|
||||
#[deny(while_true)]
|
||||
const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with
|
||||
|
||||
#[deny(unused_parens)]
|
||||
type assoc_type = (i32); //~ ERROR unnecessary parentheses around type
|
||||
}
|
||||
|
||||
struct StructFields {
|
||||
#[deny(unused_parens)]f1: (i32), //~ ERROR unnecessary parentheses around type
|
||||
}
|
||||
struct StructTuple(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type
|
||||
|
||||
enum Enum {
|
||||
#[deny(non_camel_case_types)]
|
||||
VARIANT_CAMEL, //~ ERROR variant `VARIANT_CAMEL` should have an upper camel case name
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#![deny(unused_parens)]
|
||||
|
||||
fn foreign_denied_from_inner(x: (i32)); //~ ERROR unnecessary parentheses around type
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[deny(unused_parens)]
|
||||
fn foreign_denied_from_outer(x: (i32)); //~ ERROR unnecessary parentheses around type
|
||||
}
|
||||
|
||||
fn function(#[deny(unused_parens)] param: (i32)) {} //~ ERROR unnecessary parentheses around type
|
||||
|
||||
fn generics<#[deny(non_camel_case_types)]foo>() {} //~ ERROR type parameter `foo` should have an upper camel case name
|
||||
|
||||
|
||||
// ################## Statements
|
||||
fn statements() {
|
||||
#[deny(unused_parens)]
|
||||
let x = (1); //~ ERROR unnecessary parentheses around assigned value
|
||||
}
|
||||
|
||||
|
||||
// ################## Expressions
|
||||
fn expressions() {
|
||||
let closure = |#[deny(unused_parens)] param: (i32)| {}; //~ ERROR unnecessary parentheses around type
|
||||
|
||||
struct Match{f1: i32}
|
||||
// Strangely unused_parens doesn't fire with {f1: (123)}
|
||||
let f = Match{#[deny(unused_parens)]f1: {(123)}}; //~ ERROR unnecessary parentheses around block return value
|
||||
|
||||
match f {
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[deny(while_true)]
|
||||
Match{f1} => {
|
||||
unsafe {} //~ ERROR usage of an `unsafe` block
|
||||
while true {} //~ ERROR denote infinite loops with
|
||||
}
|
||||
}
|
||||
|
||||
// Statement Block
|
||||
{
|
||||
#![deny(unsafe_code)]
|
||||
unsafe {} //~ ERROR usage of an `unsafe` block
|
||||
}
|
||||
let block_tail = {
|
||||
#[deny(unsafe_code)]
|
||||
unsafe {} //~ ERROR usage of an `unsafe` block
|
||||
};
|
||||
|
||||
// Before expression as a statement.
|
||||
#[deny(unsafe_code)]
|
||||
unsafe {}; //~ ERROR usage of an `unsafe` block
|
||||
|
||||
[#[deny(unsafe_code)] unsafe {123}]; //~ ERROR usage of an `unsafe` block
|
||||
(#[deny(unsafe_code)] unsafe {123},); //~ ERROR usage of an `unsafe` block
|
||||
fn call(p: i32) {}
|
||||
call(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block
|
||||
struct TupleStruct(i32);
|
||||
TupleStruct(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block
|
||||
}
|
||||
|
||||
|
||||
// ################## Patterns
|
||||
fn patterns() {
|
||||
struct PatField{f1: i32, f2: i32};
|
||||
let f = PatField{f1: 1, f2: 2};
|
||||
match f {
|
||||
PatField {
|
||||
#[deny(ellipsis_inclusive_range_patterns)]
|
||||
f1: 0...100,
|
||||
//~^ ERROR range patterns are deprecated
|
||||
//~| WARNING this is accepted in the current edition
|
||||
..
|
||||
} => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
486
src/test/ui/lint/lint-attr-everywhere-early.stderr
Normal file
486
src/test/ui/lint/lint-attr-everywhere-early.stderr
Normal file
|
@ -0,0 +1,486 @@
|
|||
error: type `type_outer` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:22:6
|
||||
|
|
||||
LL | type type_outer = i32;
|
||||
| ^^^^^^^^^^ help: convert the identifier to upper camel case: `TypeOuter`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:21:8
|
||||
|
|
||||
LL | #[deny(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:24:43
|
||||
|
|
||||
LL | type BareFnPtr = fn(#[deny(unused_parens)](i32));
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:24:28
|
||||
|
|
||||
LL | type BareFnPtr = fn(#[deny(unused_parens)](i32));
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - type BareFnPtr = fn(#[deny(unused_parens)](i32));
|
||||
LL + type BareFnPtr = fn(#[deny(unused_parens)]i32);
|
||||
|
|
||||
|
||||
error: type `ITEM_OUTER` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:30:8
|
||||
|
|
||||
LL | struct ITEM_OUTER;
|
||||
| ^^^^^^^^^^ help: convert the identifier to upper camel case: `ItemOuter`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:29:8
|
||||
|
|
||||
LL | #[deny(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:35:9
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:33:13
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:43:39
|
||||
|
|
||||
LL | fn inherent_denied_from_inner() { unsafe {} }
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:41:13
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:46:24
|
||||
|
|
||||
LL | fn inherent_fn() { while true {} }
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:45:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:49:34
|
||||
|
|
||||
LL | const INHERENT_CONST: i32 = {while true {} 1};
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:48:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: trait `trait_inner` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:52:7
|
||||
|
|
||||
LL | trait trait_inner {
|
||||
| ^^^^^^^^^^^ help: convert the identifier to upper camel case: `TraitInner`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:53:13
|
||||
|
|
||||
LL | #![deny(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:59:30
|
||||
|
|
||||
LL | fn denied_from_inner() { unsafe {} }
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:57:13
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:62:21
|
||||
|
|
||||
LL | fn assoc_fn() { while true {} }
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:61:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:65:31
|
||||
|
|
||||
LL | const ASSOC_CONST: i32 = {while true {} 1};
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:64:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: associated type `assoc_type` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:68:10
|
||||
|
|
||||
LL | type assoc_type;
|
||||
| ^^^^^^^^^^ help: convert the identifier to upper camel case: `AssocType`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:67:12
|
||||
|
|
||||
LL | #[deny(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:74:30
|
||||
|
|
||||
LL | fn denied_from_inner() { unsafe {} }
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:72:13
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:77:21
|
||||
|
|
||||
LL | fn assoc_fn() { while true {} }
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:76:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:80:31
|
||||
|
|
||||
LL | const ASSOC_CONST: i32 = {while true {} 1};
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:79:12
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:83:23
|
||||
|
|
||||
LL | type assoc_type = (i32);
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:82:12
|
||||
|
|
||||
LL | #[deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - type assoc_type = (i32);
|
||||
LL + type assoc_type = i32;
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:87:31
|
||||
|
|
||||
LL | #[deny(unused_parens)]f1: (i32),
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:87:12
|
||||
|
|
||||
LL | #[deny(unused_parens)]f1: (i32),
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - #[deny(unused_parens)]f1: (i32),
|
||||
LL + #[deny(unused_parens)]f1: i32,
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:89:42
|
||||
|
|
||||
LL | struct StructTuple(#[deny(unused_parens)](i32));
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:89:27
|
||||
|
|
||||
LL | struct StructTuple(#[deny(unused_parens)](i32));
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - struct StructTuple(#[deny(unused_parens)](i32));
|
||||
LL + struct StructTuple(#[deny(unused_parens)]i32);
|
||||
|
|
||||
|
||||
error: variant `VARIANT_CAMEL` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:93:5
|
||||
|
|
||||
LL | VARIANT_CAMEL,
|
||||
| ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `VariantCamel`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:92:12
|
||||
|
|
||||
LL | #[deny(non_camel_case_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:99:37
|
||||
|
|
||||
LL | fn foreign_denied_from_inner(x: (i32));
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:97:13
|
||||
|
|
||||
LL | #![deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - fn foreign_denied_from_inner(x: (i32));
|
||||
LL + fn foreign_denied_from_inner(x: i32);
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:104:37
|
||||
|
|
||||
LL | fn foreign_denied_from_outer(x: (i32));
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:103:12
|
||||
|
|
||||
LL | #[deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - fn foreign_denied_from_outer(x: (i32));
|
||||
LL + fn foreign_denied_from_outer(x: i32);
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:107:43
|
||||
|
|
||||
LL | fn function(#[deny(unused_parens)] param: (i32)) {}
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:107:20
|
||||
|
|
||||
LL | fn function(#[deny(unused_parens)] param: (i32)) {}
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - fn function(#[deny(unused_parens)] param: (i32)) {}
|
||||
LL + fn function(#[deny(unused_parens)] param: i32) {}
|
||||
|
|
||||
|
||||
error: type parameter `foo` should have an upper camel case name
|
||||
--> $DIR/lint-attr-everywhere-early.rs:109:42
|
||||
|
|
||||
LL | fn generics<#[deny(non_camel_case_types)]foo>() {}
|
||||
| ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:109:20
|
||||
|
|
||||
LL | fn generics<#[deny(non_camel_case_types)]foo>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unnecessary parentheses around assigned value
|
||||
--> $DIR/lint-attr-everywhere-early.rs:115:13
|
||||
|
|
||||
LL | let x = (1);
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:114:12
|
||||
|
|
||||
LL | #[deny(unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - let x = (1);
|
||||
LL + let x = 1;
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around type
|
||||
--> $DIR/lint-attr-everywhere-early.rs:121:50
|
||||
|
|
||||
LL | let closure = |#[deny(unused_parens)] param: (i32)| {};
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:121:27
|
||||
|
|
||||
LL | let closure = |#[deny(unused_parens)] param: (i32)| {};
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - let closure = |#[deny(unused_parens)] param: (i32)| {};
|
||||
LL + let closure = |#[deny(unused_parens)] param: i32| {};
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around block return value
|
||||
--> $DIR/lint-attr-everywhere-early.rs:125:46
|
||||
|
|
||||
LL | let f = Match{#[deny(unused_parens)]f1: {(123)}};
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:125:26
|
||||
|
|
||||
LL | let f = Match{#[deny(unused_parens)]f1: {(123)}};
|
||||
| ^^^^^^^^^^^^^
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - let f = Match{#[deny(unused_parens)]f1: {(123)}};
|
||||
LL + let f = Match{#[deny(unused_parens)]f1: {123}};
|
||||
|
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:132:13
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:128:17
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-attr-everywhere-early.rs:133:13
|
||||
|
|
||||
LL | while true {}
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:130:16
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:140:9
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:139:17
|
||||
|
|
||||
LL | #![deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:144:9
|
||||
|
|
||||
LL | unsafe {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:143:16
|
||||
|
|
||||
LL | #[deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:149:5
|
||||
|
|
||||
LL | unsafe {};
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:148:12
|
||||
|
|
||||
LL | #[deny(unsafe_code)]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:151:27
|
||||
|
|
||||
LL | [#[deny(unsafe_code)] unsafe {123}];
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:151:13
|
||||
|
|
||||
LL | [#[deny(unsafe_code)] unsafe {123}];
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:152:27
|
||||
|
|
||||
LL | (#[deny(unsafe_code)] unsafe {123},);
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:152:13
|
||||
|
|
||||
LL | (#[deny(unsafe_code)] unsafe {123},);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:154:31
|
||||
|
|
||||
LL | call(#[deny(unsafe_code)] unsafe {123});
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:154:17
|
||||
|
|
||||
LL | call(#[deny(unsafe_code)] unsafe {123});
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: usage of an `unsafe` block
|
||||
--> $DIR/lint-attr-everywhere-early.rs:156:38
|
||||
|
|
||||
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:156:24
|
||||
|
|
||||
LL | TupleStruct(#[deny(unsafe_code)] unsafe {123});
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `...` range patterns are deprecated
|
||||
--> $DIR/lint-attr-everywhere-early.rs:167:18
|
||||
|
|
||||
LL | f1: 0...100,
|
||||
| ^^^ help: use `..=` for an inclusive range
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-early.rs:166:20
|
||||
|
|
||||
LL | #[deny(ellipsis_inclusive_range_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
|
||||
|
||||
error: aborting due to 36 previous errors
|
||||
|
197
src/test/ui/lint/lint-attr-everywhere-late.rs
Normal file
197
src/test/ui/lint/lint-attr-everywhere-late.rs
Normal file
|
@ -0,0 +1,197 @@
|
|||
// Tests that lint levels can be set for late lints.
|
||||
#![allow(
|
||||
non_snake_case,
|
||||
overflowing_literals,
|
||||
missing_docs,
|
||||
dyn_drop,
|
||||
enum_intrinsics_non_enums,
|
||||
clashing_extern_declarations
|
||||
)]
|
||||
|
||||
extern crate core;
|
||||
use core::mem::{Discriminant, discriminant};
|
||||
|
||||
// The following is a check of the lints used here to verify they do not warn
|
||||
// when allowed.
|
||||
pub fn missing_docs_allowed() {} // missing_docs
|
||||
fn dyn_drop_allowed(_x: Box<dyn Drop>) {} // dyn_drop
|
||||
fn verify_no_warnings() {
|
||||
discriminant::<i32>(&123); // enum_intrinsics_non_enums
|
||||
let x: u8 = 1000; // overflowing_literals
|
||||
let NON_SNAKE_CASE = 1; // non_snake_case
|
||||
}
|
||||
mod clashing_extern_allowed {
|
||||
extern "C" {
|
||||
fn extern_allowed();
|
||||
}
|
||||
}
|
||||
extern "C" {
|
||||
fn extern_allowed(_: i32); // clashing_extern_declarations
|
||||
}
|
||||
|
||||
// ################## Types
|
||||
|
||||
#[deny(missing_docs)]
|
||||
pub type MissingDocType = i32; //~ ERROR missing documentation for a type alias
|
||||
|
||||
// There aren't any late lints that I can find that can be easily used with types.
|
||||
// type BareFnPtr = fn(#[deny()]i32);
|
||||
// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...);
|
||||
|
||||
// ################## Items
|
||||
#[deny(missing_docs)]
|
||||
pub struct ItemOuter; //~ ERROR missing documentation for a struct
|
||||
|
||||
pub mod module_inner { //~ ERROR missing documentation for a module
|
||||
#![deny(missing_docs)]
|
||||
pub fn missing_inner() {} //~ ERROR missing documentation for a function
|
||||
}
|
||||
|
||||
pub struct Associated;
|
||||
impl Associated {
|
||||
#![deny(missing_docs)]
|
||||
|
||||
pub fn inherent_denied_from_inner() {} //~ ERROR missing documentation for an associated function
|
||||
}
|
||||
|
||||
impl Associated {
|
||||
#[deny(missing_docs)]
|
||||
pub fn inherent_fn() {} //~ ERROR missing documentation for an associated function
|
||||
|
||||
#[deny(missing_docs)]
|
||||
pub const INHERENT_CONST: i32 = 1; //~ ERROR missing documentation for an associated constant
|
||||
}
|
||||
|
||||
pub trait TraitInner { //~ ERROR missing documentation for a trait
|
||||
#![deny(missing_docs)]
|
||||
}
|
||||
|
||||
pub trait AssociatedTraitInner { //~ ERROR missing documentation for a trait
|
||||
#![deny(missing_docs)]
|
||||
|
||||
fn denied_from_inner() {} //~ ERROR missing documentation for an associated function
|
||||
}
|
||||
|
||||
pub trait AssociatedTrait {
|
||||
fn denied_from_inner(_x: Box<dyn Drop>) {} // Used below
|
||||
|
||||
#[deny(missing_docs)]
|
||||
fn assoc_fn() {} //~ ERROR missing documentation for an associated function
|
||||
|
||||
#[deny(missing_docs)]
|
||||
const ASSOC_CONST: u8 = 1; //~ ERROR missing documentation for an associated constant
|
||||
|
||||
#[deny(missing_docs)]
|
||||
type AssocType; //~ ERROR missing documentation for an associated type
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl AssociatedTrait for Associated {
|
||||
#![deny(dyn_drop)]
|
||||
|
||||
fn denied_from_inner(_x: Box<dyn Drop>) {} //~ ERROR types that do not implement `Drop`
|
||||
|
||||
#[deny(enum_intrinsics_non_enums)]
|
||||
fn assoc_fn() { discriminant::<i32>(&123); } //~ ERROR the return value of
|
||||
|
||||
#[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; //~ ERROR literal out of range
|
||||
type AssocType = i32;
|
||||
}
|
||||
|
||||
|
||||
// There aren't any late lints that can apply to a field that I can find.
|
||||
// non_snake_case doesn't work on fields
|
||||
// struct StructFields {
|
||||
// #[deny()]f1: i32,
|
||||
// }
|
||||
// struct StructTuple(#[deny()]i32);
|
||||
|
||||
pub enum Enum {
|
||||
#[deny(missing_docs)]
|
||||
Variant1, //~ ERROR missing documentation for a variant
|
||||
}
|
||||
|
||||
mod clashing_extern {
|
||||
extern "C" {
|
||||
fn clashing1();
|
||||
fn clashing2();
|
||||
}
|
||||
}
|
||||
extern "C" {
|
||||
#![deny(clashing_extern_declarations)]
|
||||
fn clashing1(_: i32); //~ ERROR `clashing1` redeclared with a different signature
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[deny(clashing_extern_declarations)]
|
||||
fn clashing2(_: i32); //~ ERROR `clashing2` redeclared with a different signature
|
||||
}
|
||||
|
||||
fn function(#[deny(non_snake_case)] PARAM: i32) {} //~ ERROR variable `PARAM` should have a snake case name
|
||||
// There aren't any late lints that can apply to generics that I can find.
|
||||
// fn generics<#[deny()]T>() {}
|
||||
|
||||
|
||||
// ################## Statements
|
||||
fn statements() {
|
||||
#[deny(enum_intrinsics_non_enums)]
|
||||
let _ = discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
}
|
||||
|
||||
|
||||
// ################## Expressions
|
||||
fn expressions() {
|
||||
let closure = |#[deny(non_snake_case)] PARAM: i32| {}; //~ ERROR variable `PARAM` should have a snake case name
|
||||
|
||||
struct Match{f1: i32}
|
||||
// I can't find any late lints for patterns.
|
||||
// let f = Match{#[deny()]f1: 123};
|
||||
|
||||
let f = Match{f1: 123};
|
||||
match f {
|
||||
#![deny(enum_intrinsics_non_enums)]
|
||||
Match{f1} => {
|
||||
discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
}
|
||||
}
|
||||
match f {
|
||||
#[deny(enum_intrinsics_non_enums)]
|
||||
Match{f1} => {
|
||||
discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
}
|
||||
}
|
||||
|
||||
// Statement Block
|
||||
{
|
||||
#![deny(enum_intrinsics_non_enums)]
|
||||
discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
}
|
||||
let block_tail = {
|
||||
#[deny(enum_intrinsics_non_enums)]
|
||||
discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
};
|
||||
|
||||
// Before expression as a statement.
|
||||
#[deny(enum_intrinsics_non_enums)]
|
||||
discriminant::<i32>(&123); //~ ERROR the return value of
|
||||
|
||||
[#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; //~ ERROR the return value of
|
||||
(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); //~ ERROR the return value of
|
||||
fn call(p: Discriminant<i32>) {}
|
||||
call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); //~ ERROR the return value of
|
||||
struct TupleStruct(Discriminant<i32>);
|
||||
TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); //~ ERROR the return value of
|
||||
}
|
||||
|
||||
|
||||
// ################## Patterns
|
||||
fn patterns() {
|
||||
// There aren't any late lints that I can find that apply to pattern fields.
|
||||
//
|
||||
// struct PatField{f1: i32, f2: i32};
|
||||
// let f = PatField{f1: 1, f2: 2};
|
||||
// let PatField{#[deny()]f1, #[deny()]..} = f;
|
||||
}
|
||||
|
||||
fn main() {}
|
428
src/test/ui/lint/lint-attr-everywhere-late.stderr
Normal file
428
src/test/ui/lint/lint-attr-everywhere-late.stderr
Normal file
|
@ -0,0 +1,428 @@
|
|||
error: missing documentation for a type alias
|
||||
--> $DIR/lint-attr-everywhere-late.rs:35:1
|
||||
|
|
||||
LL | pub type MissingDocType = i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:34:8
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a struct
|
||||
--> $DIR/lint-attr-everywhere-late.rs:43:1
|
||||
|
|
||||
LL | pub struct ItemOuter;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:42:8
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a module
|
||||
--> $DIR/lint-attr-everywhere-late.rs:45:1
|
||||
|
|
||||
LL | pub mod module_inner {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:46:13
|
||||
|
|
||||
LL | #![deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a function
|
||||
--> $DIR/lint-attr-everywhere-late.rs:47:5
|
||||
|
|
||||
LL | pub fn missing_inner() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated function
|
||||
--> $DIR/lint-attr-everywhere-late.rs:54:5
|
||||
|
|
||||
LL | pub fn inherent_denied_from_inner() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:52:13
|
||||
|
|
||||
LL | #![deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated function
|
||||
--> $DIR/lint-attr-everywhere-late.rs:59:5
|
||||
|
|
||||
LL | pub fn inherent_fn() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:58:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated constant
|
||||
--> $DIR/lint-attr-everywhere-late.rs:62:5
|
||||
|
|
||||
LL | pub const INHERENT_CONST: i32 = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:61:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a trait
|
||||
--> $DIR/lint-attr-everywhere-late.rs:65:1
|
||||
|
|
||||
LL | pub trait TraitInner {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:66:13
|
||||
|
|
||||
LL | #![deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a trait
|
||||
--> $DIR/lint-attr-everywhere-late.rs:69:1
|
||||
|
|
||||
LL | pub trait AssociatedTraitInner {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:70:13
|
||||
|
|
||||
LL | #![deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated function
|
||||
--> $DIR/lint-attr-everywhere-late.rs:72:5
|
||||
|
|
||||
LL | fn denied_from_inner() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated function
|
||||
--> $DIR/lint-attr-everywhere-late.rs:79:5
|
||||
|
|
||||
LL | fn assoc_fn() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:78:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated constant
|
||||
--> $DIR/lint-attr-everywhere-late.rs:82:5
|
||||
|
|
||||
LL | const ASSOC_CONST: u8 = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:81:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for an associated type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:85:5
|
||||
|
|
||||
LL | type AssocType;
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:84:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: missing documentation for a variant
|
||||
--> $DIR/lint-attr-everywhere-late.rs:112:5
|
||||
|
|
||||
LL | Variant1,
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:111:12
|
||||
|
|
||||
LL | #[deny(missing_docs)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: `clashing1` redeclared with a different signature
|
||||
--> $DIR/lint-attr-everywhere-late.rs:123:5
|
||||
|
|
||||
LL | fn clashing1();
|
||||
| --------------- `clashing1` previously declared here
|
||||
...
|
||||
LL | fn clashing1(_: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:122:13
|
||||
|
|
||||
LL | #![deny(clashing_extern_declarations)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: expected `unsafe extern "C" fn()`
|
||||
found `unsafe extern "C" fn(i32)`
|
||||
|
||||
error: `clashing2` redeclared with a different signature
|
||||
--> $DIR/lint-attr-everywhere-late.rs:128:5
|
||||
|
|
||||
LL | fn clashing2();
|
||||
| --------------- `clashing2` previously declared here
|
||||
...
|
||||
LL | fn clashing2(_: i32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:127:12
|
||||
|
|
||||
LL | #[deny(clashing_extern_declarations)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: expected `unsafe extern "C" fn()`
|
||||
found `unsafe extern "C" fn(i32)`
|
||||
|
||||
error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
|
||||
--> $DIR/lint-attr-everywhere-late.rs:93:38
|
||||
|
|
||||
LL | fn denied_from_inner(_x: Box<dyn Drop>) {}
|
||||
| ^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:91:13
|
||||
|
|
||||
LL | #![deny(dyn_drop)]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:96:21
|
||||
|
|
||||
LL | fn assoc_fn() { discriminant::<i32>(&123); }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:95:12
|
||||
|
|
||||
LL | #[deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:96:41
|
||||
|
|
||||
LL | fn assoc_fn() { discriminant::<i32>(&123); }
|
||||
| ^^^^
|
||||
|
||||
error: literal out of range for `u8`
|
||||
--> $DIR/lint-attr-everywhere-late.rs:98:59
|
||||
|
|
||||
LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
|
||||
| ^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:98:12
|
||||
|
|
||||
LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= note: the literal `1000` does not fit into the type `u8` whose range is `0..=255`
|
||||
|
||||
error: variable `PARAM` should have a snake case name
|
||||
--> $DIR/lint-attr-everywhere-late.rs:131:37
|
||||
|
|
||||
LL | fn function(#[deny(non_snake_case)] PARAM: i32) {}
|
||||
| ^^^^^ help: convert the identifier to snake case: `param`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:131:20
|
||||
|
|
||||
LL | fn function(#[deny(non_snake_case)] PARAM: i32) {}
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:139:13
|
||||
|
|
||||
LL | let _ = discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:138:12
|
||||
|
|
||||
LL | #[deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:139:33
|
||||
|
|
||||
LL | let _ = discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: variable `PARAM` should have a snake case name
|
||||
--> $DIR/lint-attr-everywhere-late.rs:145:44
|
||||
|
|
||||
LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {};
|
||||
| ^^^^^ help: convert the identifier to snake case: `param`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:145:27
|
||||
|
|
||||
LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {};
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:155:13
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:153:17
|
||||
|
|
||||
LL | #![deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:155:33
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:161:13
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:159:16
|
||||
|
|
||||
LL | #[deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:161:33
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:168:9
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:167:17
|
||||
|
|
||||
LL | #![deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:168:29
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:172:9
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:171:16
|
||||
|
|
||||
LL | #[deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:172:29
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:177:5
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:176:12
|
||||
|
|
||||
LL | #[deny(enum_intrinsics_non_enums)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:177:25
|
||||
|
|
||||
LL | discriminant::<i32>(&123);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:179:41
|
||||
|
|
||||
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:179:13
|
||||
|
|
||||
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:179:61
|
||||
|
|
||||
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:180:41
|
||||
|
|
||||
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:180:13
|
||||
|
|
||||
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:180:61
|
||||
|
|
||||
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:182:45
|
||||
|
|
||||
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:182:17
|
||||
|
|
||||
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:182:65
|
||||
|
|
||||
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-attr-everywhere-late.rs:184:52
|
||||
|
|
||||
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attr-everywhere-late.rs:184:24
|
||||
|
|
||||
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
|
||||
--> $DIR/lint-attr-everywhere-late.rs:184:72
|
||||
|
|
||||
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 31 previous errors
|
||||
|
|
@ -122,4 +122,10 @@ fn main() {
|
|||
Some(res) => res,
|
||||
None => 0,
|
||||
};
|
||||
|
||||
struct PatternField {
|
||||
foo: i32,
|
||||
}
|
||||
let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect
|
||||
let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
|
||||
}
|
||||
|
|
|
@ -105,6 +105,18 @@ error: `#[must_use]` has no effect when applied to an match arm
|
|||
LL | #[must_use]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a struct field
|
||||
--> $DIR/unused_attributes-must_use.rs:129:28
|
||||
|
|
||||
LL | let s = PatternField { #[must_use] foo: 123 };
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to a pattern field
|
||||
--> $DIR/unused_attributes-must_use.rs:130:24
|
||||
|
|
||||
LL | let PatternField { #[must_use] foo } = s;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: `#[must_use]` has no effect when applied to an associated const
|
||||
--> $DIR/unused_attributes-must_use.rs:68:5
|
||||
|
|
||||
|
@ -171,5 +183,5 @@ error: unused return value of `Use::get_four` that must be used
|
|||
LL | ().get_four();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
|
|||
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
|
||||
use clippy_utils::sugg::has_enclosing_paren;
|
||||
use clippy_utils::ty::{expr_sig, peel_mid_ty_refs, ty_sig, variant_of_res};
|
||||
use clippy_utils::{get_parent_expr, is_lint_allowed, path_to_local, walk_to_expr_usage};
|
||||
use clippy_utils::{get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage};
|
||||
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::Applicability;
|
||||
|
@ -699,6 +699,19 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
|
|||
Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
|
||||
},
|
||||
|
||||
Node::ExprField(field) if field.span.ctxt() == ctxt => match get_parent_expr_for_hir(cx, field.hir_id) {
|
||||
Some(Expr {
|
||||
hir_id,
|
||||
kind: ExprKind::Struct(path, ..),
|
||||
..
|
||||
}) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
|
||||
.and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
|
||||
.map(|field_def| {
|
||||
ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did), precedence).position_for_arg()
|
||||
}),
|
||||
_ => None,
|
||||
},
|
||||
|
||||
Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind {
|
||||
ExprKind::Ret(_) => {
|
||||
let owner_id = cx.tcx.hir().body_owner(cx.enclosing_body.unwrap());
|
||||
|
@ -788,17 +801,6 @@ fn walk_parents<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> (Position, &
|
|||
}
|
||||
})
|
||||
},
|
||||
ExprKind::Struct(path, fields, _) => {
|
||||
let variant = variant_of_res(cx, cx.qpath_res(path, parent.hir_id));
|
||||
fields
|
||||
.iter()
|
||||
.find(|f| f.expr.hir_id == child_id)
|
||||
.zip(variant)
|
||||
.and_then(|(field, variant)| variant.fields.iter().find(|f| f.name == field.ident.name))
|
||||
.map(|field| {
|
||||
ty_auto_deref_stability(cx, cx.tcx.type_of(field.did), precedence).position_for_arg()
|
||||
})
|
||||
},
|
||||
ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
|
||||
ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
|
||||
ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
|
||||
|
|
Loading…
Add table
Reference in a new issue