diff options
Diffstat (limited to 'compiler/rustc_lint/src')
| -rw-r--r-- | compiler/rustc_lint/src/builtin.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/context.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/dangling.rs | 152 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/default_could_be_derived.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/early.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/foreign_modules.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lifetime_syntax.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/lints.rs | 79 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/map_unit_fn.rs | 103 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/nonstandard_style.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/pass_by_value.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/types/literal.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/unused.rs | 8 | 
13 files changed, 273 insertions, 133 deletions
| diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 152971c4ed6..c893b723375 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,14 +21,14 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; -use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; -use rustc_hir::{Body, FnDecl, PatKind, PredicateOrigin}; +use rustc_hir::{Body, FnDecl, PatKind, PredicateOrigin, find_attr}; use rustc_middle::bug; use rustc_middle::lint::LevelAndSource; use rustc_middle::ty::layout::LayoutOf; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index b694d3dd49b..11181d10af5 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -756,22 +756,22 @@ impl<'tcx> LateContext<'tcx> { } fn print_region(&mut self, _region: ty::Region<'_>) -> Result<(), PrintError> { - Ok(()) + unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } fn print_type(&mut self, _ty: Ty<'tcx>) -> Result<(), PrintError> { - Ok(()) + unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } fn print_dyn_existential( &mut self, _predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Result<(), PrintError> { - Ok(()) + unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } fn print_const(&mut self, _ct: ty::Const<'tcx>) -> Result<(), PrintError> { - Ok(()) + unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { @@ -784,10 +784,10 @@ impl<'tcx> LateContext<'tcx> { self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - if trait_ref.is_none() { - if let ty::Adt(def, args) = self_ty.kind() { - return self.print_def_path(def.did(), args); - } + if trait_ref.is_none() + && let ty::Adt(def, args) = self_ty.kind() + { + return self.print_def_path(def.did(), args); } // This shouldn't ever be needed, but just in case: @@ -803,7 +803,6 @@ impl<'tcx> LateContext<'tcx> { fn path_append_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { @@ -854,9 +853,9 @@ impl<'tcx> LateContext<'tcx> { } } - let mut printer = AbsolutePathPrinter { tcx: self.tcx, path: vec![] }; - printer.print_def_path(def_id, &[]).unwrap(); - printer.path + let mut p = AbsolutePathPrinter { tcx: self.tcx, path: vec![] }; + p.print_def_path(def_id, &[]).unwrap(); + p.path } /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`. diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index c737919db9c..af4457f4314 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -1,13 +1,14 @@ use rustc_ast::visit::{visit_opt, walk_list}; -use rustc_attr_data_structures::{AttributeKind, find_attr}; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem}; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, LangItem, TyKind, find_attr}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::{Span, sym}; -use crate::lints::DanglingPointersFromTemporaries; +use crate::lints::{DanglingPointersFromLocals, DanglingPointersFromTemporaries}; use crate::{LateContext, LateLintPass}; declare_lint! { @@ -42,6 +43,36 @@ declare_lint! { "detects getting a pointer from a temporary" } +declare_lint! { + /// The `dangling_pointers_from_locals` lint detects getting a pointer to data + /// of a local that will be dropped at the end of the function. + /// + /// ### Example + /// + /// ```rust + /// fn f() -> *const u8 { + /// let x = 0; + /// &x // returns a dangling ptr to `x` + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Returning a pointer from a local value will not prolong its lifetime, + /// which means that the value can be dropped and the allocation freed + /// while the pointer still exists, making the pointer dangling. + /// This is not an error (as far as the type system is concerned) + /// but probably is not what the user intended either. + /// + /// If you need stronger guarantees, consider using references instead, + /// as they are statically verified by the borrow-checker to never dangle. + pub DANGLING_POINTERS_FROM_LOCALS, + Warn, + "detects returning a pointer from a local variable" +} + /// FIXME: false negatives (i.e. the lint is not emitted when it should be) /// 1. Ways to get a temporary that are not recognized: /// - `owning_temporary.field` @@ -53,20 +84,123 @@ declare_lint! { #[derive(Clone, Copy, Default)] pub(crate) struct DanglingPointers; -impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES]); +impl_lint_pass!(DanglingPointers => [DANGLING_POINTERS_FROM_TEMPORARIES, DANGLING_POINTERS_FROM_LOCALS]); // This skips over const blocks, but they cannot use or return a dangling pointer anyways. impl<'tcx> LateLintPass<'tcx> for DanglingPointers { fn check_fn( &mut self, cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl<'tcx>, + fn_kind: FnKind<'tcx>, + fn_decl: &'tcx FnDecl<'tcx>, body: &'tcx Body<'tcx>, _: Span, - _: LocalDefId, + def_id: LocalDefId, ) { - DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body) + DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body); + + if let FnRetTy::Return(ret_ty) = &fn_decl.output + && let TyKind::Ptr(_) = ret_ty.kind + { + // get the return type of the function or closure + let ty = match cx.tcx.type_of(def_id).instantiate_identity().kind() { + ty::FnDef(..) => cx.tcx.fn_sig(def_id).instantiate_identity(), + ty::Closure(_, args) => args.as_closure().sig(), + _ => return, + }; + let ty = ty.output(); + + // this type is only used for layout computation and pretty-printing, neither of them rely on regions + let ty = cx.tcx.instantiate_bound_regions_with_erased(ty); + + // verify that we have a pointer type + let inner_ty = match ty.kind() { + ty::RawPtr(inner_ty, _) => *inner_ty, + _ => return, + }; + + if cx + .tcx + .layout_of(cx.typing_env().as_query_input(inner_ty)) + .is_ok_and(|layout| !layout.is_1zst()) + { + let dcx = &DanglingPointerLocalContext { + body: def_id, + fn_ret: ty, + fn_ret_span: ret_ty.span, + fn_ret_inner: inner_ty, + fn_kind: match fn_kind { + FnKind::ItemFn(..) => "function", + FnKind::Method(..) => "method", + FnKind::Closure => "closure", + }, + }; + + // look for `return`s + DanglingPointerReturnSearcher { cx, dcx }.visit_body(body); + + // analyze implicit return expression + if let ExprKind::Block(block, None) = &body.value.kind + && let innermost_block = block.innermost_block() + && let Some(expr) = innermost_block.expr + { + lint_addr_of_local(cx, dcx, expr); + } + } + } + } +} + +struct DanglingPointerLocalContext<'tcx> { + body: LocalDefId, + fn_ret: Ty<'tcx>, + fn_ret_span: Span, + fn_ret_inner: Ty<'tcx>, + fn_kind: &'static str, +} + +struct DanglingPointerReturnSearcher<'lcx, 'tcx> { + cx: &'lcx LateContext<'tcx>, + dcx: &'lcx DanglingPointerLocalContext<'tcx>, +} + +impl<'tcx> Visitor<'tcx> for DanglingPointerReturnSearcher<'_, 'tcx> { + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> Self::Result { + if let ExprKind::Ret(Some(expr)) = expr.kind { + lint_addr_of_local(self.cx, self.dcx, expr); + } + walk_expr(self, expr) + } +} + +/// Look for `&<path_to_local_in_same_body>` pattern and emit lint for it +fn lint_addr_of_local<'a>( + cx: &LateContext<'a>, + dcx: &DanglingPointerLocalContext<'a>, + expr: &'a Expr<'a>, +) { + // peel casts as they do not interest us here, we want the inner expression. + let (inner, _) = super::utils::peel_casts(cx, expr); + + if let ExprKind::AddrOf(_, _, inner_of) = inner.kind + && let ExprKind::Path(ref qpath) = inner_of.peel_blocks().kind + && let Res::Local(from) = cx.qpath_res(qpath, inner_of.hir_id) + && cx.tcx.hir_enclosing_body_owner(from) == dcx.body + { + cx.tcx.emit_node_span_lint( + DANGLING_POINTERS_FROM_LOCALS, + expr.hir_id, + expr.span, + DanglingPointersFromLocals { + ret_ty: dcx.fn_ret, + ret_ty_span: dcx.fn_ret_span, + fn_kind: dcx.fn_kind, + local_var: cx.tcx.hir_span(from), + local_var_name: cx.tcx.hir_ident(from), + local_var_ty: dcx.fn_ret_inner, + created_at: (expr.hir_id != inner.hir_id).then_some(inner.span), + }, + ); } } diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index b5fc083a095..1d92cfbc039 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -1,7 +1,8 @@ -use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::find_attr; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; @@ -61,8 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { // Look for manual implementations of `Default`. let Some(default_def_id) = cx.tcx.get_diagnostic_item(sym::Default) else { return }; let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return }; - let assoc = cx.tcx.associated_item(impl_item.owner_id); - let parent = assoc.container_id(cx.tcx); + let parent = cx.tcx.parent(impl_item.owner_id.to_def_id()); if find_attr!(cx.tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) { // We don't care about what `#[derive(Default)]` produces in this lint. return; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 48e3bbb79fa..58205087def 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -4,7 +4,6 @@ //! resolution, just before AST lowering. These lints are for purely //! syntactical lints. -use rustc_ast::ptr::P; use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -297,7 +296,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) { } } -impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::Item>]) { +impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [Box<ast::Item>]) { fn id(self) -> ast::NodeId { self.0 } diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index d6c402d481f..759e6c927b8 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -1,9 +1,10 @@ use rustc_abi::FIRST_VARIANT; -use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; +use rustc_hir::find_attr; use rustc_middle::query::Providers; use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt}; use rustc_session::declare_lint; diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 2a5a34cdc6e..464f4fc34b9 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -434,7 +434,7 @@ fn emit_mismatch_diagnostic<'tcx>( lints::MismatchedLifetimeSyntaxesSuggestion::Mixed { implicit_suggestions, explicit_anonymous_suggestions, - tool_only: false, + optional_alternative: false, } }); @@ -455,7 +455,10 @@ fn emit_mismatch_diagnostic<'tcx>( let implicit_suggestion = should_suggest_implicit.then(|| { let suggestions = make_implicit_suggestions(&suggest_change_to_implicit); - lints::MismatchedLifetimeSyntaxesSuggestion::Implicit { suggestions, tool_only: false } + lints::MismatchedLifetimeSyntaxesSuggestion::Implicit { + suggestions, + optional_alternative: false, + } }); tracing::debug!( @@ -508,7 +511,7 @@ fn build_mismatch_suggestion( lints::MismatchedLifetimeSyntaxesSuggestion::Explicit { lifetime_name, suggestions, - tool_only: false, + optional_alternative: false, } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index fd8d0f832aa..73e69a1791a 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -902,9 +902,8 @@ pub(crate) struct MappingToUnit { pub argument_label: Span, #[label(lint_map_label)] pub map_label: Span, - #[suggestion(style = "verbose", code = "{replace}", applicability = "maybe-incorrect")] + #[suggestion(style = "verbose", code = "for_each", applicability = "maybe-incorrect")] pub suggestion: Span, - pub replace: String, } // internal.rs @@ -1188,6 +1187,22 @@ pub(crate) struct DanglingPointersFromTemporaries<'tcx> { pub temporary_span: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_dangling_pointers_from_locals)] +#[note] +pub(crate) struct DanglingPointersFromLocals<'tcx> { + pub ret_ty: Ty<'tcx>, + #[label(lint_ret_ty)] + pub ret_ty_span: Span, + pub fn_kind: &'static str, + #[label(lint_local_var)] + pub local_var: Span, + pub local_var_name: Ident, + pub local_var_ty: Ty<'tcx>, + #[label(lint_created_at)] + pub created_at: Option<Span>, +} + // multiple_supertrait_upcastable.rs #[derive(LintDiagnostic)] #[diag(lint_multiple_supertrait_upcastable)] @@ -3276,7 +3291,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta diag.subdiagnostic(s); for mut s in suggestions { - s.make_tool_only(); + s.make_optional_alternative(); diag.subdiagnostic(s); } } @@ -3287,33 +3302,33 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta pub(crate) enum MismatchedLifetimeSyntaxesSuggestion { Implicit { suggestions: Vec<Span>, - tool_only: bool, + optional_alternative: bool, }, Mixed { implicit_suggestions: Vec<Span>, explicit_anonymous_suggestions: Vec<(Span, String)>, - tool_only: bool, + optional_alternative: bool, }, Explicit { lifetime_name: String, suggestions: Vec<(Span, String)>, - tool_only: bool, + optional_alternative: bool, }, } impl MismatchedLifetimeSyntaxesSuggestion { - fn make_tool_only(&mut self) { + fn make_optional_alternative(&mut self) { use MismatchedLifetimeSyntaxesSuggestion::*; - let tool_only = match self { - Implicit { tool_only, .. } | Mixed { tool_only, .. } | Explicit { tool_only, .. } => { - tool_only - } + let optional_alternative = match self { + Implicit { optional_alternative, .. } + | Mixed { optional_alternative, .. } + | Explicit { optional_alternative, .. } => optional_alternative, }; - *tool_only = true; + *optional_alternative = true; } } @@ -3321,22 +3336,40 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { use MismatchedLifetimeSyntaxesSuggestion::*; - let style = |tool_only| { - if tool_only { SuggestionStyle::CompletelyHidden } else { SuggestionStyle::ShowAlways } + let style = |optional_alternative| { + if optional_alternative { + SuggestionStyle::CompletelyHidden + } else { + SuggestionStyle::ShowAlways + } + }; + + let applicability = |optional_alternative| { + // `cargo fix` can't handle more than one fix for the same issue, + // so hide alternative suggestions from it by marking them as maybe-incorrect + if optional_alternative { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + } }; match self { - Implicit { suggestions, tool_only } => { + Implicit { suggestions, optional_alternative } => { let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); diag.multipart_suggestion_with_style( fluent::lint_mismatched_lifetime_syntaxes_suggestion_implicit, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } - Mixed { implicit_suggestions, explicit_anonymous_suggestions, tool_only } => { + Mixed { + implicit_suggestions, + explicit_anonymous_suggestions, + optional_alternative, + } => { let message = if implicit_suggestions.is_empty() { fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths } else { @@ -3352,12 +3385,12 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { diag.multipart_suggestion_with_style( message, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } - Explicit { lifetime_name, suggestions, tool_only } => { + Explicit { lifetime_name, suggestions, optional_alternative } => { diag.arg("lifetime_name", lifetime_name); let msg = diag.eagerly_translate( fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit, @@ -3366,8 +3399,8 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { diag.multipart_suggestion_with_style( msg, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } } diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 34210137bde..18a947dc1ee 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -1,6 +1,7 @@ -use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind}; -use rustc_middle::ty::{self, Ty}; +use rustc_hir::{Expr, ExprKind, Stmt, StmtKind}; +use rustc_middle::ty::{self}; use rustc_session::{declare_lint, declare_lint_pass}; +use rustc_span::sym; use crate::lints::MappingToUnit; use crate::{LateContext, LateLintPass, LintContext}; @@ -39,58 +40,43 @@ declare_lint_pass!(MapUnitFn => [MAP_UNIT_FN]); impl<'tcx> LateLintPass<'tcx> for MapUnitFn { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) { - if stmt.span.from_expansion() { + let StmtKind::Semi(expr) = stmt.kind else { return; - } - - if let StmtKind::Semi(expr) = stmt.kind - && let ExprKind::MethodCall(path, receiver, args, span) = expr.kind + }; + let ExprKind::MethodCall(path, receiver, [arg], span) = expr.kind else { + return; + }; + if path.ident.name != sym::map + || stmt.span.from_expansion() + || receiver.span.from_expansion() + || arg.span.from_expansion() + || !is_impl_slice(cx, receiver) + || !cx + .typeck_results() + .type_dependent_def_id(expr.hir_id) + .is_some_and(|id| cx.tcx.is_diagnostic_item(sym::IteratorMap, id)) { - if path.ident.name.as_str() == "map" { - if receiver.span.from_expansion() - || args.iter().any(|e| e.span.from_expansion()) - || !is_impl_slice(cx, receiver) - || !is_diagnostic_name(cx, expr.hir_id, "IteratorMap") - { - return; - } - let arg_ty = cx.typeck_results().expr_ty(&args[0]); - let default_span = args[0].span; - if let ty::FnDef(id, _) = arg_ty.kind() { - let fn_ty = cx.tcx.fn_sig(id).skip_binder(); - let ret_ty = fn_ty.output().skip_binder(); - if is_unit_type(ret_ty) { - cx.emit_span_lint( - MAP_UNIT_FN, - span, - MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span), - argument_label: args[0].span, - map_label: span, - suggestion: path.ident.span, - replace: "for_each".to_string(), - }, - ) - } - } else if let ty::Closure(id, subs) = arg_ty.kind() { - let cl_ty = subs.as_closure().sig(); - let ret_ty = cl_ty.output().skip_binder(); - if is_unit_type(ret_ty) { - cx.emit_span_lint( - MAP_UNIT_FN, - span, - MappingToUnit { - function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span), - argument_label: args[0].span, - map_label: span, - suggestion: path.ident.span, - replace: "for_each".to_string(), - }, - ) - } - } - } + return; } + let (id, sig) = match *cx.typeck_results().expr_ty(arg).kind() { + ty::Closure(id, subs) => (id, subs.as_closure().sig()), + ty::FnDef(id, _) => (id, cx.tcx.fn_sig(id).skip_binder()), + _ => return, + }; + let ret_ty = sig.output().skip_binder(); + if !(ret_ty.is_unit() || ret_ty.is_never()) { + return; + } + cx.emit_span_lint( + MAP_UNIT_FN, + span, + MappingToUnit { + function_label: cx.tcx.span_of_impl(id).unwrap_or(arg.span), + argument_label: arg.span, + map_label: span, + suggestion: path.ident.span, + }, + ); } } @@ -102,18 +88,3 @@ fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { } false } - -fn is_unit_type(ty: Ty<'_>) -> bool { - ty.is_unit() || ty.is_never() -} - -fn is_diagnostic_name(cx: &LateContext<'_>, id: HirId, name: &str) -> bool { - if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id) - && let Some(item) = cx.tcx.get_diagnostic_name(def_id) - { - if item.as_str() == name { - return true; - } - } - false -} diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 76e374deef6..7e5f43ba77f 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,11 +1,11 @@ use rustc_abi::ExternAbi; -use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::Applicability; +use rustc_hir::attrs::{AttributeKind, ReprAttr}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind}; +use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind, find_attr}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty; use rustc_session::config::CrateType; diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index a3cf3d568b1..4f65acd8001 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -1,6 +1,6 @@ -use rustc_attr_data_structures::{AttributeKind, find_attr}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::Res; -use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind}; +use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind, find_attr}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 2bac58ba23d..1febbff4bbf 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -1,11 +1,11 @@ use hir::{ExprKind, Node, is_range_literal}; use rustc_abi::{Integer, Size}; -use rustc_hir::HirId; +use rustc_hir::{HirId, attrs}; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::{bug, ty}; use rustc_span::Span; -use {rustc_ast as ast, rustc_attr_data_structures as attrs, rustc_hir as hir}; +use {rustc_ast as ast, rustc_hir as hir}; use crate::LateContext; use crate::context::LintContext; @@ -272,7 +272,7 @@ fn lint_int_literal<'tcx>( cx, hir_id, span, - attrs::IntType::SignedInt(ty::ast_int_ty(t)), + attrs::IntType::SignedInt(t), Integer::from_int_ty(cx, t).size(), repr_str, v, @@ -358,7 +358,7 @@ fn lint_uint_literal<'tcx>( cx, hir_id, span, - attrs::IntType::UnsignedInt(ty::ast_uint_ty(t)), + attrs::IntType::UnsignedInt(t), Integer::from_uint_ty(cx, t).size(), repr_str, lit_val, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 11df071f068..22d89d24612 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -2,12 +2,12 @@ use std::iter; use rustc_ast::util::{classify, parser}; use rustc_ast::{self as ast, ExprKind, FnRetTy, HasAttrs as _, StmtKind}; -use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{MultiSpan, pluralize}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, LangItem, find_attr}; use rustc_infer::traits::util::elaborate; use rustc_middle::ty::{self, Ty, adjustment}; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; @@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let mut op_warned = false; if let Some(must_use_op) = must_use_op { - let span = expr.span.find_oldest_ancestor_in_same_ctxt(); + let span = expr.span.find_ancestor_not_from_macro().unwrap_or(expr.span); cx.emit_span_lint( UNUSED_MUST_USE, expr.span, @@ -511,7 +511,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ); } MustUsePath::Def(span, def_id, reason) => { - let span = span.find_oldest_ancestor_in_same_ctxt(); + let span = span.find_ancestor_not_from_macro().unwrap_or(*span); cx.emit_span_lint( UNUSED_MUST_USE, span, | 
