Auto merge of #135272 - BoxyUwU:generic_arg_infer_reliability_2, r=compiler-errors
Forbid usage of `hir` `Infer` const/ty variants in ambiguous contexts
The feature `generic_arg_infer` allows providing `_` as an argument to const generics in order to infer them. This introduces a syntactic ambiguity as to whether generic arguments are type or const arguments. In order to get around this we introduced a fourth `GenericArg` variant, `Infer` used to represent `_` as an argument to generic parameters when we don't know if its a type or a const argument.
This made hir visitors that care about `TyKind::Infer` or `ConstArgKind::Infer` very error prone as checking for `TyKind::Infer`s in `visit_ty` would find *some* type infer arguments but not *all* of them as they would sometimes be lowered to `GenericArg::Infer` instead.
Additionally the `visit_infer` method would previously only visit `GenericArg::Infer` not *all* infers (e.g. `TyKind::Infer`), this made it very easy to override `visit_infer` and expect it to visit all infers when in reality it would only visit *some* infers.
---
This PR aims to fix those issues by making the `TyKind` and `ConstArgKind` types generic over whether the infer types/consts are represented by `Ty/ConstArgKind::Infer` or out of line (e.g. by a `GenericArg::Infer` or accessible by overiding `visit_infer`). We then make HIR Visitors convert all const args and types to the versions where infer vars are stored out of line and call `visit_infer` in cases where a `Ty`/`Const` would previously have had a `Ty/ConstArgKind::Infer` variant:
API Summary
```rust
enum AmbigArg {}
enum Ty/ConstArgKind<Unambig = ()> {
...
Infer(Unambig),
}
impl Ty/ConstArg {
fn try_as_ambig_ty/ct(self) -> Option<Ty/ConstArg<AmbigArg>>;
}
impl Ty/ConstArg<AmbigArg> {
fn as_unambig_ty/ct(self) -> Ty/ConstArg;
}
enum InferKind {
Ty(Ty),
Const(ConstArg),
Ambig(InferArg),
}
trait Visitor {
...
fn visit_ty/const_arg(&mut self, Ty/ConstArg<AmbigArg>) -> Self::Result;
fn visit_infer(&mut self, id: HirId, sp: Span, kind: InferKind) -> Self::Result;
}
// blanket impl'd, not meant to be overriden
trait VisitorExt {
fn visit_ty/const_arg_unambig(&mut self, Ty/ConstArg) -> Self::Result;
}
fn walk_unambig_ty/const_arg(&mut V, Ty/ConstArg) -> Self::Result;
fn walk_ty/const_arg(&mut V, Ty/ConstArg<AmbigArg>) -> Self::Result;
```
The end result is that `visit_infer` visits *all* infer args and is also the *only* way to visit an infer arg, `visit_ty` and `visit_const_arg` can now no longer encounter a `Ty/ConstArgKind::Infer`. Representing this in the type system means that it is now very difficult to mess things up, either accessing `TyKind::Infer` "just works" and you won't miss *some* type infers- or it doesn't work and you have to look at `visit_infer` or some `GenericArg::Infer` which forces you to think about the full complexity involved.
Unfortunately there is no lint right now about explicitly matching on uninhabited variants, I can't find the context for why this is the case 🤷♀️
I'm not convinced the framing of un/ambig ty/consts is necessarily the right one but I'm not sure what would be better. I somewhat like calling them full/partial types based on the fact that `Ty<Partial>`/`Ty<Full>` directly specifies how many of the type kinds are actually represented compared to `Ty<Ambig>` which which leaves that to the reader to figure out based on the logical consequences of it the type being in an ambiguous position.
---
tool changes have been modified in their own commits for easier reviewing by anyone getting cc'd from subtree changes. I also attempted to split out "bug fixes arising from the refactoring" into their own commit so they arent lumped in with a big general refactor commit
Fixes #112110
This commit is contained in:
commit
8231e8599e
119 changed files with 1056 additions and 669 deletions
|
|
@ -4,12 +4,12 @@ use clippy_utils::ty::expr_sig;
|
|||
use clippy_utils::{is_default_equivalent, path_def_id};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::intravisit::{Visitor, walk_ty};
|
||||
use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind};
|
||||
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
|
||||
use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -92,8 +92,13 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>)
|
|||
struct InferVisitor(bool);
|
||||
|
||||
impl Visitor<'_> for InferVisitor {
|
||||
fn visit_ty(&mut self, t: &Ty<'_>) {
|
||||
self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
|
||||
fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, _kind: InferKind<'_>) -> Self::Result {
|
||||
self.0 = true;
|
||||
self.visit_id(inf_id);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &Ty<'_, AmbigArg>) {
|
||||
self.0 |= matches!(t.kind, TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
|
||||
if !self.0 {
|
||||
walk_ty(self, t);
|
||||
}
|
||||
|
|
@ -104,7 +109,7 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||
match cx.tcx.parent_hir_node(expr.hir_id) {
|
||||
Node::LetStmt(LetStmt { ty: Some(ty), .. }) => {
|
||||
let mut v = InferVisitor::default();
|
||||
v.visit_ty(ty);
|
||||
v.visit_ty_unambig(ty);
|
||||
!v.0
|
||||
},
|
||||
Node::Expr(Expr {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_middle::ty::Ty;
|
|||
|
||||
pub fn check<'tcx>(cx: &LateContext<'tcx>, ty_into: Ty<'_>, cast_to_hir: &'tcx rustc_hir::Ty<'tcx>) {
|
||||
if let rustc_hir::TyKind::Ptr(rustc_hir::MutTy { ty, .. }) = cast_to_hir.kind
|
||||
&& matches!(ty.kind, rustc_hir::TyKind::Infer)
|
||||
&& matches!(ty.kind, rustc_hir::TyKind::Infer(()))
|
||||
{
|
||||
clippy_utils::diagnostics::span_lint_and_sugg(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_middle::ty;
|
|||
use super::AS_UNDERSCORE;
|
||||
|
||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ty: &'tcx Ty<'_>) {
|
||||
if matches!(ty.kind, TyKind::Infer) {
|
||||
if matches!(ty.kind, TyKind::Infer(())) {
|
||||
span_lint_and_then(cx, AS_UNDERSCORE, expr.span, "using `as _` conversion", |diag| {
|
||||
let ty_resolved = cx.typeck_results().expr_ty(expr);
|
||||
if let ty::Error(_) = ty_resolved.kind() {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub(super) fn check(
|
|||
return;
|
||||
};
|
||||
match cast_to_hir.kind {
|
||||
TyKind::Infer => {
|
||||
TyKind::Infer(()) => {
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span,
|
||||
"use `Into::into` instead",
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
|||
&& let Some(generic_args) = method_path.args
|
||||
&& let [GenericArg::Type(cast_to)] = generic_args.args
|
||||
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
|
||||
&& !is_hir_ty_cfg_dependant(cx, cast_to)
|
||||
&& !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty())
|
||||
{
|
||||
let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
|
||||
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
|
|||
{
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let turbofish = match &cast_to_hir_ty.kind {
|
||||
TyKind::Infer => String::new(),
|
||||
TyKind::Infer(()) => String::new(),
|
||||
TyKind::Ptr(mut_ty) => {
|
||||
if matches!(mut_ty.ty.kind, TyKind::Infer) {
|
||||
if matches!(mut_ty.ty.kind, TyKind::Infer(())) {
|
||||
String::new()
|
||||
} else {
|
||||
format!(
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ pub(super) fn check<'tcx>(
|
|||
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let turbofish = match &cast_to_hir_ty.kind {
|
||||
TyKind::Infer => String::new(),
|
||||
TyKind::Infer(()) => String::new(),
|
||||
TyKind::Ptr(mut_ty) => {
|
||||
if matches!(mut_ty.ty.kind, TyKind::Infer) {
|
||||
if matches!(mut_ty.ty.kind, TyKind::Infer(())) {
|
||||
String::new()
|
||||
} else {
|
||||
format!(
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
},
|
||||
// Ignore `p as *const _`
|
||||
TyKind::Infer => return false,
|
||||
TyKind::Infer(()) => return false,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>
|
|||
Mutability::Not => ("`0 as *const _` detected", "ptr::null"),
|
||||
};
|
||||
|
||||
let sugg = if let TyKind::Infer = mut_ty.ty.kind {
|
||||
let sugg = if let TyKind::Infer(()) = mut_ty.ty.kind {
|
||||
format!("{std_or_core}::{sugg_fn}()")
|
||||
} else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) {
|
||||
format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ use rustc_ast::util::parser::ExprPrecedence;
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{Visitor, walk_ty};
|
||||
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
|
||||
use rustc_hir::{
|
||||
self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat,
|
||||
PatKind, Path, QPath, TyKind, UnOp,
|
||||
self as hir, AmbigArg, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node,
|
||||
Pat, PatKind, Path, QPath, TyKind, UnOp,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
|
||||
|
|
@ -796,7 +796,7 @@ impl TyCoercionStability {
|
|||
if let Some(args) = path.args
|
||||
&& args.args.iter().any(|arg| match arg {
|
||||
hir::GenericArg::Infer(_) => true,
|
||||
hir::GenericArg::Type(ty) => ty_contains_infer(ty),
|
||||
hir::GenericArg::Type(ty) => ty_contains_infer(ty.as_unambig_ty()),
|
||||
_ => false,
|
||||
})
|
||||
{
|
||||
|
|
@ -815,7 +815,7 @@ impl TyCoercionStability {
|
|||
| TyKind::Path(_) => Self::Deref,
|
||||
TyKind::OpaqueDef(..)
|
||||
| TyKind::TraitAscription(..)
|
||||
| TyKind::Infer
|
||||
| TyKind::Infer(())
|
||||
| TyKind::Typeof(..)
|
||||
| TyKind::TraitObject(..)
|
||||
| TyKind::InferDelegation(..)
|
||||
|
|
@ -889,29 +889,23 @@ impl TyCoercionStability {
|
|||
fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
|
||||
struct V(bool);
|
||||
impl Visitor<'_> for V {
|
||||
fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
|
||||
if self.0
|
||||
|| matches!(
|
||||
ty.kind,
|
||||
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_)
|
||||
)
|
||||
{
|
||||
fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result {
|
||||
if let InferKind::Ty(_) | InferKind::Ambig(_) = kind {
|
||||
self.0 = true;
|
||||
}
|
||||
self.visit_id(inf_id);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
|
||||
if self.0 || matches!(ty.kind, TyKind::OpaqueDef(..) | TyKind::Typeof(_) | TyKind::Err(_)) {
|
||||
self.0 = true;
|
||||
} else {
|
||||
walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, arg: &hir::GenericArg<'_>) {
|
||||
if self.0 || matches!(arg, hir::GenericArg::Infer(_)) {
|
||||
self.0 = true;
|
||||
} else if let hir::GenericArg::Type(ty) = arg {
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut v = V(false);
|
||||
v.visit_ty(ty);
|
||||
v.visit_ty_unambig(ty);
|
||||
v.0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_errors::Diag;
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_hir::{
|
||||
Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
|
||||
AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -140,7 +140,7 @@ impl LateLintPass<'_> for DisallowedMacros {
|
|||
self.check(cx, stmt.span, None);
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_, AmbigArg>) {
|
||||
self.check(cx, ty.span, None);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
|
||||
use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
|
@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) {
|
||||
if let TyKind::Path(path) = &ty.kind {
|
||||
self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,22 +76,22 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
|
|||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
|
||||
if let ExprKind::MethodCall(_method, receiver, args, _) = expr.kind {
|
||||
for arg in args {
|
||||
check_clousure(cx, Some(receiver), arg);
|
||||
check_closure(cx, Some(receiver), arg);
|
||||
}
|
||||
}
|
||||
if let ExprKind::Call(func, args) = expr.kind {
|
||||
check_clousure(cx, None, func);
|
||||
check_closure(cx, None, func);
|
||||
for arg in args {
|
||||
check_clousure(cx, None, arg);
|
||||
check_closure(cx, None, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) {
|
||||
fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) {
|
||||
let body = if let ExprKind::Closure(c) = expr.kind
|
||||
&& c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer))
|
||||
&& c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(())))
|
||||
&& matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_))
|
||||
&& !expr.span.from_expansion()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
|||
use clippy_utils::{is_from_proc_macro, trait_ref_of_method};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty};
|
||||
use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty, walk_unambig_ty};
|
||||
use rustc_hir::{
|
||||
BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
|
||||
PredicateOrigin, Ty, WherePredicate, WherePredicateKind,
|
||||
AmbigArg, BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item,
|
||||
ItemKind, PredicateOrigin, Ty, WherePredicate, WherePredicateKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
|
@ -196,7 +196,7 @@ fn bound_to_trait_def_id(bound: &GenericBound<'_>) -> Option<LocalDefId> {
|
|||
impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
|
||||
type NestedFilter = nested_filter::OnlyBodies;
|
||||
|
||||
fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
|
||||
fn visit_ty(&mut self, t: &'tcx Ty<'tcx, AmbigArg>) {
|
||||
if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
|
||||
self.ty_params.remove(&def_id);
|
||||
} else {
|
||||
|
|
@ -234,7 +234,7 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
|
|||
// type, any params we find nested inside of it are being used as concrete types,
|
||||
// and can therefore can be considered used. So, we're fine to walk the left-hand
|
||||
// side of the where bound.
|
||||
walk_ty(self, predicate.bounded_ty);
|
||||
walk_unambig_ty(self, predicate.bounded_ty);
|
||||
}
|
||||
for bound in predicate.bounds {
|
||||
walk_param_bound(self, bound);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
|
|||
"replace the `Into` implementation with `From<{}>`",
|
||||
middle_trait_ref.self_ty()
|
||||
);
|
||||
if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) {
|
||||
if let Some(suggestions) =
|
||||
convert_to_from(cx, into_trait_seg, target_ty.as_unambig_ty(), self_ty, impl_item_ref)
|
||||
{
|
||||
diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
|
||||
} else {
|
||||
diag.help(message);
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ use std::borrow::Cow;
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty};
|
||||
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
|
||||
use rustc_hir::intravisit::{Visitor, VisitorExt, walk_body, walk_expr, walk_ty};
|
||||
use rustc_hir::{self as hir, AmbigArg, Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
|
|
@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
|||
match item.kind {
|
||||
ItemKind::Impl(impl_) => {
|
||||
let mut vis = ImplicitHasherTypeVisitor::new(cx);
|
||||
vis.visit_ty(impl_.self_ty);
|
||||
vis.visit_ty_unambig(impl_.self_ty);
|
||||
|
||||
for target in &vis.found {
|
||||
if !item.span.eq_ctxt(target.span()) {
|
||||
|
|
@ -159,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
|
|||
|
||||
for ty in sig.decl.inputs {
|
||||
let mut vis = ImplicitHasherTypeVisitor::new(cx);
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_ty_unambig(ty);
|
||||
|
||||
for target in &vis.found {
|
||||
if generics.span.from_expansion() {
|
||||
|
|
@ -287,21 +286,13 @@ impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'_, 'tcx> {
|
||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) {
|
||||
if let Some(target) = ImplicitHasherType::new(self.cx, t) {
|
||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'_, AmbigArg>) {
|
||||
if let Some(target) = ImplicitHasherType::new(self.cx, t.as_unambig_ty()) {
|
||||
self.found.push(target);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks for default-hasher-dependent constructors like `HashMap::new`.
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use clippy_utils::source::snippet;
|
|||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{
|
||||
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind,
|
||||
WherePredicateKind,
|
||||
AmbigArg, AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers,
|
||||
TyKind, WherePredicateKind,
|
||||
};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -146,7 +146,9 @@ fn try_resolve_type<'tcx>(
|
|||
index: usize,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
match args.get(index - 1) {
|
||||
Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty)),
|
||||
// I don't think we care about `GenericArg::Infer` since this is all for stuff in type signatures
|
||||
// which do not permit inference variables.
|
||||
Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty.as_unambig_ty())),
|
||||
Some(_) => None,
|
||||
None => Some(tcx.type_of(generics.own_params[index].def_id).skip_binder()),
|
||||
}
|
||||
|
|
@ -335,7 +337,7 @@ impl<'tcx> LateLintPass<'tcx> for ImpliedBoundsInImpls {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &rustc_hir::Ty<'tcx>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &rustc_hir::Ty<'tcx, AmbigArg>) {
|
||||
if let TyKind::OpaqueDef(opaque_ty, ..) = ty.kind {
|
||||
check(cx, opaque_ty.bounds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
|
|||
impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped {
|
||||
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
|
||||
if let Some(ty) = local.ty // Ensure that it has a type defined
|
||||
&& let TyKind::Infer = &ty.kind // that type is '_'
|
||||
&& let TyKind::Infer(()) = &ty.kind // that type is '_'
|
||||
&& local.span.eq_ctxt(ty.span)
|
||||
&& !in_external_macro(cx.tcx.sess, local.span)
|
||||
&& !is_from_proc_macro(cx, ty)
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ use rustc_errors::Applicability;
|
|||
use rustc_hir::FnRetTy::Return;
|
||||
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
|
||||
use rustc_hir::intravisit::{
|
||||
Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref,
|
||||
walk_trait_ref, walk_ty, walk_where_predicate,
|
||||
Visitor, VisitorExt, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound,
|
||||
walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, walk_where_predicate,
|
||||
};
|
||||
use rustc_hir::{
|
||||
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics,
|
||||
HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef,
|
||||
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate,
|
||||
AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind,
|
||||
Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node,
|
||||
PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate,
|
||||
WherePredicateKind, lang_items,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
|
@ -232,11 +232,11 @@ fn could_use_elision<'tcx>(
|
|||
|
||||
// extract lifetimes in input argument types
|
||||
for arg in func.inputs {
|
||||
input_visitor.visit_ty(arg);
|
||||
input_visitor.visit_ty_unambig(arg);
|
||||
}
|
||||
// extract lifetimes in output type
|
||||
if let Return(ty) = func.output {
|
||||
output_visitor.visit_ty(ty);
|
||||
output_visitor.visit_ty_unambig(ty);
|
||||
}
|
||||
for lt in named_generics {
|
||||
input_visitor.visit_generic_param(lt);
|
||||
|
|
@ -340,7 +340,7 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident:
|
|||
&& let Some(self_ty) = func.inputs.first()
|
||||
{
|
||||
let mut visitor = RefVisitor::new(cx);
|
||||
visitor.visit_ty(self_ty);
|
||||
visitor.visit_ty_unambig(self_ty);
|
||||
|
||||
!visitor.all_lts().is_empty()
|
||||
} else {
|
||||
|
|
@ -426,14 +426,14 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
|
||||
fn visit_ty(&mut self, ty: &'tcx Ty<'_, AmbigArg>) {
|
||||
match ty.kind {
|
||||
TyKind::BareFn(&BareFnTy { decl, .. }) => {
|
||||
let mut sub_visitor = RefVisitor::new(self.cx);
|
||||
sub_visitor.visit_fn_decl(decl);
|
||||
self.nested_elision_site_lts.append(&mut sub_visitor.all_lts());
|
||||
},
|
||||
TyKind::TraitObject(bounds, lt, _) => {
|
||||
TyKind::TraitObject(bounds, lt) => {
|
||||
if !lt.is_elided() {
|
||||
self.unelided_trait_object_lifetime = true;
|
||||
}
|
||||
|
|
@ -456,7 +456,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
|
|||
// a predicate like F: Trait or F: for<'a> Trait<'a>
|
||||
let mut visitor = RefVisitor::new(cx);
|
||||
// walk the type F, it may not contain LT refs
|
||||
walk_ty(&mut visitor, pred.bounded_ty);
|
||||
walk_unambig_ty(&mut visitor, pred.bounded_ty);
|
||||
if !visitor.all_lts().is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -477,8 +477,8 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
|
|||
},
|
||||
WherePredicateKind::EqPredicate(ref pred) => {
|
||||
let mut visitor = RefVisitor::new(cx);
|
||||
walk_ty(&mut visitor, pred.lhs_ty);
|
||||
walk_ty(&mut visitor, pred.rhs_ty);
|
||||
walk_unambig_ty(&mut visitor, pred.lhs_ty);
|
||||
walk_unambig_ty(&mut visitor, pred.rhs_ty);
|
||||
if !visitor.lts.is_empty() {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ where
|
|||
try_visit!(self.visit_id(hir_id));
|
||||
|
||||
self.bounded_ty_depth += 1;
|
||||
try_visit!(self.visit_ty(bounded_ty));
|
||||
try_visit!(self.visit_ty_unambig(bounded_ty));
|
||||
self.bounded_ty_depth -= 1;
|
||||
|
||||
walk_list!(self, visit_param_bound, bounds);
|
||||
|
|
@ -625,7 +625,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<'
|
|||
if let Some(ref trait_ref) = impl_.of_trait {
|
||||
walk_trait_ref(&mut checker, trait_ref);
|
||||
}
|
||||
walk_ty(&mut checker, impl_.self_ty);
|
||||
walk_unambig_ty(&mut checker, impl_.self_ty);
|
||||
for item in impl_.items {
|
||||
walk_impl_item_ref(&mut checker, item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use clippy_utils::source::snippet;
|
|||
use hir::def::{DefKind, Res};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, AmbigArg};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::edition::Edition;
|
||||
|
|
@ -123,7 +123,7 @@ impl LateLintPass<'_> for MacroUseImports {
|
|||
self.push_unique_macro_pat_ty(cx, pat.span);
|
||||
}
|
||||
}
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, AmbigArg>) {
|
||||
if ty.span.from_expansion() {
|
||||
self.push_unique_macro_pat_ty(cx, ty.span);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ use clippy_utils::source::snippet_with_context;
|
|||
use rustc_ast::ast::LitKind;
|
||||
use rustc_data_structures::packed::Pu128;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -57,13 +57,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits {
|
|||
&& let ctxt = expr.span.ctxt()
|
||||
&& left_expr.span.ctxt() == ctxt
|
||||
&& right_expr.span.ctxt() == ctxt
|
||||
&& let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr)
|
||||
&& let Some((real_ty_span, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr)
|
||||
&& matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_))
|
||||
&& let ExprKind::Lit(lit) = &other_expr.kind
|
||||
&& let LitKind::Int(Pu128(8), _) = lit.node
|
||||
{
|
||||
let mut app = Applicability::MachineApplicable;
|
||||
let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0;
|
||||
let ty_snip = snippet_with_context(cx, real_ty_span, ctxt, "..", &mut app).0;
|
||||
let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS"));
|
||||
|
||||
span_lint_and_sugg(
|
||||
|
|
@ -85,21 +85,21 @@ fn get_one_size_of_ty<'tcx>(
|
|||
cx: &LateContext<'tcx>,
|
||||
expr1: &'tcx Expr<'_>,
|
||||
expr2: &'tcx Expr<'_>,
|
||||
) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>, &'tcx Expr<'tcx>)> {
|
||||
) -> Option<(Span, Ty<'tcx>, &'tcx Expr<'tcx>)> {
|
||||
match (get_size_of_ty(cx, expr1), get_size_of_ty(cx, expr2)) {
|
||||
(Some((real_ty, resolved_ty)), None) => Some((real_ty, resolved_ty, expr2)),
|
||||
(None, Some((real_ty, resolved_ty))) => Some((real_ty, resolved_ty, expr1)),
|
||||
(Some((real_ty_span, resolved_ty)), None) => Some((real_ty_span, resolved_ty, expr2)),
|
||||
(None, Some((real_ty_span, resolved_ty))) => Some((real_ty_span, resolved_ty, expr1)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> {
|
||||
fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Span, Ty<'tcx>)> {
|
||||
if let ExprKind::Call(count_func, []) = expr.kind
|
||||
&& let ExprKind::Path(ref count_func_qpath) = count_func.kind
|
||||
&& let QPath::Resolved(_, count_func_path) = count_func_qpath
|
||||
&& let Some(segment_zero) = count_func_path.segments.first()
|
||||
&& let Some(args) = segment_zero.args
|
||||
&& let Some(GenericArg::Type(real_ty)) = args.args.first()
|
||||
&& let Some(real_ty_span) = args.args.first().map(|arg| arg.span())
|
||||
&& let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
|
||||
{
|
||||
|
|
@ -107,7 +107,7 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
|
|||
.node_args(count_func.hir_id)
|
||||
.types()
|
||||
.next()
|
||||
.map(|resolved_ty| (*real_ty, resolved_ty))
|
||||
.map(|resolved_ty| (real_ty_span, resolved_ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
|
|||
Node::Param(..) => (),
|
||||
Node::LetStmt(local) => {
|
||||
let Some(ty) = local.ty else { return };
|
||||
if matches!(ty.kind, TyKind::Infer) {
|
||||
if matches!(ty.kind, TyKind::Infer(())) {
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(super) fn check<'tcx>(
|
|||
fn_decl.output,
|
||||
FnRetTy::DefaultReturn(_)
|
||||
| FnRetTy::Return(hir::Ty {
|
||||
kind: hir::TyKind::Infer,
|
||||
kind: hir::TyKind::Infer(()),
|
||||
..
|
||||
})
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, AmbigArg};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
|
||||
use super::UNNECESSARY_LITERAL_UNWRAP;
|
||||
|
||||
fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a>> {
|
||||
fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a, AmbigArg>> {
|
||||
let args = args?;
|
||||
|
||||
if args.len() <= index {
|
||||
|
|
@ -16,10 +16,7 @@ fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -
|
|||
}
|
||||
|
||||
match args[index] {
|
||||
hir::GenericArg::Type(ty) => match ty.kind {
|
||||
hir::TyKind::Infer => None,
|
||||
_ => Some(ty),
|
||||
},
|
||||
hir::GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>,
|
|||
fn find_elem_explicit_type_span(fn_decl: &FnDecl<'_>) -> Option<Span> {
|
||||
if let [tuple_ty] = fn_decl.inputs
|
||||
&& let TyKind::Tup([_idx_ty, elem_ty]) = tuple_ty.kind
|
||||
&& !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer)
|
||||
&& !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer(()))
|
||||
{
|
||||
Some(elem_ty.span)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use clippy_utils::diagnostics::{span_lint, span_lint_hir};
|
||||
use clippy_utils::higher;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::{self as hir, AmbigArg, intravisit};
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty;
|
||||
|
|
@ -34,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
|
|||
intravisit::walk_block(&mut MutVisitor { cx }, block);
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_, AmbigArg>) {
|
||||
if let hir::TyKind::Ref(_, mty) = ty.kind
|
||||
&& mty.mutbl == hir::Mutability::Mut
|
||||
&& let hir::TyKind::Ref(_, mty) = mty.ty.kind
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@ fn in_impl<'tcx>(
|
|||
&& let Some(generic_args) = seg.args
|
||||
&& let Some(GenericArg::Type(other_ty)) = generic_args.args.last()
|
||||
{
|
||||
Some((item.self_ty, other_ty))
|
||||
// `_` is not permitted in impl headers
|
||||
Some((item.self_ty, other_ty.as_unambig_ty()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||
use clippy_utils::last_path_segment;
|
||||
use clippy_utils::source::snippet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind};
|
||||
use rustc_hir::{AmbigArg, GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::symbol::sym;
|
||||
|
|
@ -36,7 +36,7 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) {
|
||||
if let TyKind::Ref(_, ref mut_ty) = ty.kind
|
||||
&& mut_ty.mutbl == Mutability::Not
|
||||
&& let TyKind::Path(qpath) = &mut_ty.ty.kind
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_data_structures::unhash::UnhashMap;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{
|
||||
BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
|
||||
TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind,
|
||||
AmbigArg, BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment,
|
||||
PredicateOrigin, QPath, TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind,
|
||||
};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
|
@ -171,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) {
|
||||
if let TyKind::Ref(.., mut_ty) = &ty.kind
|
||||
&& let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind
|
||||
&& bounds.len() > 2
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ pub(super) fn check<'tcx>(
|
|||
let missing_generic = match args {
|
||||
Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg {
|
||||
GenericArg::Infer(_) => true,
|
||||
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer),
|
||||
_ => false,
|
||||
}),
|
||||
_ => true,
|
||||
|
|
@ -65,7 +64,7 @@ pub(super) fn check<'tcx>(
|
|||
// ... which does have type annotations.
|
||||
if let Some(ty) = local.ty
|
||||
// If this is a `let x: _ =`, we should lint.
|
||||
&& !matches!(ty.kind, TyKind::Infer)
|
||||
&& !matches!(ty.kind, TyKind::Infer(()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
|
|||
_ => None,
|
||||
})
|
||||
{
|
||||
if is_any_trait(cx, inner) {
|
||||
if is_any_trait(cx, inner.as_unambig_ty()) {
|
||||
// Ignore `Box<Any>` types; see issue #1884 for details.
|
||||
return false;
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
|
|||
// Originally reported as the issue #3128.
|
||||
let inner_snippet = snippet(cx, inner.span, "..");
|
||||
let suggestion = match &inner.kind {
|
||||
TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
|
||||
TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => {
|
||||
format!("&{ltopt}({inner_snippet})")
|
||||
},
|
||||
TyKind::Path(qpath)
|
||||
|
|
|
|||
|
|
@ -560,7 +560,7 @@ impl Types {
|
|||
_ => None,
|
||||
})
|
||||
}) {
|
||||
self.check_ty(cx, ty, context);
|
||||
self.check_ty(cx, ty.as_unambig_ty(), context);
|
||||
}
|
||||
},
|
||||
QPath::Resolved(None, p) => {
|
||||
|
|
@ -574,7 +574,7 @@ impl Types {
|
|||
_ => None,
|
||||
})
|
||||
}) {
|
||||
self.check_ty(cx, ty, context);
|
||||
self.check_ty(cx, ty.as_unambig_ty(), context);
|
||||
}
|
||||
},
|
||||
QPath::TypeRelative(ty, seg) => {
|
||||
|
|
@ -585,7 +585,7 @@ impl Types {
|
|||
GenericArg::Type(ty) => Some(ty),
|
||||
_ => None,
|
||||
}) {
|
||||
self.check_ty(cx, ty, context);
|
||||
self.check_ty(cx, ty.as_unambig_ty(), context);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
|
||||
use rustc_hir::{GenericParamKind, TyKind};
|
||||
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, TyKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::TYPE_COMPLEXITY;
|
||||
|
|
@ -10,7 +10,7 @@ use super::TYPE_COMPLEXITY;
|
|||
pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool {
|
||||
let score = {
|
||||
let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_ty_unambig(ty);
|
||||
visitor.score
|
||||
};
|
||||
|
||||
|
|
@ -36,15 +36,15 @@ struct TypeComplexityVisitor {
|
|||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
||||
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
|
||||
fn visit_infer(&mut self, inf_id: hir::HirId, _inf_span: Span, _kind: InferKind<'tcx>) -> Self::Result {
|
||||
self.score += 1;
|
||||
walk_inf(self, inf);
|
||||
self.visit_id(inf_id);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) {
|
||||
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_, AmbigArg>) {
|
||||
let (add_score, sub_nest) = match ty.kind {
|
||||
// _, &x and *x have only small overhead; don't mess with nesting level
|
||||
TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0),
|
||||
// &x and *x have only small overhead; don't mess with nesting level
|
||||
TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0),
|
||||
|
||||
// the "normal" components of a type: named types, arrays/tuples
|
||||
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1),
|
||||
|
|
@ -52,7 +52,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
|
|||
// function types bring a lot of overhead
|
||||
TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1),
|
||||
|
||||
TyKind::TraitObject(param_bounds, _, _) => {
|
||||
TyKind::TraitObject(param_bounds, _) => {
|
||||
let has_lifetime_parameters = param_bounds.iter().any(|bound| {
|
||||
bound
|
||||
.bound_generic_params
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ pub(super) fn check<'tcx>(
|
|||
&& let Some(GenericArg::Type(boxed_ty)) = last.args.first()
|
||||
// extract allocator from the Box for later
|
||||
&& let boxed_alloc_ty = last.args.get(1)
|
||||
&& let ty_ty = lower_ty(cx.tcx, boxed_ty)
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
&& let ty_ty = lower_ty(cx.tcx, boxed_ty.as_unambig_ty())
|
||||
&& !ty_ty.has_escaping_bound_vars()
|
||||
&& ty_ty.is_sized(cx.tcx, cx.typing_env())
|
||||
&& let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
|
||||
|
|
@ -55,7 +56,8 @@ pub(super) fn check<'tcx>(
|
|||
}
|
||||
},
|
||||
(Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) =>
|
||||
lower_ty(cx.tcx, l) == lower_ty(cx.tcx, r),
|
||||
// we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay
|
||||
lower_ty(cx.tcx, l.as_unambig_ty()) == lower_ty(cx.tcx, r.as_unambig_ty()),
|
||||
_ => false
|
||||
}
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer))
|
||||
if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer(())))
|
||||
|| matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
|
||||
&& expr_needs_inferred_result(cx, init)
|
||||
{
|
||||
|
|
@ -158,7 +158,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -
|
|||
}
|
||||
while let Some(id) = locals_to_check.pop() {
|
||||
if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) {
|
||||
if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer)) {
|
||||
if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer(()))) {
|
||||
return false;
|
||||
}
|
||||
if let Some(e) = l.init {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
|
||||
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
|
||||
use rustc_hir::{
|
||||
self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
|
||||
ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
|
||||
self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind,
|
||||
HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
|
||||
};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
|
@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
|
||||
if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
|
||||
let mut visitor = SkipTyCollector::default();
|
||||
visitor.visit_ty(impl_hir_ty);
|
||||
visitor.visit_ty_unambig(impl_hir_ty);
|
||||
types_to_skip.extend(visitor.types_to_skip);
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx>) {
|
||||
fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx, AmbigArg>) {
|
||||
if !hir_ty.span.from_expansion()
|
||||
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
|
||||
&& let Some(&StackItem::Check {
|
||||
|
|
@ -218,7 +218,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
|
|||
&& let ty = if in_body > 0 {
|
||||
cx.typeck_results().node_type(hir_ty.hir_id)
|
||||
} else {
|
||||
lower_ty(cx.tcx, hir_ty)
|
||||
// We don't care about ignoring infer vars here
|
||||
lower_ty(cx.tcx, hir_ty.as_unambig_ty())
|
||||
}
|
||||
&& let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity()
|
||||
&& same_type_and_consts(ty, impl_ty)
|
||||
|
|
@ -275,12 +276,14 @@ struct SkipTyCollector {
|
|||
}
|
||||
|
||||
impl Visitor<'_> for SkipTyCollector {
|
||||
fn visit_infer(&mut self, inf: &hir::InferArg) {
|
||||
self.types_to_skip.push(inf.hir_id);
|
||||
|
||||
walk_inf(self, inf);
|
||||
fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result {
|
||||
// Conservatively assume ambiguously kinded inferred arguments are type arguments
|
||||
if let InferKind::Ambig(_) | InferKind::Ty(_) = kind {
|
||||
self.types_to_skip.push(inf_id);
|
||||
}
|
||||
self.visit_id(inf_id);
|
||||
}
|
||||
fn visit_ty(&mut self, hir_ty: &Ty<'_>) {
|
||||
fn visit_ty(&mut self, hir_ty: &Ty<'_, AmbigArg>) {
|
||||
self.types_to_skip.push(hir_ty.hir_id);
|
||||
|
||||
walk_ty(self, hir_ty);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item};
|
||||
use rustc_hir::{self as hir, HirId, ItemKind, Node};
|
||||
use rustc_hir::{self as hir, AmbigArg, HirId, ItemKind, Node};
|
||||
use rustc_hir_analysis::lower_ty;
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_middle::ty::layout::LayoutOf as _;
|
||||
|
|
@ -44,10 +44,11 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]);
|
||||
|
||||
impl LateLintPass<'_> for ZeroSizedMapValues {
|
||||
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) {
|
||||
fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx, AmbigArg>) {
|
||||
if !hir_ty.span.from_expansion()
|
||||
&& !in_trait_impl(cx, hir_ty.hir_id)
|
||||
&& let ty = ty_from_hir_ty(cx, hir_ty)
|
||||
// We don't care about infer vars
|
||||
&& let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty())
|
||||
&& (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
|
||||
&& let ty::Adt(_, args) = ty.kind()
|
||||
&& let ty = args.type_at(1)
|
||||
|
|
|
|||
|
|
@ -399,8 +399,8 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) {
|
|||
TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1),
|
||||
TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")),
|
||||
TyKind::Path(qpath) => qpath_search_pat(&qpath),
|
||||
TyKind::Infer => (Pat::Str("_"), Pat::Str("_")),
|
||||
TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), Pat::Str("")),
|
||||
TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")),
|
||||
TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => (Pat::Str("dyn"), Pat::Str("")),
|
||||
// NOTE: `TraitObject` is incomplete. It will always return true then.
|
||||
_ => (Pat::Str(""), Pat::Str("")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -459,9 +459,9 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
|
||||
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
|
||||
match (left, right) {
|
||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r),
|
||||
(GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l.as_unambig_ct(), r.as_unambig_ct()),
|
||||
(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::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty.as_unambig_ty(), r_ty.as_unambig_ty()),
|
||||
(GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
|
||||
_ => false,
|
||||
}
|
||||
|
|
@ -618,7 +618,7 @@ impl HirEqInterExpr<'_, '_, '_> {
|
|||
},
|
||||
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
|
||||
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
||||
(&TyKind::Infer, &TyKind::Infer) => true,
|
||||
(&TyKind::Infer(()), &TyKind::Infer(())) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
@ -1281,7 +1281,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
}
|
||||
},
|
||||
TyKind::Path(qpath) => self.hash_qpath(qpath),
|
||||
TyKind::TraitObject(_, lifetime, _) => {
|
||||
TyKind::TraitObject(_, lifetime) => {
|
||||
self.hash_lifetime(lifetime);
|
||||
},
|
||||
TyKind::Typeof(anon_const) => {
|
||||
|
|
@ -1291,7 +1291,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_ty(binder.inner_ty);
|
||||
},
|
||||
TyKind::Err(_)
|
||||
| TyKind::Infer
|
||||
| TyKind::Infer(())
|
||||
| TyKind::Never
|
||||
| TyKind::InferDelegation(..)
|
||||
| TyKind::OpaqueDef(_)
|
||||
|
|
@ -1318,8 +1318,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
for arg in arg_list {
|
||||
match *arg {
|
||||
GenericArg::Lifetime(l) => self.hash_lifetime(l),
|
||||
GenericArg::Type(ty) => self.hash_ty(ty),
|
||||
GenericArg::Const(ca) => self.hash_const_arg(ca),
|
||||
GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()),
|
||||
GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()),
|
||||
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc
|
|||
.map_or(&[][..], |a| a.args)
|
||||
.iter()
|
||||
.filter_map(|a| match a {
|
||||
hir::GenericArg::Type(ty) => Some(*ty),
|
||||
hir::GenericArg::Type(ty) => Some(ty.as_unambig_ty()),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
|
@ -2148,7 +2148,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
|
|||
pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
match expr.kind {
|
||||
ExprKind::Closure(&Closure { body, fn_decl, .. })
|
||||
if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) =>
|
||||
if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) =>
|
||||
{
|
||||
is_body_identity_function(cx, cx.tcx.hir().body(body))
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
use crate::def_path_res;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty};
|
||||
use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
|
||||
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_qpath, walk_ty};
|
||||
use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
|
@ -116,14 +116,15 @@ impl<'cx> Visitor<'cx> for CertaintyVisitor<'cx, '_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &'cx hir::Ty<'_>) {
|
||||
if matches!(ty.kind, TyKind::Infer) {
|
||||
self.certainty = Certainty::Uncertain;
|
||||
}
|
||||
fn visit_ty(&mut self, ty: &'cx hir::Ty<'_, AmbigArg>) {
|
||||
if self.certainty != Certainty::Uncertain {
|
||||
walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_infer(&mut self, _inf_id: HirId, _inf_span: Span, _kind: InferKind<'cx>) -> Self::Result {
|
||||
self.certainty = Certainty::Uncertain;
|
||||
}
|
||||
}
|
||||
|
||||
fn type_certainty(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Certainty {
|
||||
|
|
@ -139,7 +140,7 @@ fn type_certainty(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Certainty {
|
|||
}
|
||||
|
||||
let mut visitor = CertaintyVisitor::new(cx);
|
||||
visitor.visit_ty(ty);
|
||||
visitor.visit_ty_unambig(ty);
|
||||
visitor.certainty
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::ty::needs_ordered_drop;
|
|||
use crate::{get_enclosing_block, path_to_local_id};
|
||||
use core::ops::ControlFlow;
|
||||
use rustc_ast::visit::{VisitorResult, try_visit};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::{self as hir, AmbigArg};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
|
||||
use rustc_hir::{
|
||||
|
|
@ -122,7 +122,7 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
|
|||
}
|
||||
|
||||
// Avoid unnecessary `walk_*` calls.
|
||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
|
||||
|
|
@ -172,7 +172,7 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
|
|||
ControlFlow::Continue(())
|
||||
}
|
||||
// Avoid unnecessary `walk_*` calls.
|
||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result {
|
||||
fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue