1
Fork 0

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:
bors 2025-01-24 11:12:01 +00:00
commit 8231e8599e
119 changed files with 1056 additions and 669 deletions

View file

@ -28,6 +28,7 @@ use rustc_data_structures::packed::Pu128;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::tagged_ptr::Tag;
use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_macros::{Decodable, Encodable, HashStable_Generic};
pub use rustc_span::AttrId; pub use rustc_span::AttrId;
use rustc_span::source_map::{Spanned, respan}; use rustc_span::source_map::{Spanned, respan};
@ -287,6 +288,7 @@ impl ParenthesizedArgs {
} }
} }
use crate::AstDeref;
pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId}; pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId};
/// Modifiers on a trait bound like `~const`, `?` and `!`. /// Modifiers on a trait bound like `~const`, `?` and `!`.
@ -2165,6 +2167,14 @@ impl Ty {
} }
final_ty final_ty
} }
pub fn is_maybe_parenthesised_infer(&self) -> bool {
match &self.kind {
TyKind::Infer => true,
TyKind::Paren(inner) => inner.ast_deref().is_maybe_parenthesised_infer(),
_ => false,
}
}
} }
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
@ -2269,10 +2279,32 @@ impl TyKind {
/// Syntax used to declare a trait object. /// Syntax used to declare a trait object.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
#[repr(u8)]
pub enum TraitObjectSyntax { pub enum TraitObjectSyntax {
Dyn, // SAFETY: When adding new variants make sure to update the `Tag` impl.
DynStar, Dyn = 0,
None, DynStar = 1,
None = 2,
}
/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
/// it can be represented with a `u2`. We use `repr(u8)` to guarantee the
/// discriminants of the variants are no greater than `3`.
unsafe impl Tag for TraitObjectSyntax {
const BITS: u32 = 2;
fn into_usize(self) -> usize {
self as u8 as usize
}
unsafe fn from_usize(tag: usize) -> Self {
match tag {
0 => TraitObjectSyntax::Dyn,
1 => TraitObjectSyntax::DynStar,
2 => TraitObjectSyntax::None,
_ => unreachable!(),
}
}
} }
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]

View file

@ -1,3 +1,4 @@
use intravisit::InferKind;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap};
@ -265,14 +266,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}); });
} }
fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg));
self.with_parent(const_arg.hir_id, |this| {
intravisit::walk_const_arg(this, const_arg);
});
}
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) { fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
self.insert(expr.span, expr.hir_id, Node::Expr(expr)); self.insert(expr.span, expr.hir_id, Node::Expr(expr));
@ -302,22 +295,41 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
intravisit::walk_path_segment(self, path_segment); intravisit::walk_path_segment(self, path_segment);
} }
fn visit_ty(&mut self, ty: &'hir Ty<'hir>) { fn visit_ty(&mut self, ty: &'hir Ty<'hir, AmbigArg>) {
self.insert(ty.span, ty.hir_id, Node::Ty(ty)); self.insert(ty.span, ty.hir_id, Node::Ty(ty.as_unambig_ty()));
self.with_parent(ty.hir_id, |this| { self.with_parent(ty.hir_id, |this| {
intravisit::walk_ty(this, ty); intravisit::walk_ty(this, ty);
}); });
} }
fn visit_infer(&mut self, inf: &'hir InferArg) { fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir, AmbigArg>) {
self.insert(inf.span, inf.hir_id, Node::Infer(inf)); self.insert(
const_arg.as_unambig_ct().span(),
const_arg.hir_id,
Node::ConstArg(const_arg.as_unambig_ct()),
);
self.with_parent(inf.hir_id, |this| { self.with_parent(const_arg.hir_id, |this| {
intravisit::walk_inf(this, inf); intravisit::walk_ambig_const_arg(this, const_arg);
}); });
} }
fn visit_infer(
&mut self,
inf_id: HirId,
inf_span: Span,
kind: InferKind<'hir>,
) -> Self::Result {
match kind {
InferKind::Ty(ty) => self.insert(inf_span, inf_id, Node::Ty(ty)),
InferKind::Const(ct) => self.insert(inf_span, inf_id, Node::ConstArg(ct)),
InferKind::Ambig(inf) => self.insert(inf_span, inf_id, Node::Infer(inf)),
}
self.visit_id(inf_id);
}
fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) { fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) {
self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr)); self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr));

View file

@ -48,6 +48,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::tagged_ptr::TaggedRef;
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
@ -1083,17 +1084,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match arg { match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
ast::GenericArg::Type(ty) => { ast::GenericArg::Type(ty) => {
match &ty.kind { // We cannot just match on `TyKind::Infer` as `(_)` is represented as
TyKind::Infer if self.tcx.features().generic_arg_infer() => { // `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer`
if ty.is_maybe_parenthesised_infer() {
return GenericArg::Infer(hir::InferArg { return GenericArg::Infer(hir::InferArg {
hir_id: self.lower_node_id(ty.id), hir_id: self.lower_node_id(ty.id),
span: self.lower_span(ty.span), span: self.lower_span(ty.span),
}); });
} }
match &ty.kind {
// We parse const arguments as path types as we cannot distinguish them during // We parse const arguments as path types as we cannot distinguish them during
// parsing. We try to resolve that ambiguity by attempting resolution in both the // parsing. We try to resolve that ambiguity by attempting resolution in both the
// type and value namespaces. If we resolved the path in the value namespace, we // type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument. // transform it into a generic const argument.
//
// FIXME: Should we be handling `(PATH_TO_CONST)`?
TyKind::Path(None, path) => { TyKind::Path(None, path) => {
if let Some(res) = self if let Some(res) = self
.resolver .resolver
@ -1110,15 +1116,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let ct = let ct =
self.lower_const_path_to_const_arg(path, res, ty.id, ty.span); self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);
return GenericArg::Const(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap());
} }
} }
} }
_ => {} _ => {}
} }
GenericArg::Type(self.lower_ty(ty, itctx)) GenericArg::Type(self.lower_ty(ty, itctx).try_as_ambig_ty().unwrap())
}
ast::GenericArg::Const(ct) => {
GenericArg::Const(self.lower_anon_const_to_const_arg(ct).try_as_ambig_ct().unwrap())
} }
ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)),
} }
} }
@ -1158,7 +1166,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let lifetime_bound = this.elided_dyn_bound(t.span); let lifetime_bound = this.elided_dyn_bound(t.span);
(bounds, lifetime_bound) (bounds, lifetime_bound)
}); });
let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); let kind = hir::TyKind::TraitObject(
bounds,
TaggedRef::new(lifetime_bound, TraitObjectSyntax::None),
);
return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() };
} }
@ -1185,7 +1196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
let kind = match &t.kind { let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer, TyKind::Infer => hir::TyKind::Infer(()),
TyKind::Err(guar) => hir::TyKind::Err(*guar), TyKind::Err(guar) => hir::TyKind::Err(*guar),
TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
@ -1309,7 +1320,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
(bounds, lifetime_bound) (bounds, lifetime_bound)
}); });
hir::TyKind::TraitObject(bounds, lifetime_bound, *kind) hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind))
} }
TyKind::ImplTrait(def_node_id, bounds) => { TyKind::ImplTrait(def_node_id, bounds) => {
let span = t.span; let span = t.span;
@ -2041,7 +2052,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
.stash(c.value.span, StashKey::UnderscoreForArrayLengths); .stash(c.value.span, StashKey::UnderscoreForArrayLengths);
} }
let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span), ());
self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind })
} }
_ => self.lower_anon_const_to_const_arg(c), _ => self.lower_anon_const_to_const_arg(c),
@ -2365,8 +2376,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir_id = self.next_id(); hir_id = self.next_id();
hir::TyKind::TraitObject( hir::TyKind::TraitObject(
arena_vec![self; principal], arena_vec![self; principal],
self.elided_dyn_bound(span), TaggedRef::new(self.elided_dyn_bound(span), TraitObjectSyntax::None),
TraitObjectSyntax::None,
) )
} }
_ => hir::TyKind::Path(hir::QPath::Resolved(None, path)), _ => hir::TyKind::Path(hir::QPath::Resolved(None, path)),

View file

@ -525,7 +525,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
}; };
let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; let args = smallvec![GenericArg::Type(
self.arena.alloc(self.ty_tup(*inputs_span, inputs)).try_as_ambig_ty().unwrap()
)];
// If we have a bound like `async Fn() -> T`, make sure that we mark the // If we have a bound like `async Fn() -> T`, make sure that we mark the
// `Output = T` associated type bound with the right feature gates. // `Output = T` associated type bound with the right feature gates.

View file

@ -8,7 +8,7 @@ use rustc_hir::QPath::Resolved;
use rustc_hir::WherePredicateKind::BoundPredicate; use rustc_hir::WherePredicateKind::BoundPredicate;
use rustc_hir::def::Res::Def; use rustc_hir::def::Res::Def;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate}; use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
use rustc_middle::bug; use rustc_middle::bug;
@ -887,7 +887,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if alias_ty.span.desugaring_kind().is_some() { if alias_ty.span.desugaring_kind().is_some() {
// Skip `async` desugaring `impl Future`. // Skip `async` desugaring `impl Future`.
} }
if let TyKind::TraitObject(_, lt, _) = alias_ty.kind { if let TyKind::TraitObject(_, lt) = alias_ty.kind {
if lt.ident.name == kw::Empty { if lt.ident.name == kw::Empty {
spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string())); spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string()));
} else { } else {
@ -987,7 +987,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
for found_did in found_dids { for found_did in found_dids {
let mut traits = vec![]; let mut traits = vec![];
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
hir_v.visit_ty(self_ty); hir_v.visit_ty_unambig(self_ty);
debug!("trait spans found: {:?}", traits); debug!("trait spans found: {:?}", traits);
for span in &traits { for span in &traits {
let mut multi_span: MultiSpan = vec![*span].into(); let mut multi_span: MultiSpan = vec![*span].into();

View file

@ -432,7 +432,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// must highlight the variable. // must highlight the variable.
// NOTE(eddyb) this is handled in/by the sole caller // NOTE(eddyb) this is handled in/by the sole caller
// (`give_name_if_anonymous_region_appears_in_arguments`). // (`give_name_if_anonymous_region_appears_in_arguments`).
hir::TyKind::Infer => None, hir::TyKind::Infer(()) => None,
_ => Some(argument_hir_ty), _ => Some(argument_hir_ty),
} }
@ -615,7 +615,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
} }
(GenericArgKind::Type(ty), hir::GenericArg::Type(hir_ty)) => { (GenericArgKind::Type(ty), hir::GenericArg::Type(hir_ty)) => {
search_stack.push((ty, hir_ty)); search_stack.push((ty, hir_ty.as_unambig_ty()));
} }
(GenericArgKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => { (GenericArgKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => {

View file

@ -15,6 +15,7 @@ pub use rustc_ast::{
}; };
use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::tagged_ptr::TaggedRef;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_macros::{Decodable, Encodable, HashStable_Generic};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
@ -30,7 +31,7 @@ use crate::LangItem;
use crate::def::{CtorKind, DefKind, Res}; use crate::def::{CtorKind, DefKind, Res};
use crate::def_id::{DefId, LocalDefIdMap}; use crate::def_id::{DefId, LocalDefIdMap};
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
use crate::intravisit::FnKind; use crate::intravisit::{FnKind, VisitorExt};
#[derive(Debug, Copy, Clone, HashStable_Generic)] #[derive(Debug, Copy, Clone, HashStable_Generic)]
pub struct Lifetime { pub struct Lifetime {
@ -263,14 +264,58 @@ impl<'hir> PathSegment<'hir> {
/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args /// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args
/// that are [just paths](ConstArgKind::Path) (currently just bare const params) /// that are [just paths](ConstArgKind::Path) (currently just bare const params)
/// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`). /// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`).
///
/// The `Unambig` generic parameter represents whether the position this const is from is
/// unambiguously a const or ambiguous as to whether it is a type or a const. When in an
/// ambiguous context the parameter is instantiated with an uninhabited type making the
/// [`ConstArgKind::Infer`] variant unusable and [`GenericArg::Infer`] is used instead.
#[derive(Clone, Copy, Debug, HashStable_Generic)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
pub struct ConstArg<'hir> { #[repr(C)]
pub struct ConstArg<'hir, Unambig = ()> {
#[stable_hasher(ignore)] #[stable_hasher(ignore)]
pub hir_id: HirId, pub hir_id: HirId,
pub kind: ConstArgKind<'hir>, pub kind: ConstArgKind<'hir, Unambig>,
}
impl<'hir> ConstArg<'hir, AmbigArg> {
/// Converts a `ConstArg` in an ambiguous position to one in an unambiguous position.
///
/// Functions accepting an unambiguous consts may expect the [`ConstArgKind::Infer`] variant
/// to be used. Care should be taken to separately handle infer consts when calling this
/// function as it cannot be handled by downstream code making use of the returned const.
///
/// In practice this may mean overriding the [`Visitor::visit_infer`][visit_infer] method on hir visitors, or
/// specifically matching on [`GenericArg::Infer`] when handling generic arguments.
///
/// [visit_infer]: [rustc_hir::intravisit::Visitor::visit_infer]
pub fn as_unambig_ct(&self) -> &ConstArg<'hir> {
// SAFETY: `ConstArg` is `repr(C)` and `ConstArgKind` is marked `repr(u8)` so that the
// layout is the same across different ZST type arguments.
let ptr = self as *const ConstArg<'hir, AmbigArg> as *const ConstArg<'hir, ()>;
unsafe { &*ptr }
}
} }
impl<'hir> ConstArg<'hir> { impl<'hir> ConstArg<'hir> {
/// Converts a `ConstArg` in an unambigous position to one in an ambiguous position. This is
/// fallible as the [`ConstArgKind::Infer`] variant is not present in ambiguous positions.
///
/// Functions accepting ambiguous consts will not handle the [`ConstArgKind::Infer`] variant, if
/// infer consts are relevant to you then care should be taken to handle them separately.
pub fn try_as_ambig_ct(&self) -> Option<&ConstArg<'hir, AmbigArg>> {
if let ConstArgKind::Infer(_, ()) = self.kind {
return None;
}
// SAFETY: `ConstArg` is `repr(C)` and `ConstArgKind` is marked `repr(u8)` so that the layout is
// the same across different ZST type arguments. We also asserted that the `self` is
// not a `ConstArgKind::Infer` so there is no risk of transmuting a `()` to `AmbigArg`.
let ptr = self as *const ConstArg<'hir> as *const ConstArg<'hir, AmbigArg>;
Some(unsafe { &*ptr })
}
}
impl<'hir, Unambig> ConstArg<'hir, Unambig> {
pub fn anon_const_hir_id(&self) -> Option<HirId> { pub fn anon_const_hir_id(&self) -> Option<HirId> {
match self.kind { match self.kind {
ConstArgKind::Anon(ac) => Some(ac.hir_id), ConstArgKind::Anon(ac) => Some(ac.hir_id),
@ -282,14 +327,15 @@ impl<'hir> ConstArg<'hir> {
match self.kind { match self.kind {
ConstArgKind::Path(path) => path.span(), ConstArgKind::Path(path) => path.span(),
ConstArgKind::Anon(anon) => anon.span, ConstArgKind::Anon(anon) => anon.span,
ConstArgKind::Infer(span) => span, ConstArgKind::Infer(span, _) => span,
} }
} }
} }
/// See [`ConstArg`]. /// See [`ConstArg`].
#[derive(Clone, Copy, Debug, HashStable_Generic)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
pub enum ConstArgKind<'hir> { #[repr(u8, C)]
pub enum ConstArgKind<'hir, Unambig = ()> {
/// **Note:** Currently this is only used for bare const params /// **Note:** Currently this is only used for bare const params
/// (`N` where `fn foo<const N: usize>(...)`), /// (`N` where `fn foo<const N: usize>(...)`),
/// not paths to any const (`N` where `const N: usize = ...`). /// not paths to any const (`N` where `const N: usize = ...`).
@ -297,11 +343,9 @@ pub enum ConstArgKind<'hir> {
/// However, in the future, we'll be using it for all of those. /// However, in the future, we'll be using it for all of those.
Path(QPath<'hir>), Path(QPath<'hir>),
Anon(&'hir AnonConst), Anon(&'hir AnonConst),
/// **Note:** Not all inferred consts are represented as /// This variant is not always used to represent inference consts, sometimes
/// `ConstArgKind::Infer`. In cases where it is ambiguous whether /// [`GenericArg::Infer`] is used instead.
/// a generic arg is a type or a const, inference variables are Infer(Span, Unambig),
/// represented as `GenericArg::Infer` instead.
Infer(Span),
} }
#[derive(Clone, Copy, Debug, HashStable_Generic)] #[derive(Clone, Copy, Debug, HashStable_Generic)]
@ -313,19 +357,24 @@ pub struct InferArg {
impl InferArg { impl InferArg {
pub fn to_ty(&self) -> Ty<'static> { pub fn to_ty(&self) -> Ty<'static> {
Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id } Ty { kind: TyKind::Infer(()), span: self.span, hir_id: self.hir_id }
} }
} }
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum GenericArg<'hir> { pub enum GenericArg<'hir> {
Lifetime(&'hir Lifetime), Lifetime(&'hir Lifetime),
Type(&'hir Ty<'hir>), Type(&'hir Ty<'hir, AmbigArg>),
Const(&'hir ConstArg<'hir>), Const(&'hir ConstArg<'hir, AmbigArg>),
/// **Note:** Inference variables are only represented as /// Inference variables in [`GenericArg`] are always represnted by
/// `GenericArg::Infer` in cases where it is ambiguous whether /// `GenericArg::Infer` instead of the `Infer` variants on [`TyKind`] and
/// a generic arg is a type or a const. Otherwise, inference variables /// [`ConstArgKind`] as it is not clear until hir ty lowering whether a
/// are represented as `TyKind::Infer` or `ConstArgKind::Infer`. /// `_` argument is a type or const argument.
///
/// However, some builtin types' generic arguments are represented by [`TyKind`]
/// without a [`GenericArg`], instead directly storing a [`Ty`] or [`ConstArg`]. In
/// such cases they *are* represented by the `Infer` variants on [`TyKind`] and
/// [`ConstArgKind`] as it is not ambiguous whether the argument is a type or const.
Infer(InferArg), Infer(InferArg),
} }
@ -353,7 +402,7 @@ impl GenericArg<'_> {
GenericArg::Lifetime(_) => "lifetime", GenericArg::Lifetime(_) => "lifetime",
GenericArg::Type(_) => "type", GenericArg::Type(_) => "type",
GenericArg::Const(_) => "constant", GenericArg::Const(_) => "constant",
GenericArg::Infer(_) => "inferred", GenericArg::Infer(_) => "placeholder",
} }
} }
@ -764,11 +813,8 @@ impl<'hir> Generics<'hir> {
&& let [.., segment] = trait_ref.path.segments && let [.., segment] = trait_ref.path.segments
&& let Some(ret_ty) = segment.args().paren_sugar_output() && let Some(ret_ty) = segment.args().paren_sugar_output()
&& let ret_ty = ret_ty.peel_refs() && let ret_ty = ret_ty.peel_refs()
&& let TyKind::TraitObject( && let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
_, && let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag()
_,
TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar,
) = ret_ty.kind
&& ret_ty.span.can_be_used_for_suggestions() && ret_ty.span.can_be_used_for_suggestions()
{ {
Some(ret_ty.span) Some(ret_ty.span)
@ -2917,15 +2963,84 @@ impl<'hir> AssocItemConstraintKind<'hir> {
} }
} }
/// An uninhabited enum used to make `Infer` variants on [`Ty`] and [`ConstArg`] be
/// unreachable. Zero-Variant enums are guaranteed to have the same layout as the never
/// type.
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Ty<'hir> { pub enum AmbigArg {}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
#[repr(C)]
/// Represents a type in the `HIR`.
///
/// The `Unambig` generic parameter represents whether the position this type is from is
/// unambiguously a type or ambiguous as to whether it is a type or a const. When in an
/// ambiguous context the parameter is instantiated with an uninhabited type making the
/// [`TyKind::Infer`] variant unusable and [`GenericArg::Infer`] is used instead.
pub struct Ty<'hir, Unambig = ()> {
#[stable_hasher(ignore)] #[stable_hasher(ignore)]
pub hir_id: HirId, pub hir_id: HirId,
pub kind: TyKind<'hir>,
pub span: Span, pub span: Span,
pub kind: TyKind<'hir, Unambig>,
}
impl<'hir> Ty<'hir, AmbigArg> {
/// Converts a `Ty` in an ambiguous position to one in an unambiguous position.
///
/// Functions accepting an unambiguous types may expect the [`TyKind::Infer`] variant
/// to be used. Care should be taken to separately handle infer types when calling this
/// function as it cannot be handled by downstream code making use of the returned ty.
///
/// In practice this may mean overriding the [`Visitor::visit_infer`][visit_infer] method on hir visitors, or
/// specifically matching on [`GenericArg::Infer`] when handling generic arguments.
///
/// [visit_infer]: [rustc_hir::intravisit::Visitor::visit_infer]
pub fn as_unambig_ty(&self) -> &Ty<'hir> {
// SAFETY: `Ty` is `repr(C)` and `TyKind` is marked `repr(u8)` so that the layout is
// the same across different ZST type arguments.
let ptr = self as *const Ty<'hir, AmbigArg> as *const Ty<'hir, ()>;
unsafe { &*ptr }
}
} }
impl<'hir> Ty<'hir> { impl<'hir> Ty<'hir> {
/// Converts a `Ty` in an unambigous position to one in an ambiguous position. This is
/// fallible as the [`TyKind::Infer`] variant is not present in ambiguous positions.
///
/// Functions accepting ambiguous types will not handle the [`TyKind::Infer`] variant, if
/// infer types are relevant to you then care should be taken to handle them separately.
pub fn try_as_ambig_ty(&self) -> Option<&Ty<'hir, AmbigArg>> {
if let TyKind::Infer(()) = self.kind {
return None;
}
// SAFETY: `Ty` is `repr(C)` and `TyKind` is marked `repr(u8)` so that the layout is
// the same across different ZST type arguments. We also asserted that the `self` is
// not a `TyKind::Infer` so there is no risk of transmuting a `()` to `AmbigArg`.
let ptr = self as *const Ty<'hir> as *const Ty<'hir, AmbigArg>;
Some(unsafe { &*ptr })
}
}
impl<'hir> Ty<'hir, AmbigArg> {
pub fn peel_refs(&self) -> &Ty<'hir> {
let mut final_ty = self.as_unambig_ty();
while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = ty;
}
final_ty
}
}
impl<'hir> Ty<'hir> {
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = ty;
}
final_ty
}
/// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate.
pub fn as_generic_param(&self) -> Option<(DefId, Ident)> { pub fn as_generic_param(&self) -> Option<(DefId, Ident)> {
let TyKind::Path(QPath::Resolved(None, path)) = self.kind else { let TyKind::Path(QPath::Resolved(None, path)) = self.kind else {
@ -2942,19 +3057,11 @@ impl<'hir> Ty<'hir> {
} }
} }
pub fn peel_refs(&self) -> &Self {
let mut final_ty = self;
while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind {
final_ty = ty;
}
final_ty
}
pub fn find_self_aliases(&self) -> Vec<Span> { pub fn find_self_aliases(&self) -> Vec<Span> {
use crate::intravisit::Visitor; use crate::intravisit::Visitor;
struct MyVisitor(Vec<Span>); struct MyVisitor(Vec<Span>);
impl<'v> Visitor<'v> for MyVisitor { impl<'v> Visitor<'v> for MyVisitor {
fn visit_ty(&mut self, t: &'v Ty<'v>) { fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) {
if matches!( if matches!(
&t.kind, &t.kind,
TyKind::Path(QPath::Resolved(_, Path { TyKind::Path(QPath::Resolved(_, Path {
@ -2970,7 +3077,7 @@ impl<'hir> Ty<'hir> {
} }
let mut my_visitor = MyVisitor(vec![]); let mut my_visitor = MyVisitor(vec![]);
my_visitor.visit_ty(self); my_visitor.visit_ty_unambig(self);
my_visitor.0 my_visitor.0
} }
@ -2979,14 +3086,14 @@ impl<'hir> Ty<'hir> {
pub fn is_suggestable_infer_ty(&self) -> bool { pub fn is_suggestable_infer_ty(&self) -> bool {
fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool { fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
generic_args.iter().any(|arg| match arg { generic_args.iter().any(|arg| match arg {
GenericArg::Type(ty) => ty.is_suggestable_infer_ty(), GenericArg::Type(ty) => ty.as_unambig_ty().is_suggestable_infer_ty(),
GenericArg::Infer(_) => true, GenericArg::Infer(_) => true,
_ => false, _ => false,
}) })
} }
debug!(?self); debug!(?self);
match &self.kind { match &self.kind {
TyKind::Infer => true, TyKind::Infer(()) => true,
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
TyKind::Array(ty, length) => { TyKind::Array(ty, length) => {
ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..)) ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..))
@ -3200,7 +3307,9 @@ pub enum InferDelegationKind {
/// The various kinds of types recognized by the compiler. /// The various kinds of types recognized by the compiler.
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TyKind<'hir> { // SAFETY: `repr(u8)` is required so that `TyKind<()>` and `TyKind<!>` are layout compatible
#[repr(u8, C)]
pub enum TyKind<'hir, Unambig = ()> {
/// Actual type should be inherited from `DefId` signature /// Actual type should be inherited from `DefId` signature
InferDelegation(DefId, InferDelegationKind), InferDelegation(DefId, InferDelegationKind),
/// A variable length slice (i.e., `[T]`). /// A variable length slice (i.e., `[T]`).
@ -3230,21 +3339,22 @@ pub enum TyKind<'hir> {
TraitAscription(GenericBounds<'hir>), TraitAscription(GenericBounds<'hir>),
/// A trait object type `Bound1 + Bound2 + Bound3` /// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime. /// where `Bound` is a trait or a lifetime.
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), ///
/// We use pointer tagging to represent a `&'hir Lifetime` and `TraitObjectSyntax` pair
/// as otherwise this type being `repr(C)` would result in `TyKind` increasing in size.
TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
/// Unused for now. /// Unused for now.
Typeof(&'hir AnonConst), Typeof(&'hir AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
///
/// **Note:** Not all inferred types are represented as
/// `TyKind::Infer`. In cases where it is ambiguous whether
/// a generic arg is a type or a const, inference variables are
/// represented as `GenericArg::Infer` instead.
Infer,
/// Placeholder for a type that has failed to be defined. /// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed), Err(rustc_span::ErrorGuaranteed),
/// Pattern types (`pattern_type!(u32 is 1..)`) /// Pattern types (`pattern_type!(u32 is 1..)`)
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>), Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
/// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
///
/// This variant is not always used to represent inference types, sometimes
/// [`GenericArg::Infer`] is used instead.
Infer(Unambig),
} }
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]
@ -4537,3 +4647,6 @@ fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Deb
} }
DebugFn(f) DebugFn(f)
} }
#[cfg(test)]
mod tests;

View file

@ -0,0 +1,83 @@
use rustc_span::def_id::DefIndex;
use super::*;
macro_rules! define_tests {
($($name:ident $kind:ident $variant:ident {$($init:tt)*})*) => {$(
#[test]
fn $name() {
let unambig = $kind::$variant::<'_, ()> { $($init)* };
let unambig_to_ambig = unsafe { std::mem::transmute::<_, $kind<'_, AmbigArg>>(unambig) };
assert!(matches!(&unambig_to_ambig, $kind::$variant { $($init)* }));
let ambig_to_unambig = unsafe { std::mem::transmute::<_, $kind<'_, ()>>(unambig_to_ambig) };
assert!(matches!(&ambig_to_unambig, $kind::$variant { $($init)* }));
}
)*};
}
define_tests! {
cast_never TyKind Never {}
cast_tup TyKind Tup { 0: &[Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }] }
cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, mutbl: Mutability::Not }}
cast_array TyKind Array {
0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never },
1: &ConstArg { hir_id: HirId::INVALID, kind: ConstArgKind::Anon(&AnonConst {
hir_id: HirId::INVALID,
def_id: LocalDefId { local_def_index: DefIndex::ZERO },
body: BodyId { hir_id: HirId::INVALID },
span: DUMMY_SP,
})}
}
cast_anon ConstArgKind Anon {
0: &AnonConst {
hir_id: HirId::INVALID,
def_id: LocalDefId { local_def_index: DefIndex::ZERO },
body: BodyId { hir_id: HirId::INVALID },
span: DUMMY_SP,
}
}
}
#[test]
fn trait_object_roundtrips() {
trait_object_roundtrips_impl(TraitObjectSyntax::Dyn);
trait_object_roundtrips_impl(TraitObjectSyntax::DynStar);
trait_object_roundtrips_impl(TraitObjectSyntax::None);
}
fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
let unambig = TyKind::TraitObject::<'_, ()>(
&[],
TaggedRef::new(
&const {
Lifetime {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
res: LifetimeName::Static,
}
},
syntax,
),
);
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };
match unambig_to_ambig {
TyKind::TraitObject(_, tagged_ref) => {
assert!(tagged_ref.tag() == syntax)
}
_ => panic!("`TyKind::TraitObject` did not roundtrip"),
};
let ambig_to_unambig = unsafe { std::mem::transmute::<_, TyKind<'_, ()>>(unambig_to_ambig) };
match ambig_to_unambig {
TyKind::TraitObject(_, tagged_ref) => {
assert!(tagged_ref.tag() == syntax)
}
_ => panic!("`TyKind::TraitObject` did not roundtrip"),
};
}

View file

@ -351,18 +351,48 @@ pub trait Visitor<'v>: Sized {
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result { fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
walk_inline_const(self, c) walk_inline_const(self, c)
} }
fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
walk_const_arg(self, c) fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result {
walk_generic_arg(self, generic_arg)
} }
/// All types are treated as ambiguous types for the purposes of hir visiting in
/// order to ensure that visitors can handle infer vars without it being too error-prone.
///
/// See the doc comments on [`Ty`] for an explanation of what it means for a type to be
/// ambiguous.
///
/// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) -> Self::Result {
walk_ty(self, t)
}
/// All consts are treated as ambiguous consts for the purposes of hir visiting in
/// order to ensure that visitors can handle infer vars without it being too error-prone.
///
/// See the doc comments on [`ConstArg`] for an explanation of what it means for a const to be
/// ambiguous.
///
/// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
fn visit_const_arg(&mut self, c: &'v ConstArg<'v, AmbigArg>) -> Self::Result {
walk_ambig_const_arg(self, c)
}
#[allow(unused_variables)]
fn visit_infer(&mut self, inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
self.visit_id(inf_id)
}
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result {
walk_lifetime(self, lifetime)
}
fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result { fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result {
walk_expr(self, ex) walk_expr(self, ex)
} }
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result { fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
walk_expr_field(self, field) walk_expr_field(self, field)
} }
fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result {
walk_ty(self, t)
}
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) { fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
// Do nothing. Only a few visitors need to know the details of the pattern type, // Do nothing. Only a few visitors need to know the details of the pattern type,
// and they opt into it. All other visitors will just choke on our fake patterns // and they opt into it. All other visitors will just choke on our fake patterns
@ -444,15 +474,6 @@ pub trait Visitor<'v>: Sized {
fn visit_label(&mut self, label: &'v Label) -> Self::Result { fn visit_label(&mut self, label: &'v Label) -> Self::Result {
walk_label(self, label) walk_label(self, label)
} }
fn visit_infer(&mut self, inf: &'v InferArg) -> Self::Result {
walk_inf(self, inf)
}
fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result {
walk_generic_arg(self, generic_arg)
}
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result {
walk_lifetime(self, lifetime)
}
// The span is that of the surrounding type/pattern/expr/whatever. // The span is that of the surrounding type/pattern/expr/whatever.
fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result { fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result {
walk_qpath(self, qpath, id) walk_qpath(self, qpath, id)
@ -486,6 +507,26 @@ pub trait Visitor<'v>: Sized {
} }
} }
pub trait VisitorExt<'v>: Visitor<'v> {
/// Extension trait method to visit types in unambiguous positions, this is not
/// directly on the [`Visitor`] trait as this method should never be overridden.
///
/// Named `visit_ty_unambig` instead of `visit_unambig_ty` to aid in discovery
/// by IDes when `v.visit_ty` is written.
fn visit_ty_unambig(&mut self, t: &'v Ty<'v>) -> Self::Result {
walk_unambig_ty(self, t)
}
/// Extension trait method to visit consts in unambiguous positions, this is not
/// directly on the [`Visitor`] trait as this method should never be overridden.
///
/// Named `visit_const_arg_unambig` instead of `visit_unambig_const_arg` to aid in
/// discovery by IDes when `v.visit_const_arg` is written.
fn visit_const_arg_unambig(&mut self, c: &'v ConstArg<'v>) -> Self::Result {
walk_const_arg(self, c)
}
}
impl<'v, V: Visitor<'v>> VisitorExt<'v> for V {}
pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result { pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result {
try_visit!(visitor.visit_id(param.hir_id)); try_visit!(visitor.visit_id(param.hir_id));
visitor.visit_pat(param.pat) visitor.visit_pat(param.pat)
@ -503,12 +544,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
} }
ItemKind::Static(ref typ, _, body) => { ItemKind::Static(ref typ, _, body) => {
try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(visitor.visit_ty(typ)); try_visit!(visitor.visit_ty_unambig(typ));
try_visit!(visitor.visit_nested_body(body)); try_visit!(visitor.visit_nested_body(body));
} }
ItemKind::Const(ref typ, ref generics, body) => { ItemKind::Const(ref typ, ref generics, body) => {
try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(visitor.visit_ty(typ)); try_visit!(visitor.visit_ty_unambig(typ));
try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_generics(generics));
try_visit!(visitor.visit_nested_body(body)); try_visit!(visitor.visit_nested_body(body));
} }
@ -539,7 +580,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
} }
ItemKind::TyAlias(ref ty, ref generics) => { ItemKind::TyAlias(ref ty, ref generics) => {
try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_generics(generics));
} }
ItemKind::Enum(ref enum_definition, ref generics) => { ItemKind::Enum(ref enum_definition, ref generics) => {
@ -561,7 +602,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_id(item.hir_id()));
try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_generics(generics));
visit_opt!(visitor, visit_trait_ref, of_trait); visit_opt!(visitor, visit_trait_ref, of_trait);
try_visit!(visitor.visit_ty(self_ty)); try_visit!(visitor.visit_ty_unambig(self_ty));
walk_list!(visitor, visit_impl_item_ref, *items); walk_list!(visitor, visit_impl_item_ref, *items);
} }
ItemKind::Struct(ref struct_definition, ref generics) ItemKind::Struct(ref struct_definition, ref generics)
@ -618,7 +659,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
walk_list!(visitor, visit_ident, param_names.iter().copied()); walk_list!(visitor, visit_ident, param_names.iter().copied());
} }
ForeignItemKind::Static(ref typ, _, _) => { ForeignItemKind::Static(ref typ, _, _) => {
try_visit!(visitor.visit_ty(typ)); try_visit!(visitor.visit_ty_unambig(typ));
} }
ForeignItemKind::Type => (), ForeignItemKind::Type => (),
} }
@ -632,7 +673,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v LetStmt<'v>) -
try_visit!(visitor.visit_id(local.hir_id)); try_visit!(visitor.visit_id(local.hir_id));
try_visit!(visitor.visit_pat(local.pat)); try_visit!(visitor.visit_pat(local.pat));
visit_opt!(visitor, visit_block, local.els); visit_opt!(visitor, visit_block, local.els);
visit_opt!(visitor, visit_ty, local.ty); visit_opt!(visitor, visit_ty_unambig, local.ty);
V::Result::output() V::Result::output()
} }
@ -735,18 +776,6 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>(
visitor.visit_nested_body(constant.body) visitor.visit_nested_body(constant.body)
} }
pub fn walk_const_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
const_arg: &'v ConstArg<'v>,
) -> V::Result {
try_visit!(visitor.visit_id(const_arg.hir_id));
match &const_arg.kind {
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
ConstArgKind::Infer(..) => V::Result::output(),
}
}
pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result {
try_visit!(visitor.visit_id(expression.hir_id)); try_visit!(visitor.visit_id(expression.hir_id));
match expression.kind { match expression.kind {
@ -758,7 +787,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
} }
ExprKind::Repeat(ref element, ref count) => { ExprKind::Repeat(ref element, ref count) => {
try_visit!(visitor.visit_expr(element)); try_visit!(visitor.visit_expr(element));
try_visit!(visitor.visit_const_arg(count)); try_visit!(visitor.visit_const_arg_unambig(count));
} }
ExprKind::Struct(ref qpath, fields, ref optional_base) => { ExprKind::Struct(ref qpath, fields, ref optional_base) => {
try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
@ -789,7 +818,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
} }
ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
try_visit!(visitor.visit_expr(subexpression)); try_visit!(visitor.visit_expr(subexpression));
try_visit!(visitor.visit_ty(typ)); try_visit!(visitor.visit_ty_unambig(typ));
} }
ExprKind::DropTemps(ref subexpression) => { ExprKind::DropTemps(ref subexpression) => {
try_visit!(visitor.visit_expr(subexpression)); try_visit!(visitor.visit_expr(subexpression));
@ -798,7 +827,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
// match the visit order in walk_local // match the visit order in walk_local
try_visit!(visitor.visit_expr(init)); try_visit!(visitor.visit_expr(init));
try_visit!(visitor.visit_pat(pat)); try_visit!(visitor.visit_pat(pat));
visit_opt!(visitor, visit_ty, ty); visit_opt!(visitor, visit_ty_unambig, ty);
} }
ExprKind::If(ref cond, ref then, ref else_opt) => { ExprKind::If(ref cond, ref then, ref else_opt) => {
try_visit!(visitor.visit_expr(cond)); try_visit!(visitor.visit_expr(cond));
@ -866,7 +895,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
try_visit!(visitor.visit_inline_asm(asm, expression.hir_id)); try_visit!(visitor.visit_inline_asm(asm, expression.hir_id));
} }
ExprKind::OffsetOf(ref container, ref fields) => { ExprKind::OffsetOf(ref container, ref fields) => {
try_visit!(visitor.visit_ty(container)); try_visit!(visitor.visit_ty_unambig(container));
walk_list!(visitor, visit_ident, fields.iter().copied()); walk_list!(visitor, visit_ident, fields.iter().copied());
} }
ExprKind::Yield(ref subexpression, _) => { ExprKind::Yield(ref subexpression, _) => {
@ -874,7 +903,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
} }
ExprKind::UnsafeBinderCast(_kind, expr, ty) => { ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
try_visit!(visitor.visit_expr(expr)); try_visit!(visitor.visit_expr(expr));
visit_opt!(visitor, visit_ty, ty); visit_opt!(visitor, visit_ty_unambig, ty);
} }
ExprKind::Lit(_) | ExprKind::Err(_) => {} ExprKind::Lit(_) | ExprKind::Err(_) => {}
} }
@ -886,20 +915,49 @@ pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField
try_visit!(visitor.visit_ident(field.ident)); try_visit!(visitor.visit_ident(field.ident));
visitor.visit_expr(field.expr) visitor.visit_expr(field.expr)
} }
/// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that
/// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited
pub enum InferKind<'hir> {
Ty(&'hir Ty<'hir>),
Const(&'hir ConstArg<'hir>),
Ambig(&'hir InferArg),
}
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result { pub fn walk_generic_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
generic_arg: &'v GenericArg<'v>,
) -> V::Result {
match generic_arg {
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
GenericArg::Type(ty) => visitor.visit_ty(ty),
GenericArg::Const(ct) => visitor.visit_const_arg(ct),
GenericArg::Infer(inf) => visitor.visit_infer(inf.hir_id, inf.span, InferKind::Ambig(inf)),
}
}
pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result {
match typ.try_as_ambig_ty() {
Some(ambig_ty) => visitor.visit_ty(ambig_ty),
None => {
try_visit!(visitor.visit_id(typ.hir_id));
visitor.visit_infer(typ.hir_id, typ.span, InferKind::Ty(typ))
}
}
}
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -> V::Result {
try_visit!(visitor.visit_id(typ.hir_id)); try_visit!(visitor.visit_id(typ.hir_id));
match typ.kind { match typ.kind {
TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty(ty)), TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty(mutable_type.ty)), TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty_unambig(mutable_type.ty)),
TyKind::Ref(ref lifetime, ref mutable_type) => { TyKind::Ref(ref lifetime, ref mutable_type) => {
try_visit!(visitor.visit_lifetime(lifetime)); try_visit!(visitor.visit_lifetime(lifetime));
try_visit!(visitor.visit_ty(mutable_type.ty)); try_visit!(visitor.visit_ty_unambig(mutable_type.ty));
} }
TyKind::Never => {} TyKind::Never => {}
TyKind::Tup(tuple_element_types) => { TyKind::Tup(tuple_element_types) => {
walk_list!(visitor, visit_ty, tuple_element_types); walk_list!(visitor, visit_ty_unambig, tuple_element_types);
} }
TyKind::BareFn(ref function_declaration) => { TyKind::BareFn(ref function_declaration) => {
walk_list!(visitor, visit_generic_param, function_declaration.generic_params); walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
@ -907,7 +965,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
} }
TyKind::UnsafeBinder(ref unsafe_binder) => { TyKind::UnsafeBinder(ref unsafe_binder) => {
walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params); walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params);
try_visit!(visitor.visit_ty(unsafe_binder.inner_ty)); try_visit!(visitor.visit_ty_unambig(unsafe_binder.inner_ty));
} }
TyKind::Path(ref qpath) => { TyKind::Path(ref qpath) => {
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span)); try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
@ -919,25 +977,49 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_param_bound, bounds);
} }
TyKind::Array(ref ty, ref length) => { TyKind::Array(ref ty, ref length) => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
try_visit!(visitor.visit_const_arg(length)); try_visit!(visitor.visit_const_arg_unambig(length));
} }
TyKind::TraitObject(bounds, ref lifetime, _syntax) => { TyKind::TraitObject(bounds, ref lifetime) => {
for bound in bounds { for bound in bounds {
try_visit!(visitor.visit_poly_trait_ref(bound)); try_visit!(visitor.visit_poly_trait_ref(bound));
} }
try_visit!(visitor.visit_lifetime(lifetime)); try_visit!(visitor.visit_lifetime(lifetime));
} }
TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)), TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)),
TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {} TyKind::InferDelegation(..) | TyKind::Err(_) => {}
TyKind::Pat(ty, pat) => { TyKind::Pat(ty, pat) => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
try_visit!(visitor.visit_pattern_type_pattern(pat)); try_visit!(visitor.visit_pattern_type_pattern(pat));
} }
} }
V::Result::output() V::Result::output()
} }
pub fn walk_const_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
const_arg: &'v ConstArg<'v>,
) -> V::Result {
match const_arg.try_as_ambig_ct() {
Some(ambig_ct) => visitor.visit_const_arg(ambig_ct),
None => {
try_visit!(visitor.visit_id(const_arg.hir_id));
visitor.visit_infer(const_arg.hir_id, const_arg.span(), InferKind::Const(const_arg))
}
}
}
pub fn walk_ambig_const_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
const_arg: &'v ConstArg<'v, AmbigArg>,
) -> V::Result {
try_visit!(visitor.visit_id(const_arg.hir_id));
match &const_arg.kind {
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()),
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
}
}
pub fn walk_generic_param<'v, V: Visitor<'v>>( pub fn walk_generic_param<'v, V: Visitor<'v>>(
visitor: &mut V, visitor: &mut V,
param: &'v GenericParam<'v>, param: &'v GenericParam<'v>,
@ -949,9 +1031,11 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
} }
match param.kind { match param.kind {
GenericParamKind::Lifetime { .. } => {} GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default), GenericParamKind::Type { ref default, .. } => {
visit_opt!(visitor, visit_ty_unambig, default)
}
GenericParamKind::Const { ref ty, ref default, synthetic: _ } => { GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
if let Some(ref default) = default { if let Some(ref default) = default {
try_visit!(visitor.visit_const_param_default(param.hir_id, default)); try_visit!(visitor.visit_const_param_default(param.hir_id, default));
} }
@ -964,7 +1048,7 @@ pub fn walk_const_param_default<'v, V: Visitor<'v>>(
visitor: &mut V, visitor: &mut V,
ct: &'v ConstArg<'v>, ct: &'v ConstArg<'v>,
) -> V::Result { ) -> V::Result {
visitor.visit_const_arg(ct) visitor.visit_const_arg_unambig(ct)
} }
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result { pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
@ -986,7 +1070,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
bound_generic_params, bound_generic_params,
origin: _, origin: _,
}) => { }) => {
try_visit!(visitor.visit_ty(bounded_ty)); try_visit!(visitor.visit_ty_unambig(bounded_ty));
walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_generic_param, bound_generic_params); walk_list!(visitor, visit_generic_param, bound_generic_params);
} }
@ -999,8 +1083,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_param_bound, bounds);
} }
WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => { WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => {
try_visit!(visitor.visit_ty(lhs_ty)); try_visit!(visitor.visit_ty_unambig(lhs_ty));
try_visit!(visitor.visit_ty(rhs_ty)); try_visit!(visitor.visit_ty_unambig(rhs_ty));
} }
} }
V::Result::output() V::Result::output()
@ -1010,13 +1094,13 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(
visitor: &mut V, visitor: &mut V,
function_declaration: &'v FnDecl<'v>, function_declaration: &'v FnDecl<'v>,
) -> V::Result { ) -> V::Result {
walk_list!(visitor, visit_ty, function_declaration.inputs); walk_list!(visitor, visit_ty_unambig, function_declaration.inputs);
visitor.visit_fn_ret_ty(&function_declaration.output) visitor.visit_fn_ret_ty(&function_declaration.output)
} }
pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result { pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result {
if let FnRetTy::Return(output_ty) = *ret_ty { if let FnRetTy::Return(output_ty) = *ret_ty {
try_visit!(visitor.visit_ty(output_ty)); try_visit!(visitor.visit_ty_unambig(output_ty));
} }
V::Result::output() V::Result::output()
} }
@ -1069,7 +1153,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_id(hir_id)); try_visit!(visitor.visit_id(hir_id));
match *kind { match *kind {
TraitItemKind::Const(ref ty, default) => { TraitItemKind::Const(ref ty, default) => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
visit_opt!(visitor, visit_nested_body, default); visit_opt!(visitor, visit_nested_body, default);
} }
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
@ -1087,7 +1171,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
} }
TraitItemKind::Type(bounds, ref default) => { TraitItemKind::Type(bounds, ref default) => {
walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_param_bound, bounds);
visit_opt!(visitor, visit_ty, default); visit_opt!(visitor, visit_ty_unambig, default);
} }
} }
V::Result::output() V::Result::output()
@ -1125,7 +1209,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_id(impl_item.hir_id())); try_visit!(visitor.visit_id(impl_item.hir_id()));
match *kind { match *kind {
ImplItemKind::Const(ref ty, body) => { ImplItemKind::Const(ref ty, body) => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty_unambig(ty));
visitor.visit_nested_body(body) visitor.visit_nested_body(body)
} }
ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn( ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn(
@ -1135,7 +1219,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
impl_item.span, impl_item.span,
impl_item.owner_id.def_id, impl_item.owner_id.def_id,
), ),
ImplItemKind::Type(ref ty) => visitor.visit_ty(ty), ImplItemKind::Type(ref ty) => visitor.visit_ty_unambig(ty),
} }
} }
@ -1223,7 +1307,7 @@ pub fn walk_field_def<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_id(*hir_id)); try_visit!(visitor.visit_id(*hir_id));
try_visit!(visitor.visit_ident(*ident)); try_visit!(visitor.visit_ident(*ident));
visit_opt!(visitor, visit_anon_const, default); visit_opt!(visitor, visit_anon_const, default);
visitor.visit_ty(*ty) visitor.visit_ty_unambig(*ty)
} }
pub fn walk_enum_def<'v, V: Visitor<'v>>( pub fn walk_enum_def<'v, V: Visitor<'v>>(
@ -1252,18 +1336,6 @@ pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Re
visitor.visit_id(inf.hir_id) visitor.visit_id(inf.hir_id)
} }
pub fn walk_generic_arg<'v, V: Visitor<'v>>(
visitor: &mut V,
generic_arg: &'v GenericArg<'v>,
) -> V::Result {
match generic_arg {
GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt),
GenericArg::Type(ty) => visitor.visit_ty(ty),
GenericArg::Const(ct) => visitor.visit_const_arg(ct),
GenericArg::Infer(inf) => visitor.visit_infer(inf),
}
}
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result { pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result {
try_visit!(visitor.visit_id(lifetime.hir_id)); try_visit!(visitor.visit_id(lifetime.hir_id));
visitor.visit_ident(lifetime.ident) visitor.visit_ident(lifetime.ident)
@ -1276,11 +1348,11 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
) -> V::Result { ) -> V::Result {
match *qpath { match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => { QPath::Resolved(ref maybe_qself, ref path) => {
visit_opt!(visitor, visit_ty, maybe_qself); visit_opt!(visitor, visit_ty_unambig, maybe_qself);
visitor.visit_path(path, id) visitor.visit_path(path, id)
} }
QPath::TypeRelative(ref qself, ref segment) => { QPath::TypeRelative(ref qself, ref segment) => {
try_visit!(visitor.visit_ty(qself)); try_visit!(visitor.visit_ty_unambig(qself));
visitor.visit_path_segment(segment) visitor.visit_path_segment(segment)
} }
QPath::LangItem(..) => V::Result::output(), QPath::LangItem(..) => V::Result::output(),
@ -1320,8 +1392,8 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
try_visit!(visitor.visit_generic_args(constraint.gen_args)); try_visit!(visitor.visit_generic_args(constraint.gen_args));
match constraint.kind { match constraint.kind {
AssocItemConstraintKind::Equality { ref term } => match term { AssocItemConstraintKind::Equality { ref term } => match term {
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), Term::Ty(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)),
Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)), Term::Const(ref c) => try_visit!(visitor.visit_const_arg_unambig(c)),
}, },
AssocItemConstraintKind::Bound { bounds } => { AssocItemConstraintKind::Bound { bounds } => {
walk_list!(visitor, visit_param_bound, bounds) walk_list!(visitor, visit_param_bound, bounds)

View file

@ -6,6 +6,7 @@
#![allow(internal_features)] #![allow(internal_features)]
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
#![feature(closure_track_caller)] #![feature(closure_track_caller)]
#![feature(exhaustive_patterns)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]

View file

@ -6,9 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::{GenericParamKind, ImplItemKind, intravisit}; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util; use rustc_infer::traits::util;
@ -1610,7 +1610,7 @@ fn compare_synthetic_generics<'tcx>(
struct Visitor(hir::def_id::LocalDefId); struct Visitor(hir::def_id::LocalDefId);
impl<'v> intravisit::Visitor<'v> for Visitor { impl<'v> intravisit::Visitor<'v> for Visitor {
type Result = ControlFlow<Span>; type Result = ControlFlow<Span>;
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) -> Self::Result { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result {
if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind
&& let Res::Def(DefKind::TyParam, def_id) = path.res && let Res::Def(DefKind::TyParam, def_id) = path.res
&& def_id == self.0.to_def_id() && def_id == self.0.to_def_id()
@ -1622,9 +1622,9 @@ fn compare_synthetic_generics<'tcx>(
} }
} }
let span = input_tys.iter().find_map(|ty| { let span = input_tys
intravisit::Visitor::visit_ty(&mut Visitor(impl_def_id), ty).break_value() .iter()
})?; .find_map(|ty| Visitor(impl_def_id).visit_ty_unambig(ty).break_value())?;
let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds;
let bounds = bounds.first()?.span().to(bounds.last()?.span()); let bounds = bounds.first()?.span().to(bounds.last()?.span());

View file

@ -6,10 +6,10 @@ use rustc_abi::ExternAbi;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
use rustc_hir::ItemKind;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{AmbigArg, ItemKind};
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_macros::LintDiagnostic; use rustc_macros::LintDiagnostic;
@ -2196,7 +2196,7 @@ impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> {
// Skip the generics. We only care about fields, not where clause/param bounds. // Skip the generics. We only care about fields, not where clause/param bounds.
} }
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind { if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind {
if let Res::Def(DefKind::TyParam, def_id) = qpath.res if let Res::Def(DefKind::TyParam, def_id) = qpath.res
&& def_id == self.param_def_id && def_id == self.param_def_id

View file

@ -28,7 +28,7 @@ use rustc_errors::{
}; };
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor, walk_generics}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics};
use rustc_hir::{self as hir, GenericParamKind, HirId, Node}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::ObligationCause;
@ -139,29 +139,12 @@ pub(crate) struct HirPlaceholderCollector {
} }
impl<'v> Visitor<'v> for HirPlaceholderCollector { impl<'v> Visitor<'v> for HirPlaceholderCollector {
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
if let hir::TyKind::Infer = t.kind { self.spans.push(inf_span);
self.spans.push(t.span);
} if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
intravisit::walk_ty(self, t)
}
fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
match generic_arg {
hir::GenericArg::Infer(inf) => {
self.spans.push(inf.span);
self.may_contain_const_infer = true; self.may_contain_const_infer = true;
intravisit::walk_inf(self, inf);
} }
hir::GenericArg::Type(t) => self.visit_ty(t),
_ => {}
}
}
fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) {
if let hir::ConstArgKind::Infer(span) = const_arg.kind {
self.may_contain_const_infer = true;
self.spans.push(span);
}
intravisit::walk_const_arg(self, const_arg)
} }
} }
@ -583,7 +566,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, a)| { .map(|(i, a)| {
if let hir::TyKind::Infer = a.kind { if let hir::TyKind::Infer(()) = a.kind {
if let Some(suggested_ty) = if let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
{ {
@ -593,21 +576,21 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
} }
// Only visit the type looking for `_` if we didn't fix the type above // Only visit the type looking for `_` if we didn't fix the type above
visitor.visit_ty(a); visitor.visit_ty_unambig(a);
self.lowerer().lower_arg_ty(a, None) self.lowerer().lower_arg_ty(a, None)
}) })
.collect(); .collect();
let output_ty = match decl.output { let output_ty = match decl.output {
hir::FnRetTy::Return(output) => { hir::FnRetTy::Return(output) => {
if let hir::TyKind::Infer = output.kind if let hir::TyKind::Infer(()) = output.kind
&& let Some(suggested_ty) = && let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
{ {
infer_replacements.push((output.span, suggested_ty.to_string())); infer_replacements.push((output.span, suggested_ty.to_string()));
Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string()) Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
} else { } else {
visitor.visit_ty(output); visitor.visit_ty_unambig(output);
self.lower_ty(output) self.lower_ty(output)
} }
} }
@ -1453,7 +1436,7 @@ fn recover_infer_ret_ty<'tcx>(
}); });
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(infer_ret_ty); visitor.visit_ty_unambig(infer_ret_ty);
let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type"); let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
let ret_ty = fn_sig.output(); let ret_ty = fn_sig.output();

View file

@ -3,9 +3,10 @@ use std::ops::ControlFlow;
use hir::intravisit::{self, Visitor}; use hir::intravisit::{self, Visitor};
use hir::{GenericParamKind, HirId, Node}; use hir::{GenericParamKind, HirId, Node};
use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg};
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::{Span, Symbol, kw}; use rustc_span::{Span, Symbol, kw};
@ -461,7 +462,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
type Result = ControlFlow<Span>; type Result = ControlFlow<Span>;
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) -> ControlFlow<Span> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) -> ControlFlow<Span> {
match ty.kind { match ty.kind {
hir::TyKind::BareFn(..) => { hir::TyKind::BareFn(..) => {
self.outer_index.shift_in(1); self.outer_index.shift_in(1);
@ -539,7 +540,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind { if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind {
let prev = self.in_param_ty; let prev = self.in_param_ty;
self.in_param_ty = true; self.in_param_ty = true;
let res = self.visit_ty(ty); let res = self.visit_ty_unambig(ty);
self.in_param_ty = prev; self.in_param_ty = prev;
res res
} else { } else {

View file

@ -14,11 +14,11 @@ use rustc_ast::visit::walk_list;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
use rustc_hir::{ use rustc_hir::{
GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, LifetimeName, Node, self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap,
LifetimeName, Node,
}; };
use rustc_macros::extension; use rustc_macros::extension;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
@ -489,15 +489,17 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
struct FindInferInClosureWithBinder; struct FindInferInClosureWithBinder;
impl<'v> Visitor<'v> for FindInferInClosureWithBinder { impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
type Result = ControlFlow<Span>; type Result = ControlFlow<Span>;
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
if matches!(t.kind, hir::TyKind::Infer) { fn visit_infer(
ControlFlow::Break(t.span) &mut self,
} else { _inf_id: HirId,
intravisit::walk_ty(self, t) inf_span: Span,
_kind: InferKind<'v>,
) -> Self::Result {
ControlFlow::Break(inf_span)
} }
} }
} FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value()
FindInferInClosureWithBinder.visit_ty(ty).break_value()
} }
let infer_in_rt_sp = match fn_decl.output { let infer_in_rt_sp = match fn_decl.output {
@ -749,7 +751,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
match ty.kind { match ty.kind {
hir::TyKind::BareFn(c) => { hir::TyKind::BareFn(c) => {
let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
@ -810,7 +812,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
intravisit::walk_ty(this, ty); intravisit::walk_ty(this, ty);
}); });
} }
hir::TyKind::TraitObject(bounds, lifetime, _) => { hir::TyKind::TraitObject(bounds, lifetime) => {
let lifetime = lifetime.pointer();
debug!(?bounds, ?lifetime, "TraitObject"); debug!(?bounds, ?lifetime, "TraitObject");
let scope = Scope::TraitRefBoundary { s: self.scope }; let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |this| { self.with(scope, |this| {
@ -827,7 +831,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
// use the object lifetime defaulting // use the object lifetime defaulting
// rules. So e.g., `Box<dyn Debug>` becomes // rules. So e.g., `Box<dyn Debug>` becomes
// `Box<dyn Debug + 'static>`. // `Box<dyn Debug + 'static>`.
self.resolve_object_lifetime_default(lifetime) self.resolve_object_lifetime_default(&*lifetime)
} }
LifetimeName::Infer => { LifetimeName::Infer => {
// If the user writes `'_`, we use the *ordinary* elision // If the user writes `'_`, we use the *ordinary* elision
@ -838,7 +842,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
} }
LifetimeName::Param(..) | LifetimeName::Static => { LifetimeName::Param(..) | LifetimeName::Static => {
// If the user wrote an explicit name, use that. // If the user wrote an explicit name, use that.
self.visit_lifetime(lifetime); self.visit_lifetime(&*lifetime);
} }
LifetimeName::Error => {} LifetimeName::Error => {}
} }
@ -849,7 +853,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(), lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(),
s: self.scope, s: self.scope,
}; };
self.with(scope, |this| this.visit_ty(mt.ty)); self.with(scope, |this| this.visit_ty_unambig(mt.ty));
} }
hir::TyKind::TraitAscription(bounds) => { hir::TyKind::TraitAscription(bounds) => {
let scope = Scope::TraitRefBoundary { s: self.scope }; let scope = Scope::TraitRefBoundary { s: self.scope };
@ -891,7 +895,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
this.visit_param_bound(bound); this.visit_param_bound(bound);
} }
if let Some(ty) = ty { if let Some(ty) = ty {
this.visit_ty(ty); this.visit_ty_unambig(ty);
} }
}) })
} }
@ -910,7 +914,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}), }),
Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| { Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
this.visit_generics(impl_item.generics); this.visit_generics(impl_item.generics);
this.visit_ty(ty); this.visit_ty_unambig(ty);
}), }),
Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| { Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item) intravisit::walk_impl_item(this, impl_item)
@ -1019,7 +1023,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}; };
self.with(scope, |this| { self.with(scope, |this| {
walk_list!(this, visit_generic_param, bound_generic_params); walk_list!(this, visit_generic_param, bound_generic_params);
this.visit_ty(bounded_ty); this.visit_ty_unambig(bounded_ty);
walk_list!(this, visit_param_bound, bounds); walk_list!(this, visit_param_bound, bounds);
}) })
} }
@ -1034,8 +1038,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
&hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
lhs_ty, rhs_ty, .. lhs_ty, rhs_ty, ..
}) => { }) => {
self.visit_ty(lhs_ty); self.visit_ty_unambig(lhs_ty);
self.visit_ty(rhs_ty); self.visit_ty_unambig(rhs_ty);
} }
} }
} }
@ -1068,13 +1072,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
GenericParamKind::Lifetime { .. } => {} GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { default, .. } => { GenericParamKind::Type { default, .. } => {
if let Some(ty) = default { if let Some(ty) = default {
self.visit_ty(ty); self.visit_ty_unambig(ty);
} }
} }
GenericParamKind::Const { ty, default, .. } => { GenericParamKind::Const { ty, default, .. } => {
self.visit_ty(ty); self.visit_ty_unambig(ty);
if let Some(default) = default { if let Some(default) = default {
self.visit_const_arg(default); self.visit_const_arg_unambig(default);
} }
} }
} }
@ -1983,15 +1987,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
}, },
|this| { |this| {
for input in inputs { for input in inputs {
this.visit_ty(input); this.visit_ty_unambig(input);
} }
if !in_closure && let Some(output) = output { if !in_closure && let Some(output) = output {
this.visit_ty(output); this.visit_ty_unambig(output);
} }
}, },
); );
if in_closure && let Some(output) = output { if in_closure && let Some(output) = output {
self.visit_ty(output); self.visit_ty_unambig(output);
} }
} }
@ -2309,7 +2313,7 @@ fn is_late_bound_map(
let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx };
for arg_ty in sig.decl.inputs { for arg_ty in sig.decl.inputs {
constrained_by_input.visit_ty(arg_ty); constrained_by_input.visit_ty_unambig(arg_ty);
} }
let mut appears_in_output = let mut appears_in_output =
@ -2417,7 +2421,7 @@ fn is_late_bound_map(
} }
impl<'v> Visitor<'v> for ConstrainedCollector<'_> { impl<'v> Visitor<'v> for ConstrainedCollector<'_> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
match ty.kind { match ty.kind {
hir::TyKind::Path( hir::TyKind::Path(
hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..), hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..),

View file

@ -1,10 +1,9 @@
use core::ops::ControlFlow; use core::ops::ControlFlow;
use rustc_errors::{Applicability, StashKey, Suggestions}; use rustc_errors::{Applicability, StashKey, Suggestions};
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::print::with_forced_trimmed_paths;
@ -451,7 +450,7 @@ fn infer_placeholder_type<'tcx>(
let mut visitor = HirPlaceholderCollector::default(); let mut visitor = HirPlaceholderCollector::default();
let node = tcx.hir_node_by_def_id(def_id); let node = tcx.hir_node_by_def_id(def_id);
if let Some(ty) = node.ty() { if let Some(ty) = node.ty() {
visitor.visit_ty(ty); visitor.visit_ty_unambig(ty);
} }
// If we have just one span, let's try to steal a const `_` feature error. // If we have just one span, let's try to steal a const `_` feature error.
let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.spans.len() == 1 let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.spans.len() == 1
@ -525,7 +524,7 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) ->
struct HasTait; struct HasTait;
impl<'tcx> Visitor<'tcx> for HasTait { impl<'tcx> Visitor<'tcx> for HasTait {
type Result = ControlFlow<()>; type Result = ControlFlow<()>;
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
if let hir::TyKind::OpaqueDef(..) = t.kind { if let hir::TyKind::OpaqueDef(..) = t.kind {
ControlFlow::Break(()) ControlFlow::Break(())
} else { } else {
@ -533,5 +532,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) ->
} }
} }
} }
HasTait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break() HasTait.visit_ty_unambig(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break()
} }

View file

@ -1,10 +1,9 @@
use rustc_ast::ast::ParamKindOrd; use rustc_ast::ast::ParamKindOrd;
use rustc_errors::codes::*; use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, struct_span_code_err}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::GenericArg;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, GenericArg};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty,
}; };
@ -41,17 +40,6 @@ fn generic_arg_mismatch_err(
param.kind.descr(), param.kind.descr(),
); );
if let GenericParamDefKind::Const { .. } = param.kind {
if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
err.help("const arguments cannot yet be inferred with `_`");
tcx.disabled_nightly_features(
&mut err,
param.def_id.as_local().map(|local| tcx.local_def_id_to_hir_id(local)),
[(String::new(), sym::generic_arg_infer)],
);
}
}
let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diag<'_>| { let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diag<'_>| {
let suggestions = vec![ let suggestions = vec![
(arg.span().shrink_to_lo(), String::from("{ ")), (arg.span().shrink_to_lo(), String::from("{ ")),
@ -270,6 +258,21 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
GenericParamDefKind::Const { .. }, GenericParamDefKind::Const { .. },
_, _,
) => { ) => {
if let GenericParamDefKind::Const { .. } = param.kind
&& let GenericArg::Infer(inf) = arg
&& !tcx.features().generic_arg_infer()
{
rustc_session::parse::feature_err(
tcx.sess,
sym::generic_arg_infer,
inf.span,
"const arguments cannot yet be inferred with `_`",
)
.emit();
}
// We lower to an infer even when the feature gate is not enabled
// as it is useful for diagnostics to be able to see a `ConstKind::Infer`
args.push(ctx.provided_kind(&args, param, arg)); args.push(ctx.provided_kind(&args, param, arg));
args_iter.next(); args_iter.next();
params.next(); params.next();

View file

@ -23,9 +23,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
) -> Option<ErrorGuaranteed> { ) -> Option<ErrorGuaranteed> {
let tcx = self.tcx(); let tcx = self.tcx();
let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = let poly_trait_ref = if let hir::TyKind::TraitObject([poly_trait_ref, ..], tagged_ptr) =
self_ty.kind self_ty.kind
else { && let TraitObjectSyntax::None = tagged_ptr.tag()
{
poly_trait_ref
} else {
return None; return None;
}; };
@ -294,7 +297,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let (dyn_str, paren_dyn_str) = let (dyn_str, paren_dyn_str) =
if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") };
let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind {
// There are more than one trait bound, we need surrounding parentheses. // There are more than one trait bound, we need surrounding parentheses.
vec![ vec![
(self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()),

View file

@ -517,14 +517,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into() self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into()
} }
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => {
handle_ty_args(has_default, ty) // We handle the other parts of `Ty` in the match arm below
handle_ty_args(has_default, ty.as_unambig_ty())
} }
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
handle_ty_args(has_default, &inf.to_ty()) handle_ty_args(has_default, &inf.to_ty())
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() .lowerer
} // Ambig portions of `ConstArg` are handled in the match arm below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.into(),
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.lowerer.ct_infer(Some(param), inf.span).into() self.lowerer.ct_infer(Some(param), inf.span).into()
} }
@ -2115,7 +2118,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
format!("Const::lower_const_arg: invalid qpath {qpath:?}"), format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
), ),
hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon), hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon),
hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
} }
} }
@ -2311,7 +2314,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
tcx.late_bound_vars(hir_ty.hir_id), tcx.late_bound_vars(hir_ty.hir_id),
), ),
), ),
hir::TyKind::TraitObject(bounds, lifetime, repr) => { hir::TyKind::TraitObject(bounds, tagged_ptr) => {
let lifetime = tagged_ptr.pointer();
let repr = tagged_ptr.tag();
if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) {
// Don't continue with type analysis if the `dyn` keyword is missing // Don't continue with type analysis if the `dyn` keyword is missing
// It generates confusing errors, especially if the user meant to use another // It generates confusing errors, especially if the user meant to use another
@ -2420,7 +2426,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
} }
hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(),
hir::TyKind::Infer => { hir::TyKind::Infer(()) => {
// Infer also appears as the type of arguments or return // Infer also appears as the type of arguments or return
// values in an ExprKind::Closure, or as // values in an ExprKind::Closure, or as
// the type of local variables. Both of these cases are // the type of local variables. Both of these cases are
@ -2553,7 +2559,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> { pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> {
match ty.kind { match ty.kind {
hir::TyKind::Infer if let Some(expected_ty) = expected_ty => { hir::TyKind::Infer(()) if let Some(expected_ty) = expected_ty => {
self.record_ty(ty.hir_id, expected_ty, ty.span); self.record_ty(ty.hir_id, expected_ty, ty.span);
expected_ty expected_ty
} }

View file

@ -1,6 +1,5 @@
use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind};
use rustc_hir::{ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_infer::traits::{ObligationCause, WellFormedLoc};
use rustc_middle::bug; use rustc_middle::bug;
@ -68,11 +67,13 @@ fn diagnostic_hir_wf_check<'tcx>(
} }
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let tcx_ty = self.icx.lower_ty(ty); // We don't handle infer vars but we wouldn't handle them anyway as we're creating a
// fresh `InferCtxt` in this function.
let tcx_ty = self.icx.lower_ty(ty.as_unambig_ty());
// This visitor can walk into binders, resulting in the `tcx_ty` to // This visitor can walk into binders, resulting in the `tcx_ty` to
// potentially reference escaping bound variables. We simply erase // potentially reference escaping bound variables. We simply erase
// those here. // those here.
@ -149,7 +150,11 @@ fn diagnostic_hir_wf_check<'tcx>(
.iter() .iter()
.flat_map(|seg| seg.args().args) .flat_map(|seg| seg.args().args)
.filter_map(|arg| { .filter_map(|arg| {
if let hir::GenericArg::Type(ty) = arg { Some(*ty) } else { None } if let hir::GenericArg::Type(ty) = arg {
Some(ty.as_unambig_ty())
} else {
None
}
}) })
.chain([impl_.self_ty]) .chain([impl_.self_ty])
.collect(), .collect(),
@ -196,7 +201,7 @@ fn diagnostic_hir_wf_check<'tcx>(
} }
}; };
for ty in tys { for ty in tys {
visitor.visit_ty(ty); visitor.visit_ty_unambig(ty);
} }
visitor.cause visitor.cause
} }

View file

@ -402,7 +402,8 @@ impl<'a> State<'a> {
self.print_bounds("impl", bounds); self.print_bounds("impl", bounds);
} }
hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
hir::TyKind::TraitObject(bounds, lifetime, syntax) => { hir::TyKind::TraitObject(bounds, lifetime) => {
let syntax = lifetime.tag();
match syntax { match syntax {
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"), ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"), ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
@ -421,7 +422,7 @@ impl<'a> State<'a> {
if !lifetime.is_elided() { if !lifetime.is_elided() {
self.nbsp(); self.nbsp();
self.word_space("+"); self.word_space("+");
self.print_lifetime(lifetime); self.print_lifetime(lifetime.pointer());
} }
} }
hir::TyKind::Array(ty, ref length) => { hir::TyKind::Array(ty, ref length) => {
@ -441,7 +442,7 @@ impl<'a> State<'a> {
self.word("/*ERROR*/"); self.word("/*ERROR*/");
self.pclose(); self.pclose();
} }
hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => { hir::TyKind::Infer(()) | hir::TyKind::InferDelegation(..) => {
self.word("_"); self.word("_");
} }
hir::TyKind::Pat(ty, pat) => { hir::TyKind::Pat(ty, pat) => {
@ -1799,8 +1800,8 @@ impl<'a> State<'a> {
match generic_arg { match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
GenericArg::Lifetime(_) => {} GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => s.print_type(ty), GenericArg::Type(ty) => s.print_type(ty.as_unambig_ty()),
GenericArg::Const(ct) => s.print_const_arg(ct), GenericArg::Const(ct) => s.print_const_arg(ct.as_unambig_ct()),
GenericArg::Infer(_inf) => s.word("_"), GenericArg::Infer(_inf) => s.word("_"),
} }
}); });
@ -2150,7 +2151,7 @@ impl<'a> State<'a> {
s.ann.nested(s, Nested::BodyParamPat(body_id, i)); s.ann.nested(s, Nested::BodyParamPat(body_id, i));
i += 1; i += 1;
if let hir::TyKind::Infer = ty.kind { if let hir::TyKind::Infer(()) = ty.kind {
// Print nothing. // Print nothing.
} else { } else {
s.word(":"); s.word(":");

View file

@ -10,7 +10,7 @@ use rustc_hir as hir;
use rustc_hir::HirId; use rustc_hir::HirId;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::{InferKind, Visitor};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
@ -641,16 +641,21 @@ impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> {
impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
type Result = ControlFlow<errors::SuggestAnnotation>; type Result = ControlFlow<errors::SuggestAnnotation>;
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) -> Self::Result { fn visit_infer(
&mut self,
inf_id: HirId,
inf_span: Span,
_kind: InferKind<'tcx>,
) -> Self::Result {
// Try to replace `_` with `()`. // Try to replace `_` with `()`.
if let hir::TyKind::Infer = hir_ty.kind if let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(inf_id)
&& let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(hir_ty.hir_id)
&& let Some(vid) = self.fcx.root_vid(ty) && let Some(vid) = self.fcx.root_vid(ty)
&& self.reachable_vids.contains(&vid) && self.reachable_vids.contains(&vid)
{ {
return ControlFlow::Break(errors::SuggestAnnotation::Unit(hir_ty.span)); return ControlFlow::Break(errors::SuggestAnnotation::Unit(inf_span));
} }
hir::intravisit::walk_ty(self, hir_ty)
ControlFlow::Continue(())
} }
fn visit_qpath( fn visit_qpath(

View file

@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir, ExprKind, GenericArg, HirId, Node, QPath, intravisit}; use rustc_hir::{self as hir, AmbigArg, ExprKind, GenericArg, HirId, Node, QPath, intravisit};
use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend;
use rustc_hir_analysis::hir_ty_lowering::generics::{ use rustc_hir_analysis::hir_ty_lowering::generics::{
check_generic_arg_count_for_call, lower_generic_args, check_generic_arg_count_for_call, lower_generic_args,
@ -470,7 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> { impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id) if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id)
{ {
self.clauses.extend(clauses.iter().cloned()); self.clauses.extend(clauses.iter().cloned());
@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
let mut clauses = CollectClauses { clauses: vec![], fcx: self }; let mut clauses = CollectClauses { clauses: vec![], fcx: self };
clauses.visit_ty(hir_ty); clauses.visit_ty_unambig(hir_ty);
self.tcx.mk_clauses(&clauses.clauses) self.tcx.mk_clauses(&clauses.clauses)
} }
@ -1272,14 +1272,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.lower_lifetime(lt, RegionInferReason::Param(param)) .lower_lifetime(lt, RegionInferReason::Param(param))
.into(), .into(),
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.fcx.lower_ty(ty).raw.into() // We handle the ambig portions of `Ty` in match arm below
} self.fcx.lower_ty(ty.as_unambig_ty()).raw.into()
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.fcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.fcx.ty_infer(Some(param), inf.span).into() self.fcx.lower_ty(&inf.to_ty()).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
.fcx
// Ambiguous parts of `ConstArg` are handled in the match arms below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.into(),
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.fcx.ct_infer(Some(param), inf.span).into() self.fcx.ct_infer(Some(param), inf.span).into()
} }

View file

@ -251,7 +251,8 @@ fn typeck_with_inspect<'tcx>(
fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> { fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> {
let tcx = fcx.tcx; let tcx = fcx.tcx;
let def_id = fcx.body_id; let def_id = fcx.body_id;
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() { let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty()
{
if let Some(item) = tcx.opt_associated_item(def_id.into()) if let Some(item) = tcx.opt_associated_item(def_id.into())
&& let ty::AssocKind::Const = item.kind && let ty::AssocKind::Const = item.kind
&& let ty::AssocItemContainer::Impl = item.container && let ty::AssocItemContainer::Impl = item.container

View file

@ -425,14 +425,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
.lower_lifetime(lt, RegionInferReason::Param(param)) .lower_lifetime(lt, RegionInferReason::Param(param))
.into(), .into(),
(GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => {
self.cfcx.lower_ty(ty).raw.into() // We handle the ambig portions of `Ty` in the match arms below
} self.cfcx.lower_ty(ty.as_unambig_ty()).raw.into()
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
self.cfcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
} }
(GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => {
self.cfcx.ty_infer(Some(param), inf.span).into() self.cfcx.lower_ty(&inf.to_ty()).raw.into()
} }
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self
.cfcx
// We handle the ambig portions of `ConstArg` in the match arms below
.lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id))
.into(),
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
self.cfcx.ct_infer(Some(param), inf.span).into() self.cfcx.ct_infer(Some(param), inf.span).into()
} }

View file

@ -6,9 +6,8 @@ use std::mem;
use rustc_data_structures::unord::ExtendUnord; use rustc_data_structures::unord::ExtendUnord;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::HirId; use rustc_hir::{self as hir, AmbigArg, HirId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
@ -354,7 +353,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
self.write_ty_to_typeck_results(l.hir_id, var_ty); self.write_ty_to_typeck_results(l.hir_id, var_ty);
} }
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
intravisit::walk_ty(self, hir_ty); intravisit::walk_ty(self, hir_ty);
// If there are type checking errors, Type privacy pass will stop, // If there are type checking errors, Type privacy pass will stop,
// so we may not get the type from hid_id, see #104513 // so we may not get the type from hid_id, see #104513
@ -364,12 +363,20 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
} }
} }
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { fn visit_infer(
intravisit::walk_inf(self, inf); &mut self,
// Ignore cases where the inference is a const. inf_id: HirId,
if let Some(ty) = self.fcx.node_ty_opt(inf.hir_id) { inf_span: Span,
let ty = self.resolve(ty, &inf.span); _kind: InferKind<'cx>,
self.write_ty_to_typeck_results(inf.hir_id, ty); ) -> Self::Result {
self.visit_id(inf_id);
// We don't currently write inference results of const infer vars to
// the typeck results as there is not yet any part of the compiler that
// needs this information.
if let Some(ty) = self.fcx.node_ty_opt(inf_id) {
let ty = self.resolve(ty, &inf_span);
self.write_ty_to_typeck_results(inf_id, ty);
} }
} }
} }

View file

@ -5,8 +5,8 @@ use rustc_ast as ast;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{ use rustc_hir::{
BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind, AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
Path, PathSegment, QPath, Ty, TyKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
}; };
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
} }
} }
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) {
match &ty.kind { match &ty.kind {
TyKind::Path(QPath::Resolved(_, path)) => { TyKind::Path(QPath::Resolved(_, path)) => {
if lint_ty_kind_usage(cx, &path.res) { if lint_ty_kind_usage(cx, &path.res) {

View file

@ -8,9 +8,8 @@ use std::cell::Cell;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::join; use rustc_data_structures::sync::join;
use rustc_hir as hir;
use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_hir::{HirId, intravisit as hir_visit}; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
@ -214,15 +213,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
}) })
} }
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) {
lint_callback!(self, check_ty, t); lint_callback!(self, check_ty, t);
hir_visit::walk_ty(self, t); hir_visit::walk_ty(self, t);
} }
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) {
hir_visit::walk_inf(self, inf);
}
fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: HirId) { fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: HirId) {
if !self.context.only_module { if !self.context.only_module {
self.process_mod(m, n); self.process_mod(m, n);

View file

@ -9,6 +9,7 @@ use rustc_errors::{
}; };
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{self as hir, MissingLifetimeKind}; use rustc_hir::{self as hir, MissingLifetimeKind};
use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::inhabitedness::InhabitedPredicate; use rustc_middle::ty::inhabitedness::InhabitedPredicate;
@ -293,7 +294,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> {
// avoid doing throwaway work in case the lint ends up getting suppressed. // avoid doing throwaway work in case the lint ends up getting suppressed.
let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() }; let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() };
if let Some(ty) = self.ty { if let Some(ty) = self.ty {
hir::intravisit::Visitor::visit_ty(&mut collector, ty); collector.visit_ty_unambig(ty);
} }
let affect_object_lifetime_defaults = self let affect_object_lifetime_defaults = self

View file

@ -1,6 +1,6 @@
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::{declare_lint, impl_lint_pass}; use rustc_session::{declare_lint, impl_lint_pass};
@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
// 1. We collect all the `hir::Path` from the `Self` type and `Trait` ref // 1. We collect all the `hir::Path` from the `Self` type and `Trait` ref
// of the `impl` definition // of the `impl` definition
let mut collector = PathCollector { paths: Vec::new() }; let mut collector = PathCollector { paths: Vec::new() };
collector.visit_ty(&impl_.self_ty); collector.visit_ty_unambig(&impl_.self_ty);
if let Some(of_trait) = &impl_.of_trait { if let Some(of_trait) = &impl_.of_trait {
collector.visit_trait_ref(of_trait); collector.visit_trait_ref(of_trait);
} }

View file

@ -1,4 +1,4 @@
use rustc_hir as hir; use rustc_hir::{self as hir, AmbigArg};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_macros::{LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::fold::BottomUpFolder;
@ -67,7 +67,7 @@ declare_lint! {
declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx>) { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
let hir::TyKind::OpaqueDef(opaque) = &ty.kind else { let hir::TyKind::OpaqueDef(opaque) = &ty.kind else {
return; return;
}; };

View file

@ -1,6 +1,5 @@
use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym; use rustc_span::sym;
@ -22,7 +21,7 @@ declare_tool_lint! {
declare_lint_pass!(PassByValue => [PASS_BY_VALUE]); declare_lint_pass!(PassByValue => [PASS_BY_VALUE]);
impl<'tcx> LateLintPass<'tcx> for PassByValue { impl<'tcx> LateLintPass<'tcx> for PassByValue {
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
match &ty.kind { match &ty.kind {
TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => {
if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) {

View file

@ -25,7 +25,7 @@ macro_rules! late_lint_methods {
fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>); fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>);
fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>); fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>); fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>);
fn check_ty(a: &'tcx rustc_hir::Ty<'tcx>); fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>);
fn check_generic_param(a: &'tcx rustc_hir::GenericParam<'tcx>); fn check_generic_param(a: &'tcx rustc_hir::GenericParam<'tcx>);
fn check_generics(a: &'tcx rustc_hir::Generics<'tcx>); fn check_generics(a: &'tcx rustc_hir::Generics<'tcx>);
fn check_poly_trait_ref(a: &'tcx rustc_hir::PolyTraitRef<'tcx>); fn check_poly_trait_ref(a: &'tcx rustc_hir::PolyTraitRef<'tcx>);

View file

@ -1,4 +1,4 @@
use rustc_hir::{self as hir, LangItem}; use rustc_hir::{self as hir, AmbigArg, LangItem};
use rustc_session::{declare_lint, declare_lint_pass}; use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::sym; use rustc_span::sym;
@ -110,8 +110,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
} }
} }
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; let hir::TyKind::TraitObject(bounds, _lifetime_and_syntax_pointer) = &ty.kind else {
return;
};
for bound in &bounds[..] { for bound in &bounds[..] {
let def_id = bound.trait_ref.trait_def_id(); let def_id = bound.trait_ref.trait_def_id();
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) { if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) {

View file

@ -4,7 +4,8 @@ use std::ops::ControlFlow;
use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange}; use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagMessage; use rustc_errors::DiagMessage;
use rustc_hir::{Expr, ExprKind, LangItem}; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
use rustc_middle::ty::{ use rustc_middle::ty::{
@ -1526,7 +1527,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
} }
impl<'a, 'b, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'a, 'b, 'tcx> {
fn visit_ty(&mut self, ty: &'_ hir::Ty<'_>) { fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) {
debug!(?ty); debug!(?ty);
if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind
&& !self.visitor.is_internal_abi(*abi) && !self.visitor.is_internal_abi(*abi)
@ -1554,7 +1555,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
let mut visitor = FnPtrFinder { visitor: self, spans: Vec::new(), tys: Vec::new() }; let mut visitor = FnPtrFinder { visitor: self, spans: Vec::new(), tys: Vec::new() };
ty.visit_with(&mut visitor); ty.visit_with(&mut visitor);
hir::intravisit::Visitor::visit_ty(&mut visitor, hir_ty); visitor.visit_ty_unambig(hir_ty);
iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)).collect() iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)).collect()
} }

View file

@ -33,7 +33,7 @@ use rustc_errors::{
use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::definitions::Definitions; use rustc_hir::definitions::Definitions;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::VisitorExt;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate}; use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate};
use rustc_index::IndexVec; use rustc_index::IndexVec;
@ -2028,7 +2028,7 @@ impl<'tcx> TyCtxt<'tcx> {
}; };
let mut v = TraitObjectVisitor(vec![], self.hir()); let mut v = TraitObjectVisitor(vec![], self.hir());
v.visit_ty(hir_output); v.visit_ty_unambig(hir_output);
v.0 v.0
} }
@ -2050,7 +2050,7 @@ impl<'tcx> TyCtxt<'tcx> {
&& let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias
&& let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics() && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics()
{ {
v.visit_ty(alias_ty); v.visit_ty_unambig(alias_ty);
if !v.0.is_empty() { if !v.0.is_empty() {
return Some(( return Some((
v.0, v.0,

View file

@ -9,7 +9,7 @@ use rustc_errors::{
}; };
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind}; use rustc_hir::{self as hir, AmbigArg, LangItem, PredicateOrigin, WherePredicateKind};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
use rustc_type_ir::TyKind::*; use rustc_type_ir::TyKind::*;
@ -570,18 +570,18 @@ pub fn suggest_constraining_type_params<'a>(
pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>); pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>);
impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
match ty.kind { match ty.kind {
hir::TyKind::TraitObject( hir::TyKind::TraitObject(_, tagged_ptr)
_, if let hir::Lifetime {
hir::Lifetime {
res: res:
hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
.. ..
}, } = tagged_ptr.pointer() =>
_, {
) self.0.push(ty.as_unambig_ty())
| hir::TyKind::OpaqueDef(..) => self.0.push(ty), }
hir::TyKind::OpaqueDef(..) => self.0.push(ty.as_unambig_ty()),
_ => {} _ => {}
} }
hir::intravisit::walk_ty(self, ty); hir::intravisit::walk_ty(self, ty);

View file

@ -374,7 +374,13 @@ fn find_item_ty_spans(
if let hir::GenericArg::Type(ty) = arg if let hir::GenericArg::Type(ty) = arg
&& params_in_repr.contains(i as u32) && params_in_repr.contains(i as u32)
{ {
find_item_ty_spans(tcx, ty, needle, spans, seen_representable); find_item_ty_spans(
tcx,
ty.as_unambig_ty(),
needle,
spans,
seen_representable,
);
} }
} }
} }

View file

@ -2808,7 +2808,7 @@ fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool {
&& let Some(&[hir::GenericArg::Type(ty)]) = && let Some(&[hir::GenericArg::Type(ty)]) =
path.segments.last().map(|last| last.args().args) path.segments.last().map(|last| last.args().args)
{ {
doc_fake_variadic_is_allowed_self_ty(ty) doc_fake_variadic_is_allowed_self_ty(ty.as_unambig_ty())
} else { } else {
false false
}) })

View file

@ -460,7 +460,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
} }
// mark self_ty live // mark self_ty live
intravisit::walk_ty(self, impl_ref.self_ty); intravisit::walk_unambig_ty(self, impl_ref.self_ty);
if let Some(&impl_item_id) = if let Some(&impl_item_id) =
self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id)
{ {

View file

@ -5,8 +5,7 @@
use rustc_ast::visit::BoundKind; use rustc_ast::visit::BoundKind;
use rustc_ast::{self as ast, NodeId, visit as ast_visit}; use rustc_ast::{self as ast, NodeId, visit as ast_visit};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
use rustc_hir::{HirId, intravisit as hir_visit};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_middle::util::common::to_readable_str; use rustc_middle::util::common::to_readable_str;
@ -363,7 +362,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir_visit::walk_expr_field(self, f) hir_visit::walk_expr_field(self, f)
} }
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { fn visit_ty(&mut self, t: &'v hir::Ty<'v, AmbigArg>) {
record_variants!((self, t, t.kind, Some(t.hir_id), hir, Ty, TyKind), [ record_variants!((self, t, t.kind, Some(t.hir_id), hir, Ty, TyKind), [
InferDelegation, InferDelegation,
Slice, Slice,
@ -476,7 +475,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt), hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
hir::GenericArg::Type(ty) => self.visit_ty(ty), hir::GenericArg::Type(ty) => self.visit_ty(ty),
hir::GenericArg::Const(ct) => self.visit_const_arg(ct), hir::GenericArg::Const(ct) => self.visit_const_arg(ct),
hir::GenericArg::Infer(inf) => self.visit_infer(inf), hir::GenericArg::Infer(inf) => self.visit_id(inf.hir_id),
} }
} }

View file

@ -11,12 +11,11 @@ use rustc_attr_parsing::{
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature}; use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_hir::{self as hir, AmbigArg, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::middle::privacy::EffectiveVisibilities;
@ -802,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
)) = stab )) = stab
{ {
let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true }; let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
c.visit_ty(self_ty); c.visit_ty_unambig(self_ty);
c.visit_trait_ref(t); c.visit_trait_ref(t);
// do not lint when the trait isn't resolved, since resolution error should // do not lint when the trait isn't resolved, since resolution error should
@ -1028,7 +1027,7 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
intravisit::walk_trait_ref(self, t) intravisit::walk_trait_ref(self, t)
} }
fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { fn visit_ty(&mut self, t: &'tcx Ty<'tcx, AmbigArg>) {
if let TyKind::Never = t.kind { if let TyKind::Never = t.kind {
self.fully_stable = false; self.fully_stable = false;
} }
@ -1042,12 +1041,12 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) { fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
for ty in fd.inputs { for ty in fd.inputs {
self.visit_ty(ty) self.visit_ty_unambig(ty)
} }
if let hir::FnRetTy::Return(output_ty) = fd.output { if let hir::FnRetTy::Return(output_ty) = fd.output {
match output_ty.kind { match output_ty.kind {
TyKind::Never => {} // `-> !` is stable TyKind::Never => {} // `-> !` is stable
_ => self.visit_ty(output_ty), _ => self.visit_ty_unambig(output_ty),
} }
} }
} }

View file

@ -27,8 +27,8 @@ use rustc_data_structures::intern::Interned;
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, InferKind, Visitor};
use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; use rustc_hir::{AmbigArg, AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::print::PrintTraitRefExt as _;
@ -1179,7 +1179,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
self.maybe_typeck_results = old_maybe_typeck_results; self.maybe_typeck_results = old_maybe_typeck_results;
} }
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
self.span = hir_ty.span; self.span = hir_ty.span;
if self if self
.visit( .visit(
@ -1195,12 +1195,17 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
intravisit::walk_ty(self, hir_ty); intravisit::walk_ty(self, hir_ty);
} }
fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { fn visit_infer(
self.span = inf.span; &mut self,
inf_id: rustc_hir::HirId,
inf_span: Span,
_kind: InferKind<'tcx>,
) -> Self::Result {
self.span = inf_span;
if let Some(ty) = self if let Some(ty) = self
.maybe_typeck_results .maybe_typeck_results
.unwrap_or_else(|| span_bug!(inf.span, "`hir::InferArg` outside of a body")) .unwrap_or_else(|| span_bug!(inf_span, "Inference variable outside of a body"))
.node_type_opt(inf.hir_id) .node_type_opt(inf_id)
{ {
if self.visit(ty).is_break() { if self.visit(ty).is_break() {
return; return;
@ -1208,7 +1213,8 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
} else { } else {
// FIXME: check types of const infers here. // FIXME: check types of const infers here.
} }
intravisit::walk_inf(self, inf);
self.visit_id(inf_id)
} }
// Check types of expressions // Check types of expressions

View file

@ -1,8 +1,8 @@
use core::ops::ControlFlow; use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor, VisitorExt};
use rustc_hir::{self as hir, AmbigArg};
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::middle::resolve_bound_vars as rbv;
@ -48,7 +48,7 @@ fn find_component_for_bound_region<'tcx>(
region_def_id: DefId, region_def_id: DefId,
) -> Option<&'tcx hir::Ty<'tcx>> { ) -> Option<&'tcx hir::Ty<'tcx>> {
FindNestedTypeVisitor { tcx, region_def_id, current_index: ty::INNERMOST } FindNestedTypeVisitor { tcx, region_def_id, current_index: ty::INNERMOST }
.visit_ty(arg) .visit_ty_unambig(arg)
.break_value() .break_value()
} }
@ -74,7 +74,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
self.tcx.hir() self.tcx.hir()
} }
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
match arg.kind { match arg.kind {
hir::TyKind::BareFn(_) => { hir::TyKind::BareFn(_) => {
self.current_index.shift_in(1); self.current_index.shift_in(1);
@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
Some(rbv::ResolvedArg::EarlyBound(id)) => { Some(rbv::ResolvedArg::EarlyBound(id)) => {
debug!("EarlyBound id={:?}", id); debug!("EarlyBound id={:?}", id);
if id.to_def_id() == self.region_def_id { if id.to_def_id() == self.region_def_id {
return ControlFlow::Break(arg); return ControlFlow::Break(arg.as_unambig_ty());
} }
} }
@ -117,7 +117,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
if debruijn_index == self.current_index if debruijn_index == self.current_index
&& id.to_def_id() == self.region_def_id && id.to_def_id() == self.region_def_id
{ {
return ControlFlow::Break(arg); return ControlFlow::Break(arg.as_unambig_ty());
} }
} }
@ -147,7 +147,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
) )
.is_break() .is_break()
{ {
ControlFlow::Break(arg) ControlFlow::Break(arg.as_unambig_ty())
} else { } else {
ControlFlow::Continue(()) ControlFlow::Continue(())
}; };
@ -210,7 +210,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
ControlFlow::Continue(()) ControlFlow::Continue(())
} }
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result {
// ignore nested types // ignore nested types
// //
// If you have a type like `Foo<'a, &Ty>` we // If you have a type like `Foo<'a, &Ty>` we

View file

@ -4,7 +4,7 @@
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_errors::{ErrorGuaranteed, MultiSpan};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::VisitorExt;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::TypeVisitor;
use tracing::debug; use tracing::debug;
@ -87,7 +87,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
for matching_def_id in v.0 { for matching_def_id in v.0 {
let mut hir_v = let mut hir_v =
super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id); super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id);
hir_v.visit_ty(impl_self_ty); hir_v.visit_ty_unambig(impl_self_ty);
} }
if traits.is_empty() { if traits.is_empty() {

View file

@ -3,9 +3,9 @@
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{Visitor, walk_ty}; use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
use rustc_hir::{ use rustc_hir::{
self as hir, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime,
LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{
@ -153,7 +153,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let mut add_label = true; let mut add_label = true;
if let hir::FnRetTy::Return(ty) = fn_decl.output { if let hir::FnRetTy::Return(ty) = fn_decl.output {
let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
v.visit_ty(ty); v.visit_ty_unambig(ty);
if !v.0.is_empty() { if !v.0.is_empty() {
span = v.0.clone().into(); span = v.0.clone().into();
spans = v.0; spans = v.0;
@ -374,7 +374,7 @@ pub fn suggest_new_region_bound(
} }
} }
} }
TyKind::TraitObject(_, lt, _) => { TyKind::TraitObject(_, lt) => {
if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res { if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res {
err.span_suggestion_verbose( err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(), fn_return.span.shrink_to_hi(),
@ -500,7 +500,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// In that case, only the first one will get suggestions. // In that case, only the first one will get suggestions.
let mut traits = vec![]; let mut traits = vec![];
let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
hir_v.visit_ty(self_ty); hir_v.visit_ty_unambig(self_ty);
!traits.is_empty() !traits.is_empty()
}) })
{ {
@ -560,7 +560,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
for found_did in found_dids { for found_did in found_dids {
let mut traits = vec![]; let mut traits = vec![];
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
hir_v.visit_ty(self_ty); hir_v.visit_ty_unambig(self_ty);
for &span in &traits { for &span in &traits {
let subdiag = DynTraitConstraintSuggestion { span, ident }; let subdiag = DynTraitConstraintSuggestion { span, ident };
subdiag.add_to_diag(err); subdiag.add_to_diag(err);
@ -591,12 +591,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor {
pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId); pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let TyKind::TraitObject( if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind
poly_trait_refs, && let Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. } =
Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. }, lifetime_ptr.pointer()
_,
) = t.kind
{ {
for ptr in poly_trait_refs { for ptr in poly_trait_refs {
if Some(self.1) == ptr.trait_ref.trait_def_id() { if Some(self.1) == ptr.trait_ref.trait_def_id() {

View file

@ -1,10 +1,10 @@
//! Error Reporting for `impl` items that do not match the obligations from their `trait`. //! Error Reporting for `impl` items that do not match the obligations from their `trait`.
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{Namespace, Res}; use rustc_hir::def::{Namespace, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::{Visitor, walk_ty};
use rustc_hir::{self as hir, AmbigArg};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::traits::ObligationCauseCode; use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::ExpectedFound;
@ -137,11 +137,13 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
self.tcx.hir() self.tcx.hir()
} }
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) {
match arg.kind { match arg.kind {
hir::TyKind::Ref(_, ref mut_ty) => { hir::TyKind::Ref(_, ref mut_ty) => {
// We don't want to suggest looking into borrowing `&T` or `&Self`. // We don't want to suggest looking into borrowing `&T` or `&Self`.
hir::intravisit::walk_ty(self, mut_ty.ty); if let Some(ambig_ty) = mut_ty.ty.try_as_ambig_ty() {
walk_ty(self, ambig_ty);
}
return; return;
} }
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {

View file

@ -655,7 +655,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&& let ty::Ref(found_region, _, _) = found.kind() && let ty::Ref(found_region, _, _) = found.kind()
&& expected_region.is_bound() && expected_region.is_bound()
&& !found_region.is_bound() && !found_region.is_bound()
&& let hir::TyKind::Infer = arg_hir.kind && let hir::TyKind::Infer(()) = arg_hir.kind
{ {
// If the expected region is late bound, the found region is not, and users are asking compiler // If the expected region is late bound, the found region is not, and users are asking compiler
// to infer the type, we can suggest adding `: &_`. // to infer the type, we can suggest adding `: &_`.

View file

@ -580,8 +580,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
self.tcx.hir_node_by_def_id(obligation.cause.body_id) self.tcx.hir_node_by_def_id(obligation.cause.body_id)
&& let hir::ItemKind::Impl(impl_) = item.kind && let hir::ItemKind::Impl(impl_) = item.kind
&& let None = impl_.of_trait && let None = impl_.of_trait
&& let hir::TyKind::TraitObject(_, _, syntax) = impl_.self_ty.kind && let hir::TyKind::TraitObject(_, tagged_ptr) = impl_.self_ty.kind
&& let TraitObjectSyntax::None = syntax && let TraitObjectSyntax::None = tagged_ptr.tag()
&& impl_.self_ty.span.edition().at_least_rust_2021() && impl_.self_ty.span.edition().at_least_rust_2021()
{ {
// Silence the dyn-compatibility error in favor of the missing dyn on // Silence the dyn-compatibility error in favor of the missing dyn on

View file

@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, LangItem}; use rustc_hir::{self as hir, AmbigArg, LangItem};
use rustc_infer::traits::{ use rustc_infer::traits::{
DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode, DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode,
PredicateObligation, SelectionError, PredicateObligation, SelectionError,
@ -87,9 +87,9 @@ impl<'v> Visitor<'v> for FindExprBySpan<'v> {
} }
} }
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
if self.span == ty.span { if self.span == ty.span {
self.ty_result = Some(ty); self.ty_result = Some(ty.as_unambig_ty());
} else { } else {
hir::intravisit::walk_ty(self, ty); hir::intravisit::walk_ty(self, ty);
} }

View file

@ -14,14 +14,13 @@ use rustc_errors::{
Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize, Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize,
struct_span_code_err, struct_span_code_err,
}; };
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::{Visitor, VisitorExt};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ use rustc_hir::{
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, expr_needs_parens, self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node,
is_range_literal, expr_needs_parens, is_range_literal,
}; };
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_middle::hir::map; use rustc_middle::hir::map;
@ -179,7 +178,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>(
let mut ty_spans = vec![]; let mut ty_spans = vec![];
for input in fn_sig.decl.inputs { for input in fn_sig.decl.inputs {
ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id } ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id }
.visit_ty(input); .visit_ty_unambig(input);
} }
// The type param `T: Trait` we will suggest to introduce. // The type param `T: Trait` we will suggest to introduce.
let type_param = format!("{type_param_name}: {bound_str}"); let type_param = format!("{type_param_name}: {bound_str}");
@ -3074,7 +3073,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
} }
if let Some(ty) = ty { if let Some(ty) = ty {
match ty.kind { match ty.kind {
hir::TyKind::TraitObject(traits, _, _) => { hir::TyKind::TraitObject(traits, _) => {
let (span, kw) = match traits { let (span, kw) = match traits {
[first, ..] if first.span.lo() == ty.span.lo() => { [first, ..] if first.span.lo() == ty.span.lo() => {
// Missing `dyn` in front of trait object. // Missing `dyn` in front of trait object.
@ -5065,7 +5064,7 @@ pub struct SelfVisitor<'v> {
} }
impl<'v> Visitor<'v> for SelfVisitor<'v> { impl<'v> Visitor<'v> for SelfVisitor<'v> {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
if let hir::TyKind::Path(path) = ty.kind if let hir::TyKind::Path(path) = ty.kind
&& let hir::QPath::TypeRelative(inner_ty, segment) = path && let hir::QPath::TypeRelative(inner_ty, segment) = path
&& (Some(segment.ident.name) == self.name || self.name.is_none()) && (Some(segment.ident.name) == self.name || self.name.is_none())
@ -5073,7 +5072,7 @@ impl<'v> Visitor<'v> for SelfVisitor<'v> {
&& let hir::QPath::Resolved(None, inner_path) = inner_path && let hir::QPath::Resolved(None, inner_path) = inner_path
&& let Res::SelfTyAlias { .. } = inner_path.res && let Res::SelfTyAlias { .. } = inner_path.res
{ {
self.paths.push(ty); self.paths.push(ty.as_unambig_ty());
} }
hir::intravisit::walk_ty(self, ty); hir::intravisit::walk_ty(self, ty);
} }
@ -5187,7 +5186,7 @@ struct ReplaceImplTraitVisitor<'a> {
} }
impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> { impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> {
fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) { fn visit_ty(&mut self, t: &'hir hir::Ty<'hir, AmbigArg>) {
if let hir::TyKind::Path(hir::QPath::Resolved( if let hir::TyKind::Path(hir::QPath::Resolved(
None, None,
hir::Path { res: Res::Def(_, segment_did), .. }, hir::Path { res: Res::Def(_, segment_did), .. },
@ -5480,7 +5479,7 @@ impl<'v> Visitor<'v> for FindTypeParam {
// Skip where-clauses, to avoid suggesting indirection for type parameters found there. // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
} }
fn visit_ty(&mut self, ty: &hir::Ty<'_>) { fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) {
// We collect the spans of all uses of the "bare" type param, like in `field: T` or // We collect the spans of all uses of the "bare" type param, like in `field: T` or
// `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
// valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized` // valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized`

View file

@ -6,11 +6,10 @@ use rustc_errors::{
Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic,
EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
}; };
use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{Visitor, walk_ty}; use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty};
use rustc_hir::{FnRetTy, GenericParamKind, Node}; use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node};
use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath};
use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt}; use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt};
@ -579,7 +578,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
} }
impl<'v> Visitor<'v> for ImplicitLifetimeFinder { impl<'v> Visitor<'v> for ImplicitLifetimeFinder {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) {
let make_suggestion = |ident: Ident| { let make_suggestion = |ident: Ident| {
if ident.name == kw::Empty && ident.span.is_empty() { if ident.name == kw::Empty && ident.span.is_empty() {
format!("{}, ", self.suggestion_param_name) format!("{}, ", self.suggestion_param_name)
@ -642,16 +641,16 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
if let Some(fn_decl) = node.fn_decl() if let Some(fn_decl) = node.fn_decl()
&& let hir::FnRetTy::Return(ty) = fn_decl.output && let hir::FnRetTy::Return(ty) = fn_decl.output
{ {
visitor.visit_ty(ty); visitor.visit_ty_unambig(ty);
} }
if visitor.suggestions.is_empty() { if visitor.suggestions.is_empty() {
// Do not suggest constraining the `&self` param, but rather the return type. // Do not suggest constraining the `&self` param, but rather the return type.
// If that is wrong (because it is not sufficient), a follow up error will tell the // If that is wrong (because it is not sufficient), a follow up error will tell the
// user to fix it. This way we lower the chances of *over* constraining, but still // user to fix it. This way we lower the chances of *over* constraining, but still
// get the cake of "correctly" contrained in two steps. // get the cake of "correctly" contrained in two steps.
visitor.visit_ty(self.ty_sup); visitor.visit_ty_unambig(self.ty_sup);
} }
visitor.visit_ty(self.ty_sub); visitor.visit_ty_unambig(self.ty_sub);
if visitor.suggestions.is_empty() { if visitor.suggestions.is_empty() {
return false; return false;
} }

View file

@ -1,8 +1,8 @@
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, AmbigArg};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
@ -187,7 +187,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
} }
impl<'tcx> Visitor<'tcx> for RPITVisitor { impl<'tcx> Visitor<'tcx> for RPITVisitor {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
if let hir::TyKind::OpaqueDef(opaq) = ty.kind if let hir::TyKind::OpaqueDef(opaq) = ty.kind
&& self.rpits.insert(opaq.def_id) && self.rpits.insert(opaq.def_id)
{ {

View file

@ -1747,9 +1747,9 @@ fn maybe_expand_private_type_alias<'tcx>(
}; };
let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
let provided_params = &path.segments.last().expect("segments were empty"); let final_seg = &path.segments.last().expect("segments were empty");
let mut args = DefIdMap::default(); let mut args = DefIdMap::default();
let generic_args = provided_params.args(); let generic_args = final_seg.args();
let mut indices: hir::GenericParamCount = Default::default(); let mut indices: hir::GenericParamCount = Default::default();
for param in generics.params.iter() { for param in generics.params.iter() {
@ -1781,7 +1781,7 @@ fn maybe_expand_private_type_alias<'tcx>(
let type_ = generic_args.args.iter().find_map(|arg| match arg { let type_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Type(ty) => { hir::GenericArg::Type(ty) => {
if indices.types == j { if indices.types == j {
return Some(*ty); return Some(ty.as_unambig_ty());
} }
j += 1; j += 1;
None None
@ -1843,10 +1843,13 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
} }
TyKind::Path(_) => clean_qpath(ty, cx), TyKind::Path(_) => clean_qpath(ty, cx),
TyKind::TraitObject(bounds, lifetime, _) => { TyKind::TraitObject(bounds, lifetime) => {
let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect();
let lifetime = let lifetime = if !lifetime.is_elided() {
if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None }; Some(clean_lifetime(lifetime.pointer(), cx))
} else {
None
};
DynTrait(bounds, lifetime) DynTrait(bounds, lifetime)
} }
TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))),
@ -1854,7 +1857,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx))) UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx)))
} }
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer TyKind::Infer(())
| TyKind::Err(_) | TyKind::Err(_)
| TyKind::Typeof(..) | TyKind::Typeof(..)
| TyKind::InferDelegation(..) | TyKind::InferDelegation(..)
@ -2533,8 +2536,10 @@ fn clean_generic_args<'tcx>(
GenericArg::Lifetime(clean_lifetime(lt, cx)) GenericArg::Lifetime(clean_lifetime(lt, cx))
} }
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)),
hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), hir::GenericArg::Const(ct) => {
GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx)))
}
hir::GenericArg::Infer(_inf) => GenericArg::Infer, hir::GenericArg::Infer(_inf) => GenericArg::Infer,
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()

View file

@ -598,8 +598,13 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> {
// Unneeded. // Unneeded.
} }
fn visit_infer(&mut self, _: &hir::InferArg) { fn visit_infer(
// Unneeded. &mut self,
_inf_id: hir::HirId,
_inf_span: Span,
_kind: hir::intravisit::InferKind<'tcx>,
) -> Self::Result {
// Unneeded
} }
fn visit_lifetime(&mut self, _: &hir::Lifetime) { fn visit_lifetime(&mut self, _: &hir::Lifetime) {

View file

@ -4,12 +4,12 @@ use clippy_utils::ty::expr_sig;
use clippy_utils::{is_default_equivalent, path_def_id}; use clippy_utils::{is_default_equivalent, path_def_id};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::intravisit::{Visitor, walk_ty}; use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind}; use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::sym; use rustc_span::{Span, sym};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -92,8 +92,13 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>)
struct InferVisitor(bool); struct InferVisitor(bool);
impl Visitor<'_> for InferVisitor { impl Visitor<'_> for InferVisitor {
fn visit_ty(&mut self, t: &Ty<'_>) { fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, _kind: InferKind<'_>) -> Self::Result {
self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..)); 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 { if !self.0 {
walk_ty(self, t); 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) { match cx.tcx.parent_hir_node(expr.hir_id) {
Node::LetStmt(LetStmt { ty: Some(ty), .. }) => { Node::LetStmt(LetStmt { ty: Some(ty), .. }) => {
let mut v = InferVisitor::default(); let mut v = InferVisitor::default();
v.visit_ty(ty); v.visit_ty_unambig(ty);
!v.0 !v.0
}, },
Node::Expr(Expr { Node::Expr(Expr {

View file

@ -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>) { 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 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( clippy_utils::diagnostics::span_lint_and_sugg(
cx, cx,

View file

@ -7,7 +7,7 @@ use rustc_middle::ty;
use super::AS_UNDERSCORE; use super::AS_UNDERSCORE;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ty: &'tcx Ty<'_>) { 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| { span_lint_and_then(cx, AS_UNDERSCORE, expr.span, "using `as _` conversion", |diag| {
let ty_resolved = cx.typeck_results().expr_ty(expr); let ty_resolved = cx.typeck_results().expr_ty(expr);
if let ty::Error(_) = ty_resolved.kind() { if let ty::Error(_) = ty_resolved.kind() {

View file

@ -38,7 +38,7 @@ pub(super) fn check(
return; return;
}; };
match cast_to_hir.kind { match cast_to_hir.kind {
TyKind::Infer => { TyKind::Infer(()) => {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(
expr.span, expr.span,
"use `Into::into` instead", "use `Into::into` instead",

View file

@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
&& let Some(generic_args) = method_path.args && let Some(generic_args) = method_path.args
&& let [GenericArg::Type(cast_to)] = generic_args.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. // 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)); 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); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);

View file

@ -43,9 +43,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
{ {
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
let turbofish = match &cast_to_hir_ty.kind { let turbofish = match &cast_to_hir_ty.kind {
TyKind::Infer => String::new(), TyKind::Infer(()) => String::new(),
TyKind::Ptr(mut_ty) => { TyKind::Ptr(mut_ty) => {
if matches!(mut_ty.ty.kind, TyKind::Infer) { if matches!(mut_ty.ty.kind, TyKind::Infer(())) {
String::new() String::new()
} else { } else {
format!( format!(

View file

@ -34,9 +34,9 @@ pub(super) fn check<'tcx>(
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
let turbofish = match &cast_to_hir_ty.kind { let turbofish = match &cast_to_hir_ty.kind {
TyKind::Infer => String::new(), TyKind::Infer(()) => String::new(),
TyKind::Ptr(mut_ty) => { TyKind::Ptr(mut_ty) => {
if matches!(mut_ty.ty.kind, TyKind::Infer) { if matches!(mut_ty.ty.kind, TyKind::Infer(())) {
String::new() String::new()
} else { } else {
format!( format!(

View file

@ -43,7 +43,7 @@ pub(super) fn check<'tcx>(
} }
}, },
// Ignore `p as *const _` // Ignore `p as *const _`
TyKind::Infer => return false, TyKind::Infer(()) => return false,
_ => {}, _ => {},
} }

View file

@ -18,7 +18,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>
Mutability::Not => ("`0 as *const _` detected", "ptr::null"), 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}()") format!("{std_or_core}::{sugg_fn}()")
} else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) { } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) {
format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()")

View file

@ -11,10 +11,10 @@ use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def_id::DefId; 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::{ use rustc_hir::{
self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, self as hir, AmbigArg, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node,
PatKind, Path, QPath, TyKind, UnOp, Pat, PatKind, Path, QPath, TyKind, UnOp,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
@ -796,7 +796,7 @@ impl TyCoercionStability {
if let Some(args) = path.args if let Some(args) = path.args
&& args.args.iter().any(|arg| match arg { && args.args.iter().any(|arg| match arg {
hir::GenericArg::Infer(_) => true, hir::GenericArg::Infer(_) => true,
hir::GenericArg::Type(ty) => ty_contains_infer(ty), hir::GenericArg::Type(ty) => ty_contains_infer(ty.as_unambig_ty()),
_ => false, _ => false,
}) })
{ {
@ -815,7 +815,7 @@ impl TyCoercionStability {
| TyKind::Path(_) => Self::Deref, | TyKind::Path(_) => Self::Deref,
TyKind::OpaqueDef(..) TyKind::OpaqueDef(..)
| TyKind::TraitAscription(..) | TyKind::TraitAscription(..)
| TyKind::Infer | TyKind::Infer(())
| TyKind::Typeof(..) | TyKind::Typeof(..)
| TyKind::TraitObject(..) | TyKind::TraitObject(..)
| TyKind::InferDelegation(..) | TyKind::InferDelegation(..)
@ -889,29 +889,23 @@ impl TyCoercionStability {
fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool { fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
struct V(bool); struct V(bool);
impl Visitor<'_> for V { impl Visitor<'_> for V {
fn visit_ty(&mut self, ty: &hir::Ty<'_>) { fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result {
if self.0 if let InferKind::Ty(_) | InferKind::Ambig(_) = kind {
|| matches!( self.0 = true;
ty.kind, }
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_) 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; self.0 = true;
} else { } else {
walk_ty(self, ty); 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); let mut v = V(false);
v.visit_ty(ty); v.visit_ty_unambig(ty);
v.0 v.0
} }

View file

@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Diag; use rustc_errors::Diag;
use rustc_hir::def_id::DefIdMap; use rustc_hir::def_id::DefIdMap;
use rustc_hir::{ 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_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
@ -140,7 +140,7 @@ impl LateLintPass<'_> for DisallowedMacros {
self.check(cx, stmt.span, None); 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); self.check(cx, ty.span, None);
} }

View file

@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::DefIdMap; 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_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass; 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 { if let TyKind::Path(path) = &ty.kind {
self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span); self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
} }

View file

@ -76,22 +76,22 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
if let ExprKind::MethodCall(_method, receiver, args, _) = expr.kind { if let ExprKind::MethodCall(_method, receiver, args, _) = expr.kind {
for arg in args { for arg in args {
check_clousure(cx, Some(receiver), arg); check_closure(cx, Some(receiver), arg);
} }
} }
if let ExprKind::Call(func, args) = expr.kind { if let ExprKind::Call(func, args) = expr.kind {
check_clousure(cx, None, func); check_closure(cx, None, func);
for arg in args { for arg in args {
check_clousure(cx, None, arg); check_closure(cx, None, arg);
} }
} }
} }
} }
#[allow(clippy::too_many_lines)] #[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 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(_)) && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_))
&& !expr.span.from_expansion() && !expr.span.from_expansion()
{ {

View file

@ -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 clippy_utils::{is_from_proc_macro, trait_ref_of_method};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability; 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::{ use rustc_hir::{
BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, AmbigArg, BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item,
PredicateOrigin, Ty, WherePredicate, WherePredicateKind, ItemKind, PredicateOrigin, Ty, WherePredicate, WherePredicateKind,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter; 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> { impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies; 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() { if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
self.ty_params.remove(&def_id); self.ty_params.remove(&def_id);
} else { } 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, // 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 // and can therefore can be considered used. So, we're fine to walk the left-hand
// side of the where bound. // side of the where bound.
walk_ty(self, predicate.bounded_ty); walk_unambig_ty(self, predicate.bounded_ty);
} }
for bound in predicate.bounds { for bound in predicate.bounds {
walk_param_bound(self, bound); walk_param_bound(self, bound);

View file

@ -103,7 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
"replace the `Into` implementation with `From<{}>`", "replace the `Into` implementation with `From<{}>`",
middle_trait_ref.self_ty() 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); diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
} else { } else {
diag.help(message); diag.help(message);

View file

@ -2,9 +2,8 @@ use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use rustc_errors::{Applicability, Diag}; use rustc_errors::{Applicability, Diag};
use rustc_hir as hir; use rustc_hir::intravisit::{Visitor, VisitorExt, walk_body, walk_expr, walk_ty};
use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty}; use rustc_hir::{self as hir, AmbigArg, Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
use rustc_hir_analysis::lower_ty; use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
match item.kind { match item.kind {
ItemKind::Impl(impl_) => { ItemKind::Impl(impl_) => {
let mut vis = ImplicitHasherTypeVisitor::new(cx); let mut vis = ImplicitHasherTypeVisitor::new(cx);
vis.visit_ty(impl_.self_ty); vis.visit_ty_unambig(impl_.self_ty);
for target in &vis.found { for target in &vis.found {
if !item.span.eq_ctxt(target.span()) { if !item.span.eq_ctxt(target.span()) {
@ -159,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
for ty in sig.decl.inputs { for ty in sig.decl.inputs {
let mut vis = ImplicitHasherTypeVisitor::new(cx); let mut vis = ImplicitHasherTypeVisitor::new(cx);
vis.visit_ty(ty); vis.visit_ty_unambig(ty);
for target in &vis.found { for target in &vis.found {
if generics.span.from_expansion() { if generics.span.from_expansion() {
@ -287,21 +286,13 @@ impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> {
} }
impl<'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'_, 'tcx> {
fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { fn visit_ty(&mut self, t: &'tcx hir::Ty<'_, AmbigArg>) {
if let Some(target) = ImplicitHasherType::new(self.cx, t) { if let Some(target) = ImplicitHasherType::new(self.cx, t.as_unambig_ty()) {
self.found.push(target); self.found.push(target);
} }
walk_ty(self, t); 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`. /// Looks for default-hasher-dependent constructors like `HashMap::new`.

View file

@ -3,8 +3,8 @@ use clippy_utils::source::snippet;
use rustc_errors::{Applicability, SuggestionStyle}; use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{ use rustc_hir::{
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind, AmbigArg, AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers,
WherePredicateKind, TyKind, WherePredicateKind,
}; };
use rustc_hir_analysis::lower_ty; use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -146,7 +146,9 @@ fn try_resolve_type<'tcx>(
index: usize, index: usize,
) -> Option<Ty<'tcx>> { ) -> Option<Ty<'tcx>> {
match args.get(index - 1) { 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, Some(_) => None,
None => Some(tcx.type_of(generics.own_params[index].def_id).skip_binder()), 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 { if let TyKind::OpaqueDef(opaque_ty, ..) = ty.kind {
check(cx, opaque_ty.bounds); check(cx, opaque_ty.bounds);
} }

View file

@ -28,7 +28,7 @@ declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]);
impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped { impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped {
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
if let Some(ty) = local.ty // Ensure that it has a type defined 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) && local.span.eq_ctxt(ty.span)
&& !in_external_macro(cx.tcx.sess, local.span) && !in_external_macro(cx.tcx.sess, local.span)
&& !is_from_proc_macro(cx, ty) && !is_from_proc_macro(cx, ty)

View file

@ -7,13 +7,13 @@ use rustc_errors::Applicability;
use rustc_hir::FnRetTy::Return; use rustc_hir::FnRetTy::Return;
use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter};
use rustc_hir::intravisit::{ use rustc_hir::intravisit::{
Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref, Visitor, VisitorExt, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound,
walk_trait_ref, walk_ty, walk_where_predicate, walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, walk_where_predicate,
}; };
use rustc_hir::{ use rustc_hir::{
BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind,
HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node,
PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate,
WherePredicateKind, lang_items, WherePredicateKind, lang_items,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
@ -232,11 +232,11 @@ fn could_use_elision<'tcx>(
// extract lifetimes in input argument types // extract lifetimes in input argument types
for arg in func.inputs { for arg in func.inputs {
input_visitor.visit_ty(arg); input_visitor.visit_ty_unambig(arg);
} }
// extract lifetimes in output type // extract lifetimes in output type
if let Return(ty) = func.output { if let Return(ty) = func.output {
output_visitor.visit_ty(ty); output_visitor.visit_ty_unambig(ty);
} }
for lt in named_generics { for lt in named_generics {
input_visitor.visit_generic_param(lt); 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 Some(self_ty) = func.inputs.first()
{ {
let mut visitor = RefVisitor::new(cx); let mut visitor = RefVisitor::new(cx);
visitor.visit_ty(self_ty); visitor.visit_ty_unambig(self_ty);
!visitor.all_lts().is_empty() !visitor.all_lts().is_empty()
} else { } 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 { match ty.kind {
TyKind::BareFn(&BareFnTy { decl, .. }) => { TyKind::BareFn(&BareFnTy { decl, .. }) => {
let mut sub_visitor = RefVisitor::new(self.cx); let mut sub_visitor = RefVisitor::new(self.cx);
sub_visitor.visit_fn_decl(decl); sub_visitor.visit_fn_decl(decl);
self.nested_elision_site_lts.append(&mut sub_visitor.all_lts()); self.nested_elision_site_lts.append(&mut sub_visitor.all_lts());
}, },
TyKind::TraitObject(bounds, lt, _) => { TyKind::TraitObject(bounds, lt) => {
if !lt.is_elided() { if !lt.is_elided() {
self.unelided_trait_object_lifetime = true; 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> // a predicate like F: Trait or F: for<'a> Trait<'a>
let mut visitor = RefVisitor::new(cx); let mut visitor = RefVisitor::new(cx);
// walk the type F, it may not contain LT refs // 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() { if !visitor.all_lts().is_empty() {
return true; return true;
} }
@ -477,8 +477,8 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_
}, },
WherePredicateKind::EqPredicate(ref pred) => { WherePredicateKind::EqPredicate(ref pred) => {
let mut visitor = RefVisitor::new(cx); let mut visitor = RefVisitor::new(cx);
walk_ty(&mut visitor, pred.lhs_ty); walk_unambig_ty(&mut visitor, pred.lhs_ty);
walk_ty(&mut visitor, pred.rhs_ty); walk_unambig_ty(&mut visitor, pred.rhs_ty);
if !visitor.lts.is_empty() { if !visitor.lts.is_empty() {
return true; return true;
} }
@ -541,7 +541,7 @@ where
try_visit!(self.visit_id(hir_id)); try_visit!(self.visit_id(hir_id));
self.bounded_ty_depth += 1; 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; self.bounded_ty_depth -= 1;
walk_list!(self, visit_param_bound, bounds); 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 { if let Some(ref trait_ref) = impl_.of_trait {
walk_trait_ref(&mut checker, trait_ref); 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 { for item in impl_.items {
walk_impl_item_ref(&mut checker, item); walk_impl_item_ref(&mut checker, item);
} }

View file

@ -3,7 +3,7 @@ use clippy_utils::source::snippet;
use hir::def::{DefKind, Res}; use hir::def::{DefKind, Res};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir::{self as hir, AmbigArg};
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
@ -123,7 +123,7 @@ impl LateLintPass<'_> for MacroUseImports {
self.push_unique_macro_pat_ty(cx, pat.span); 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() { if ty.span.from_expansion() {
self.push_unique_macro_pat_ty(cx, ty.span); self.push_unique_macro_pat_ty(cx, ty.span);
} }

View file

@ -6,11 +6,11 @@ use clippy_utils::source::snippet_with_context;
use rustc_ast::ast::LitKind; use rustc_ast::ast::LitKind;
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_errors::Applicability; 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_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_session::impl_lint_pass; use rustc_session::impl_lint_pass;
use rustc_span::sym; use rustc_span::{Span, sym};
declare_clippy_lint! { declare_clippy_lint! {
/// ### What it does /// ### What it does
@ -57,13 +57,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits {
&& let ctxt = expr.span.ctxt() && let ctxt = expr.span.ctxt()
&& left_expr.span.ctxt() == ctxt && left_expr.span.ctxt() == ctxt
&& right_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(_)) && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_))
&& let ExprKind::Lit(lit) = &other_expr.kind && let ExprKind::Lit(lit) = &other_expr.kind
&& let LitKind::Int(Pu128(8), _) = lit.node && let LitKind::Int(Pu128(8), _) = lit.node
{ {
let mut app = Applicability::MachineApplicable; 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")); let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS"));
span_lint_and_sugg( span_lint_and_sugg(
@ -85,21 +85,21 @@ fn get_one_size_of_ty<'tcx>(
cx: &LateContext<'tcx>, cx: &LateContext<'tcx>,
expr1: &'tcx Expr<'_>, expr1: &'tcx Expr<'_>,
expr2: &'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)) { 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)), (Some((real_ty_span, resolved_ty)), None) => Some((real_ty_span, resolved_ty, expr2)),
(None, Some((real_ty, resolved_ty))) => Some((real_ty, resolved_ty, expr1)), (None, Some((real_ty_span, resolved_ty))) => Some((real_ty_span, resolved_ty, expr1)),
_ => None, _ => 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 if let ExprKind::Call(count_func, []) = expr.kind
&& let ExprKind::Path(ref count_func_qpath) = count_func.kind && let ExprKind::Path(ref count_func_qpath) = count_func.kind
&& let QPath::Resolved(_, count_func_path) = count_func_qpath && let QPath::Resolved(_, count_func_path) = count_func_qpath
&& let Some(segment_zero) = count_func_path.segments.first() && let Some(segment_zero) = count_func_path.segments.first()
&& let Some(args) = segment_zero.args && 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() && 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) && 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) .node_args(count_func.hir_id)
.types() .types()
.next() .next()
.map(|resolved_ty| (*real_ty, resolved_ty)) .map(|resolved_ty| (real_ty_span, resolved_ty))
} else { } else {
None None
} }

View file

@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
Node::Param(..) => (), Node::Param(..) => (),
Node::LetStmt(local) => { Node::LetStmt(local) => {
let Some(ty) = local.ty else { return }; let Some(ty) = local.ty else { return };
if matches!(ty.kind, TyKind::Infer) { if matches!(ty.kind, TyKind::Infer(())) {
return; return;
} }
}, },

View file

@ -49,7 +49,7 @@ pub(super) fn check<'tcx>(
fn_decl.output, fn_decl.output,
FnRetTy::DefaultReturn(_) FnRetTy::DefaultReturn(_)
| FnRetTy::Return(hir::Ty { | FnRetTy::Return(hir::Ty {
kind: hir::TyKind::Infer, kind: hir::TyKind::Infer(()),
.. ..
}) })
) { ) {

View file

@ -1,14 +1,14 @@
use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res}; use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir::{self as hir, AmbigArg};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::print::with_forced_trimmed_paths;
use super::UNNECESSARY_LITERAL_UNWRAP; 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?; let args = args?;
if args.len() <= index { 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] { match args[index] {
hir::GenericArg::Type(ty) => match ty.kind { hir::GenericArg::Type(ty) => Some(ty),
hir::TyKind::Infer => None,
_ => Some(ty),
},
_ => None, _ => None,
} }
} }

View file

@ -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> { fn find_elem_explicit_type_span(fn_decl: &FnDecl<'_>) -> Option<Span> {
if let [tuple_ty] = fn_decl.inputs if let [tuple_ty] = fn_decl.inputs
&& let TyKind::Tup([_idx_ty, elem_ty]) = tuple_ty.kind && 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) Some(elem_ty.span)
} else { } else {

View file

@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint, span_lint_hir}; use clippy_utils::diagnostics::{span_lint, span_lint_hir};
use clippy_utils::higher; use clippy_utils::higher;
use rustc_hir as hir; use rustc_hir::{self as hir, AmbigArg, intravisit};
use rustc_hir::intravisit;
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty; use rustc_middle::ty;
@ -34,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut {
intravisit::walk_block(&mut MutVisitor { cx }, block); 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 if let hir::TyKind::Ref(_, mty) = ty.kind
&& mty.mutbl == hir::Mutability::Mut && mty.mutbl == hir::Mutability::Mut
&& let hir::TyKind::Ref(_, mty) = mty.ty.kind && let hir::TyKind::Ref(_, mty) = mty.ty.kind

View file

@ -190,7 +190,8 @@ fn in_impl<'tcx>(
&& let Some(generic_args) = seg.args && let Some(generic_args) = seg.args
&& let Some(GenericArg::Type(other_ty)) = generic_args.args.last() && 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 { } else {
None None
} }

View file

@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::last_path_segment; use clippy_utils::last_path_segment;
use clippy_utils::source::snippet; use clippy_utils::source::snippet;
use rustc_errors::Applicability; 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_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -36,7 +36,7 @@ declare_clippy_lint! {
declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);
impl<'tcx> LateLintPass<'tcx> for RefOptionRef { 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 if let TyKind::Ref(_, ref mut_ty) = ty.kind
&& mut_ty.mutbl == Mutability::Not && mut_ty.mutbl == Mutability::Not
&& let TyKind::Path(qpath) = &mut_ty.ty.kind && let TyKind::Path(qpath) = &mut_ty.ty.kind

View file

@ -10,8 +10,8 @@ use rustc_data_structures::unhash::UnhashMap;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::{ use rustc_hir::{
BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, AmbigArg, BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment,
TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind, PredicateOrigin, QPath, TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind,
}; };
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass; 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 if let TyKind::Ref(.., mut_ty) = &ty.kind
&& let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind
&& bounds.len() > 2 && bounds.len() > 2

View file

@ -52,7 +52,6 @@ pub(super) fn check<'tcx>(
let missing_generic = match args { let missing_generic = match args {
Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg { Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg {
GenericArg::Infer(_) => true, GenericArg::Infer(_) => true,
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer),
_ => false, _ => false,
}), }),
_ => true, _ => true,
@ -65,7 +64,7 @@ pub(super) fn check<'tcx>(
// ... which does have type annotations. // ... which does have type annotations.
if let Some(ty) = local.ty if let Some(ty) = local.ty
// If this is a `let x: _ =`, we should lint. // If this is a `let x: _ =`, we should lint.
&& !matches!(ty.kind, TyKind::Infer) && !matches!(ty.kind, TyKind::Infer(()))
{ {
return false; return false;
} }

View file

@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
_ => None, _ => 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. // Ignore `Box<Any>` types; see issue #1884 for details.
return false; 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. // Originally reported as the issue #3128.
let inner_snippet = snippet(cx, inner.span, ".."); let inner_snippet = snippet(cx, inner.span, "..");
let suggestion = match &inner.kind { 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})") format!("&{ltopt}({inner_snippet})")
}, },
TyKind::Path(qpath) TyKind::Path(qpath)

View file

@ -560,7 +560,7 @@ impl Types {
_ => None, _ => None,
}) })
}) { }) {
self.check_ty(cx, ty, context); self.check_ty(cx, ty.as_unambig_ty(), context);
} }
}, },
QPath::Resolved(None, p) => { QPath::Resolved(None, p) => {
@ -574,7 +574,7 @@ impl Types {
_ => None, _ => None,
}) })
}) { }) {
self.check_ty(cx, ty, context); self.check_ty(cx, ty.as_unambig_ty(), context);
} }
}, },
QPath::TypeRelative(ty, seg) => { QPath::TypeRelative(ty, seg) => {
@ -585,7 +585,7 @@ impl Types {
GenericArg::Type(ty) => Some(ty), GenericArg::Type(ty) => Some(ty),
_ => None, _ => None,
}) { }) {
self.check_ty(cx, ty, context); self.check_ty(cx, ty.as_unambig_ty(), context);
} }
} }
}, },

View file

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint; use clippy_utils::diagnostics::span_lint;
use rustc_hir as hir; use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty}; use rustc_hir::{self as hir, AmbigArg, GenericParamKind, TyKind};
use rustc_hir::{GenericParamKind, TyKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_span::Span;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use super::TYPE_COMPLEXITY; 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 { pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool {
let score = { let score = {
let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
visitor.visit_ty(ty); visitor.visit_ty_unambig(ty);
visitor.score visitor.score
}; };
@ -36,15 +36,15 @@ struct TypeComplexityVisitor {
} }
impl<'tcx> Visitor<'tcx> for 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; 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 { let (add_score, sub_nest) = match ty.kind {
// _, &x and *x have only small overhead; don't mess with nesting level // &x and *x have only small overhead; don't mess with nesting level
TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0), TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0),
// the "normal" components of a type: named types, arrays/tuples // the "normal" components of a type: named types, arrays/tuples
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), 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 // function types bring a lot of overhead
TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), 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| { let has_lifetime_parameters = param_bounds.iter().any(|bound| {
bound bound
.bound_generic_params .bound_generic_params

View file

@ -35,7 +35,8 @@ pub(super) fn check<'tcx>(
&& let Some(GenericArg::Type(boxed_ty)) = last.args.first() && let Some(GenericArg::Type(boxed_ty)) = last.args.first()
// extract allocator from the Box for later // extract allocator from the Box for later
&& let boxed_alloc_ty = last.args.get(1) && 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.has_escaping_bound_vars()
&& ty_ty.is_sized(cx.tcx, cx.typing_env()) && ty_ty.is_sized(cx.tcx, cx.typing_env())
&& let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) && 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))) => (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 _ => false
} }
{ {

View file

@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) {
return; 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())) || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
&& expr_needs_inferred_result(cx, init) && 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() { while let Some(id) = locals_to_check.pop() {
if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) { 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; return false;
} }
if let Some(e) = l.init { if let Some(e) = l.init {

View file

@ -7,10 +7,10 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::LocalDefId; 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::{ use rustc_hir::{
self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind,
ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
}; };
use rustc_hir_analysis::lower_ty; use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass}; 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) { 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()) { if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
let mut visitor = SkipTyCollector::default(); 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); 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() if !hir_ty.span.from_expansion()
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
&& let Some(&StackItem::Check { && let Some(&StackItem::Check {
@ -218,7 +218,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
&& let ty = if in_body > 0 { && let ty = if in_body > 0 {
cx.typeck_results().node_type(hir_ty.hir_id) cx.typeck_results().node_type(hir_ty.hir_id)
} else { } 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() && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity()
&& same_type_and_consts(ty, impl_ty) && same_type_and_consts(ty, impl_ty)
@ -275,12 +276,14 @@ struct SkipTyCollector {
} }
impl Visitor<'_> for SkipTyCollector { impl Visitor<'_> for SkipTyCollector {
fn visit_infer(&mut self, inf: &hir::InferArg) { fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result {
self.types_to_skip.push(inf.hir_id); // Conservatively assume ambiguously kinded inferred arguments are type arguments
if let InferKind::Ambig(_) | InferKind::Ty(_) = kind {
walk_inf(self, inf); self.types_to_skip.push(inf_id);
} }
fn visit_ty(&mut self, hir_ty: &Ty<'_>) { self.visit_id(inf_id);
}
fn visit_ty(&mut self, hir_ty: &Ty<'_, AmbigArg>) {
self.types_to_skip.push(hir_ty.hir_id); self.types_to_skip.push(hir_ty.hir_id);
walk_ty(self, hir_ty); walk_ty(self, hir_ty);

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; 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_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
@ -44,10 +44,11 @@ declare_clippy_lint! {
declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]);
impl LateLintPass<'_> for ZeroSizedMapValues { 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() if !hir_ty.span.from_expansion()
&& !in_trait_impl(cx, hir_ty.hir_id) && !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)) && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap))
&& let ty::Adt(_, args) = ty.kind() && let ty::Adt(_, args) = ty.kind()
&& let ty = args.type_at(1) && let ty = args.type_at(1)

View file

@ -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::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1),
TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")),
TyKind::Path(qpath) => qpath_search_pat(&qpath), TyKind::Path(qpath) => qpath_search_pat(&qpath),
TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")),
TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), 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. // NOTE: `TraitObject` is incomplete. It will always return true then.
_ => (Pat::Str(""), Pat::Str("")), _ => (Pat::Str(""), Pat::Str("")),
} }

View file

@ -459,9 +459,9 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool { fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
match (left, right) { 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::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()), (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()),
_ => false, _ => false,
} }
@ -618,7 +618,7 @@ impl HirEqInterExpr<'_, '_, '_> {
}, },
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), (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::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, _ => false,
} }
} }
@ -1281,7 +1281,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
} }
}, },
TyKind::Path(qpath) => self.hash_qpath(qpath), TyKind::Path(qpath) => self.hash_qpath(qpath),
TyKind::TraitObject(_, lifetime, _) => { TyKind::TraitObject(_, lifetime) => {
self.hash_lifetime(lifetime); self.hash_lifetime(lifetime);
}, },
TyKind::Typeof(anon_const) => { TyKind::Typeof(anon_const) => {
@ -1291,7 +1291,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_ty(binder.inner_ty); self.hash_ty(binder.inner_ty);
}, },
TyKind::Err(_) TyKind::Err(_)
| TyKind::Infer | TyKind::Infer(())
| TyKind::Never | TyKind::Never
| TyKind::InferDelegation(..) | TyKind::InferDelegation(..)
| TyKind::OpaqueDef(_) | TyKind::OpaqueDef(_)
@ -1318,8 +1318,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
for arg in arg_list { for arg in arg_list {
match *arg { match *arg {
GenericArg::Lifetime(l) => self.hash_lifetime(l), GenericArg::Lifetime(l) => self.hash_lifetime(l),
GenericArg::Type(ty) => self.hash_ty(ty), GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()),
GenericArg::Const(ca) => self.hash_const_arg(ca), GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()),
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
} }
} }

View file

@ -437,7 +437,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc
.map_or(&[][..], |a| a.args) .map_or(&[][..], |a| a.args)
.iter() .iter()
.filter_map(|a| match a { .filter_map(|a| match a {
hir::GenericArg::Type(ty) => Some(*ty), hir::GenericArg::Type(ty) => Some(ty.as_unambig_ty()),
_ => None, _ => 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 { pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
match expr.kind { match expr.kind {
ExprKind::Closure(&Closure { body, fn_decl, .. }) 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)) is_body_identity_function(cx, cx.tcx.hir().body(body))
}, },

View file

@ -14,8 +14,8 @@
use crate::def_path_res; use crate::def_path_res;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty}; use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_qpath, walk_ty};
use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind}; use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty}; use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty};
use rustc_span::{Span, Symbol}; 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<'_>) { fn visit_ty(&mut self, ty: &'cx hir::Ty<'_, AmbigArg>) {
if matches!(ty.kind, TyKind::Infer) {
self.certainty = Certainty::Uncertain;
}
if self.certainty != Certainty::Uncertain { if self.certainty != Certainty::Uncertain {
walk_ty(self, ty); 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 { 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); let mut visitor = CertaintyVisitor::new(cx);
visitor.visit_ty(ty); visitor.visit_ty_unambig(ty);
visitor.certainty visitor.certainty
} }

View file

@ -2,7 +2,7 @@ use crate::ty::needs_ordered_drop;
use crate::{get_enclosing_block, path_to_local_id}; use crate::{get_enclosing_block, path_to_local_id};
use core::ops::ControlFlow; use core::ops::ControlFlow;
use rustc_ast::visit::{VisitorResult, try_visit}; 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::def::{CtorKind, DefKind, Res};
use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr}; use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr};
use rustc_hir::{ use rustc_hir::{
@ -122,7 +122,7 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>(
} }
// Avoid unnecessary `walk_*` calls. // 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(()) ControlFlow::Continue(())
} }
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { 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(()) ControlFlow::Continue(())
} }
// Avoid unnecessary `walk_*` calls. // 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(()) ControlFlow::Continue(())
} }
fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result {

View file

@ -0,0 +1,9 @@
#![feature(generic_arg_infer, closure_lifetime_binder)]
struct Foo<const N: usize>([u32; N]);
fn main() {
let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] };
//~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present
c(&Foo([1_u32; 1]));
}

View file

@ -0,0 +1,10 @@
error: implicit types in closure signatures are forbidden when `for<...>` is present
--> $DIR/forbid_ambig_const_infers.rs:6:33
|
LL | let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] };
| ------- ^
| |
| `for<...>` is here
error: aborting due to 1 previous error

View file

@ -0,0 +1,9 @@
#![feature(generic_arg_infer, closure_lifetime_binder)]
struct Foo<T>(T);
fn main() {
let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0 };
//~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present
c(&Foo(1_u32));
}

Some files were not shown because too many files have changed in this diff Show more