diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index dc54c55341e9..40a890a0cfde 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -437,7 +437,7 @@ pub trait Visitor<'v>: Sized { walk_label(self, label) } fn visit_infer(&mut self, inf: &'v InferArg) { - self.visit_id(inf.hir_id); + walk_inf(self, inf); } fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) { match generic_arg { @@ -447,11 +447,6 @@ pub trait Visitor<'v>: Sized { GenericArg::Infer(inf) => self.visit_infer(inf), } } - /* - fn tcx(&self) -> Option<&TyCtxt<'tcx>> { - None - } - */ fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { walk_lifetime(self, lifetime) } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index e504662bb5ea..052efa851f7c 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -244,6 +244,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas hir_visit::walk_ty(self, t); } + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + lint_callback!(self, check_infer, inf); + hir_visit::walk_inf(self, inf); + } + fn visit_name(&mut self, sp: Span, name: Symbol) { lint_callback!(self, check_name, sp, name); } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index bbe17dcf4b73..2d047ac7a081 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -33,6 +33,7 @@ macro_rules! late_lint_methods { fn check_expr(a: &$hir hir::Expr<$hir>); fn check_expr_post(a: &$hir hir::Expr<$hir>); fn check_ty(a: &$hir hir::Ty<$hir>); + fn check_infer(a: &$hir hir::InferArg); fn check_generic_arg(a: &$hir hir::GenericArg<$hir>); fn check_generic_param(a: &$hir hir::GenericParam<$hir>); fn check_generics(a: &$hir hir::Generics<$hir>); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c1f2b767e78d..6b74724a57c7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -272,11 +272,11 @@ impl<'hir> Map<'hir> { GenericParamKind::Type { .. } => DefKind::TyParam, GenericParamKind::Const { .. } => DefKind::ConstParam, }, - Node::Infer(_) => todo!(), Node::Crate(_) => DefKind::Mod, Node::Stmt(_) | Node::PathSegment(_) | Node::Ty(_) + | Node::Infer(_) | Node::TraitRef(_) | Node::Pat(_) | Node::Binding(_) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0395082fa651..0908b6a1763d 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -133,11 +133,6 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - query generic_arg_for_infer_arg(key: DefId) -> hir::GenericArg<'tcx> { - desc { |tcx| "computes concrete type for inference, `{}`", tcx.def_path_str(key) } - storage(ArenaCacheSelector<'tcx>) - } - /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the /// predicates (where-clauses) that must be proven true in order /// to reference it. This is almost always the "predicates query" diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index f4bdaffe3f73..e77bda7d4ab0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1191,16 +1191,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_generic_arg(&mut self, generic_arg: &'tcx hir::GenericArg<'tcx>) { match generic_arg { hir::GenericArg::Type(t) => self.visit_ty(t), - hir::GenericArg::Infer(inf) => { - self.span = inf.span; - let parent_hir_id = self.tcx.hir().get_parent_node(inf.hir_id); - if let Some(typeck_results) = self.maybe_typeck_results { - let node_substs = typeck_results.node_substs(parent_hir_id); - for ty in node_substs.types() { - self.visit(ty); - } - } - } + hir::GenericArg::Infer(inf) => self.visit_infer(inf), hir::GenericArg::Lifetime(_) | hir::GenericArg::Const(_) => {} } } @@ -1224,6 +1215,23 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { intravisit::walk_ty(self, hir_ty); } + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + self.span = inf.span; + if let Some(typeck_results) = self.maybe_typeck_results { + if let Some(ty) = typeck_results.node_type_opt(inf.hir_id) { + if self.visit(ty).is_break() { + return; + } + } + } else { + // FIXME see above note for same issue. + if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() { + return; + } + } + intravisit::walk_inf(self, inf); + } + fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { self.span = trait_ref.path.span; if self.maybe_typeck_results.is_none() { diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index a227d2f2337e..dd15d2d65b99 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -18,23 +18,6 @@ use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; use rustc_span::{symbol::kw, MultiSpan, Span}; use smallvec::SmallVec; -/* -pub fn generic_arg_for_infer_arg<'tcx>(tcx: TyCtxt<'tcx>, did: LocalDefId) -> GenericArg<'tcx> { - todo!() - let hir_id = tcx.hir().local_def_id_to_hir_id(did); - let arg = match tcx.hir().get(hir_id) { - hir::Node::GenericParam(hir::GenericParam { - kind: hir::GenericParamKind::Const { ty: _, default: _ }, - .. - }) => todo!(), - _ => bug!("Expected GenericParam for generic_arg_for_infer_arg"), - }; - - assert!(!matches!(arg, GenericArg::Infer(_))); - arg -} -*/ - impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was /// expected. diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index d80eb26f6c21..58ad086f2259 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -479,6 +479,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param.def_id, Some(arg.id()), arg.span(), + None, |_, _| { // Default generic parameters may not be marked // with stability attributes, i.e. when the diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 3a88fc5587ad..310517339cd6 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -581,6 +581,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub fn node_ty_opt(&self, id: hir::HirId) -> Option> { + match self.typeck_results.borrow().node_types().get(id) { + Some(&t) => Some(t), + None if self.is_tainted_by_errors() => Some(self.tcx.ty_error()), + None => None, + } + } + /// Registers an obligation for checking later, during regionck, that `arg` is well-formed. pub fn register_wf_obligation( &self, diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 935bcc9f32e2..e6eac16667d4 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -331,6 +331,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { let ty = self.resolve(ty, &hir_ty.span); self.write_ty_to_typeck_results(hir_ty.hir_id, ty); } + + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + intravisit::walk_inf(self, inf); + // Ignore cases where the inference is a const. + if let Some(ty) = self.fcx.node_ty_opt(inf.hir_id) { + let ty = self.resolve(ty, &inf.span); + self.write_ty_to_typeck_results(inf.hir_id, ty); + } + } } impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0b3fe82605c1..997fdcefe037 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -133,6 +133,7 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector { match generic_arg { hir::GenericArg::Infer(inf) => { self.0.push(inf.span); + intravisit::walk_inf(self, inf); } hir::GenericArg::Type(t) => self.visit_ty(t), _ => {} diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index 1b6e27fa169a..85db42e9c13a 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -273,6 +273,17 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) +error: type `priv_parent_substs::Priv` is private + --> $DIR/associated-item-privacy-trait.rs:117:30 + | +LL | let _: >::AssocTy; + | ^ private type +... +LL | priv_parent_substs::mac!(); + | --------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:119:17 | @@ -317,5 +328,5 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 29 previous errors +error: aborting due to 30 previous errors diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 9a040ca572af..ad4898d1ccbb 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -5,7 +5,7 @@ use std::collections::BTreeMap; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; -use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, walk_inf, NestedVisitorMap, Visitor}; use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -295,6 +295,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'a, 'tcx> { walk_ty(self, t); } + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + if let Some(target) = ImplicitHasherType::new(self.cx, &inf.to_ty()) { + self.found.push(target); + } + + walk_inf(self, inf); + } + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index d8c4b67520d1..b438d680d2cb 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint; use rustc_hir as hir; -use rustc_hir::intravisit::{walk_ty, NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor}; use rustc_hir::{GenericParamKind, TyKind}; use rustc_lint::LateContext; use rustc_middle::hir::map::Map; @@ -39,6 +39,11 @@ struct TypeComplexityVisitor { impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { type Map = Map<'tcx>; + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + self.score += 1; + walk_inf(self, inf); + } + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { let (add_score, sub_nest) = match ty.kind { // _, &x and *x have only small overhead; don't mess with nesting level diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 71117e967e31..c8cdf1a5d2c9 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -8,8 +8,9 @@ use rustc_hir::{ self as hir, def::{CtorOf, DefKind, Res}, def_id::LocalDefId, - intravisit::{walk_ty, NestedVisitorMap, Visitor}, - Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Path, QPath, TyKind, + intravisit::{walk_ty, walk_inf, NestedVisitorMap, Visitor}, + Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Node, Path, PathSegment, + QPath, TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::map::Map; @@ -263,6 +264,11 @@ struct SkipTyCollector { impl<'tcx> Visitor<'tcx> for SkipTyCollector { type Map = Map<'tcx>; + fn visit_infer(&mut self, inf: &hir::InferArg) { + self.types_to_skip.push(inf.hir_id); + + walk_inf(self, inf) + } fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) { self.types_to_skip.push(hir_ty.hir_id); @@ -274,6 +280,52 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector { } } +<<<<<<< HEAD +======= +struct LintTyCollector<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + self_ty: Ty<'tcx>, + types_to_lint: Vec, + types_to_skip: Vec, +} + +impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> { + type Map = Map<'tcx>; + + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) { + if_chain! { + if let Some(ty) = self.cx.typeck_results().node_type_opt(hir_ty.hir_id); + if should_lint_ty(hir_ty, ty, self.self_ty); + then { + self.types_to_lint.push(hir_ty.hir_id); + } else { + self.types_to_skip.push(hir_ty.hir_id); + } + } + + walk_ty(self, hir_ty); + } + + fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + if_chain! { + if let Some(ty) = self.cx.typeck_results().node_type_opt(inf.hir_id); + if should_lint_ty(&inf.to_ty(), ty, self.self_ty); + then { + self.types_to_lint.push(inf.hir_id); + } else { + self.types_to_skip.push(inf.hir_id); + } + } + + walk_inf(self, inf) + } + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } +} + +>>>>>>> Add inferred args to typeck fn span_lint(cx: &LateContext<'_>, span: Span) { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 63737955f09b..e636038b6e1a 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -288,6 +288,8 @@ impl HirEqInterExpr<'_, '_, '_> { (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), + (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => + self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()), _ => false, } } @@ -888,10 +890,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_tykind(&ty.kind); } - pub fn hash_infer(&mut self) { - "_".hash(&mut self.s); - } - pub fn hash_tykind(&mut self, ty: &TyKind<'_>) { match ty { TyKind::Slice(ty) => { @@ -957,7 +955,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Type(ref ty) => self.hash_ty(ty), GenericArg::Const(ref ca) => self.hash_body(ca.value.body), - GenericArg::Infer(ref _inf) => self.hash_infer(), + GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), } } } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 523d55219ab6..e914dc1c222f 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -180,7 +180,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } // FIXME: Per https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/infer/at/struct.At.html#method.normalize -// this function can be removed once the `normalizie` method does not panic when normalization does +// this function can be removed once the `normalize` method does not panic when normalization does // not succeed /// Checks if `Ty` is normalizable. This function is useful /// to avoid crashes on `layout_of`. diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr index df0598a58cd3..54ab04f8c5d3 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr @@ -46,13 +46,13 @@ error: transmute from a pointer type (`*const i32`) to a reference type (`&issue --> $DIR/transmute_ptr_to_ref.rs:32:32 | LL | let _: &Foo = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo)` error: transmute from a pointer type (`*const i32`) to a reference type (`&issue1231::Foo<&u8>`) --> $DIR/transmute_ptr_to_ref.rs:34:33 | LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const Foo<&_>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(raw as *const issue1231::Foo<&u8>)` error: transmute from a pointer type (`*const i32`) to a reference type (`&u8`) --> $DIR/transmute_ptr_to_ref.rs:38:14