Split hir TyKind
and ConstArgKind
in two and update hir::Visitor
This commit is contained in:
parent
0f10ba60ff
commit
98d80e22d0
48 changed files with 513 additions and 313 deletions
|
@ -31,7 +31,7 @@ use crate::LangItem;
|
|||
use crate::def::{CtorKind, DefKind, Res};
|
||||
use crate::def_id::{DefId, LocalDefIdMap};
|
||||
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)]
|
||||
pub struct Lifetime {
|
||||
|
@ -264,11 +264,55 @@ impl<'hir> PathSegment<'hir> {
|
|||
/// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args
|
||||
/// 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 }`).
|
||||
///
|
||||
/// 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)]
|
||||
pub struct ConstArg<'hir> {
|
||||
#[repr(C)]
|
||||
pub struct ConstArg<'hir, Unambig = ()> {
|
||||
#[stable_hasher(ignore)]
|
||||
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> {
|
||||
/// 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> ConstArg<'hir> {
|
||||
|
@ -283,14 +327,15 @@ impl<'hir> ConstArg<'hir> {
|
|||
match self.kind {
|
||||
ConstArgKind::Path(path) => path.span(),
|
||||
ConstArgKind::Anon(anon) => anon.span,
|
||||
ConstArgKind::Infer(span) => span,
|
||||
ConstArgKind::Infer(span, _) => span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`ConstArg`].
|
||||
#[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
|
||||
/// (`N` where `fn foo<const N: usize>(...)`),
|
||||
/// not paths to any const (`N` where `const N: usize = ...`).
|
||||
|
@ -298,11 +343,9 @@ pub enum ConstArgKind<'hir> {
|
|||
/// However, in the future, we'll be using it for all of those.
|
||||
Path(QPath<'hir>),
|
||||
Anon(&'hir AnonConst),
|
||||
/// **Note:** Not all inferred consts are represented as
|
||||
/// `ConstArgKind::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(Span),
|
||||
/// This variant is not always used to represent inference consts, sometimes
|
||||
/// [`GenericArg::Infer`] is used instead.
|
||||
Infer(Span, Unambig),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic)]
|
||||
|
@ -314,19 +357,24 @@ pub struct InferArg {
|
|||
|
||||
impl InferArg {
|
||||
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)]
|
||||
pub enum GenericArg<'hir> {
|
||||
Lifetime(&'hir Lifetime),
|
||||
Type(&'hir Ty<'hir>),
|
||||
Const(&'hir ConstArg<'hir>),
|
||||
/// **Note:** Inference variables are only represented as
|
||||
/// `GenericArg::Infer` in cases where it is ambiguous whether
|
||||
/// a generic arg is a type or a const. Otherwise, inference variables
|
||||
/// are represented as `TyKind::Infer` or `ConstArgKind::Infer`.
|
||||
Type(&'hir Ty<'hir, AmbigArg>),
|
||||
Const(&'hir ConstArg<'hir, AmbigArg>),
|
||||
/// Inference variables in [`GenericArg`] are always represnted by
|
||||
/// `GenericArg::Infer` instead of the `Infer` variants on [`TyKind`] and
|
||||
/// [`ConstArgKind`] as it is not clear until hir ty lowering whether a
|
||||
/// `_` 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),
|
||||
}
|
||||
|
||||
|
@ -335,7 +383,7 @@ impl GenericArg<'_> {
|
|||
match self {
|
||||
GenericArg::Lifetime(l) => l.ident.span,
|
||||
GenericArg::Type(t) => t.span,
|
||||
GenericArg::Const(c) => c.span(),
|
||||
GenericArg::Const(c) => c.as_unambig_ct().span(),
|
||||
GenericArg::Infer(i) => i.span,
|
||||
}
|
||||
}
|
||||
|
@ -354,7 +402,7 @@ impl GenericArg<'_> {
|
|||
GenericArg::Lifetime(_) => "lifetime",
|
||||
GenericArg::Type(_) => "type",
|
||||
GenericArg::Const(_) => "constant",
|
||||
GenericArg::Infer(_) => "inferred",
|
||||
GenericArg::Infer(_) => "placeholder",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2915,12 +2963,63 @@ 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)]
|
||||
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)]
|
||||
pub hir_id: HirId,
|
||||
pub kind: TyKind<'hir>,
|
||||
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> {
|
||||
/// 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> {
|
||||
|
@ -2952,7 +3051,7 @@ impl<'hir> Ty<'hir> {
|
|||
use crate::intravisit::Visitor;
|
||||
struct MyVisitor(Vec<Span>);
|
||||
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!(
|
||||
&t.kind,
|
||||
TyKind::Path(QPath::Resolved(_, Path {
|
||||
|
@ -2968,7 +3067,7 @@ impl<'hir> Ty<'hir> {
|
|||
}
|
||||
|
||||
let mut my_visitor = MyVisitor(vec![]);
|
||||
my_visitor.visit_ty(self);
|
||||
my_visitor.visit_unambig_ty(self);
|
||||
my_visitor.0
|
||||
}
|
||||
|
||||
|
@ -2977,14 +3076,14 @@ impl<'hir> Ty<'hir> {
|
|||
pub fn is_suggestable_infer_ty(&self) -> bool {
|
||||
fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool {
|
||||
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,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
debug!(?self);
|
||||
match &self.kind {
|
||||
TyKind::Infer => true,
|
||||
TyKind::Infer(()) => true,
|
||||
TyKind::Slice(ty) => ty.is_suggestable_infer_ty(),
|
||||
TyKind::Array(ty, length) => {
|
||||
ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..))
|
||||
|
@ -3198,7 +3297,9 @@ pub enum InferDelegationKind {
|
|||
|
||||
/// The various kinds of types recognized by the compiler.
|
||||
#[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
|
||||
InferDelegation(DefId, InferDelegationKind),
|
||||
/// A variable length slice (i.e., `[T]`).
|
||||
|
@ -3234,18 +3335,16 @@ pub enum TyKind<'hir> {
|
|||
TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>),
|
||||
/// Unused for now.
|
||||
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.
|
||||
Err(rustc_span::ErrorGuaranteed),
|
||||
/// Pattern types (`pattern_type!(u32 is 1..)`)
|
||||
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)]
|
||||
|
|
|
@ -351,18 +351,42 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result {
|
||||
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.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// 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 {
|
||||
walk_expr(self, ex)
|
||||
}
|
||||
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
|
||||
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>) {
|
||||
// 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
|
||||
|
@ -444,15 +468,6 @@ pub trait Visitor<'v>: Sized {
|
|||
fn visit_label(&mut self, label: &'v Label) -> Self::Result {
|
||||
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.
|
||||
fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result {
|
||||
walk_qpath(self, qpath, id)
|
||||
|
@ -486,6 +501,20 @@ 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.
|
||||
fn visit_unambig_ty(&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.
|
||||
fn visit_unambig_const_arg(&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 {
|
||||
try_visit!(visitor.visit_id(param.hir_id));
|
||||
visitor.visit_pat(param.pat)
|
||||
|
@ -503,12 +532,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
|||
}
|
||||
ItemKind::Static(ref typ, _, body) => {
|
||||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
try_visit!(visitor.visit_ty(typ));
|
||||
try_visit!(visitor.visit_unambig_ty(typ));
|
||||
try_visit!(visitor.visit_nested_body(body));
|
||||
}
|
||||
ItemKind::Const(ref typ, ref generics, body) => {
|
||||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
try_visit!(visitor.visit_ty(typ));
|
||||
try_visit!(visitor.visit_unambig_ty(typ));
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
try_visit!(visitor.visit_nested_body(body));
|
||||
}
|
||||
|
@ -539,7 +568,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
|||
}
|
||||
ItemKind::TyAlias(ref ty, ref generics) => {
|
||||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
try_visit!(visitor.visit_generics(generics));
|
||||
}
|
||||
ItemKind::Enum(ref enum_definition, ref generics) => {
|
||||
|
@ -561,7 +590,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_generics(generics));
|
||||
visit_opt!(visitor, visit_trait_ref, of_trait);
|
||||
try_visit!(visitor.visit_ty(self_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(self_ty));
|
||||
walk_list!(visitor, visit_impl_item_ref, *items);
|
||||
}
|
||||
ItemKind::Struct(ref struct_definition, ref generics)
|
||||
|
@ -618,7 +647,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(
|
|||
walk_list!(visitor, visit_ident, param_names.iter().copied());
|
||||
}
|
||||
ForeignItemKind::Static(ref typ, _, _) => {
|
||||
try_visit!(visitor.visit_ty(typ));
|
||||
try_visit!(visitor.visit_unambig_ty(typ));
|
||||
}
|
||||
ForeignItemKind::Type => (),
|
||||
}
|
||||
|
@ -632,7 +661,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_pat(local.pat));
|
||||
visit_opt!(visitor, visit_block, local.els);
|
||||
visit_opt!(visitor, visit_ty, local.ty);
|
||||
visit_opt!(visitor, visit_unambig_ty, local.ty);
|
||||
V::Result::output()
|
||||
}
|
||||
|
||||
|
@ -735,18 +764,6 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>(
|
|||
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 {
|
||||
try_visit!(visitor.visit_id(expression.hir_id));
|
||||
match expression.kind {
|
||||
|
@ -758,7 +775,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
}
|
||||
ExprKind::Repeat(ref element, ref count) => {
|
||||
try_visit!(visitor.visit_expr(element));
|
||||
try_visit!(visitor.visit_const_arg(count));
|
||||
try_visit!(visitor.visit_unambig_const_arg(count));
|
||||
}
|
||||
ExprKind::Struct(ref qpath, fields, ref optional_base) => {
|
||||
try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span));
|
||||
|
@ -789,7 +806,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) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
try_visit!(visitor.visit_ty(typ));
|
||||
try_visit!(visitor.visit_unambig_ty(typ));
|
||||
}
|
||||
ExprKind::DropTemps(ref subexpression) => {
|
||||
try_visit!(visitor.visit_expr(subexpression));
|
||||
|
@ -798,7 +815,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
// match the visit order in walk_local
|
||||
try_visit!(visitor.visit_expr(init));
|
||||
try_visit!(visitor.visit_pat(pat));
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
visit_opt!(visitor, visit_unambig_ty, ty);
|
||||
}
|
||||
ExprKind::If(ref cond, ref then, ref else_opt) => {
|
||||
try_visit!(visitor.visit_expr(cond));
|
||||
|
@ -866,7 +883,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));
|
||||
}
|
||||
ExprKind::OffsetOf(ref container, ref fields) => {
|
||||
try_visit!(visitor.visit_ty(container));
|
||||
try_visit!(visitor.visit_unambig_ty(container));
|
||||
walk_list!(visitor, visit_ident, fields.iter().copied());
|
||||
}
|
||||
ExprKind::Yield(ref subexpression, _) => {
|
||||
|
@ -874,7 +891,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
|
|||
}
|
||||
ExprKind::UnsafeBinderCast(_kind, expr, ty) => {
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
visit_opt!(visitor, visit_ty, ty);
|
||||
visit_opt!(visitor, visit_unambig_ty, ty);
|
||||
}
|
||||
ExprKind::Lit(_) | ExprKind::Err(_) => {}
|
||||
}
|
||||
|
@ -887,19 +904,47 @@ pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField
|
|||
visitor.visit_expr(field.expr)
|
||||
}
|
||||
|
||||
pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result {
|
||||
pub enum InferKind<'hir> {
|
||||
Ty(&'hir Ty<'hir>),
|
||||
Const(&'hir ConstArg<'hir>),
|
||||
Ambig(&'hir InferArg),
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
match typ.kind {
|
||||
TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty(mutable_type.ty)),
|
||||
TyKind::Slice(ref ty) => try_visit!(visitor.visit_unambig_ty(ty)),
|
||||
TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_unambig_ty(mutable_type.ty)),
|
||||
TyKind::Ref(ref lifetime, ref mutable_type) => {
|
||||
try_visit!(visitor.visit_lifetime(lifetime));
|
||||
try_visit!(visitor.visit_ty(mutable_type.ty));
|
||||
try_visit!(visitor.visit_unambig_ty(mutable_type.ty));
|
||||
}
|
||||
TyKind::Never => {}
|
||||
TyKind::Tup(tuple_element_types) => {
|
||||
walk_list!(visitor, visit_ty, tuple_element_types);
|
||||
walk_list!(visitor, visit_unambig_ty, tuple_element_types);
|
||||
}
|
||||
TyKind::BareFn(ref function_declaration) => {
|
||||
walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
|
||||
|
@ -907,7 +952,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
|||
}
|
||||
TyKind::UnsafeBinder(ref unsafe_binder) => {
|
||||
walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params);
|
||||
try_visit!(visitor.visit_ty(unsafe_binder.inner_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(unsafe_binder.inner_ty));
|
||||
}
|
||||
TyKind::Path(ref qpath) => {
|
||||
try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span));
|
||||
|
@ -919,8 +964,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
|||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
TyKind::Array(ref ty, ref length) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_const_arg(length));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_const_arg(length));
|
||||
}
|
||||
TyKind::TraitObject(bounds, ref lifetime) => {
|
||||
for bound in bounds {
|
||||
|
@ -929,15 +974,39 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
|
|||
try_visit!(visitor.visit_lifetime(lifetime));
|
||||
}
|
||||
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) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
try_visit!(visitor.visit_pattern_type_pattern(pat));
|
||||
}
|
||||
}
|
||||
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>>(
|
||||
visitor: &mut V,
|
||||
param: &'v GenericParam<'v>,
|
||||
|
@ -949,9 +1018,11 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
|
|||
}
|
||||
match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => {}
|
||||
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
|
||||
GenericParamKind::Type { ref default, .. } => {
|
||||
visit_opt!(visitor, visit_unambig_ty, default)
|
||||
}
|
||||
GenericParamKind::Const { ref ty, ref default, synthetic: _ } => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
if let Some(ref default) = default {
|
||||
try_visit!(visitor.visit_const_param_default(param.hir_id, default));
|
||||
}
|
||||
|
@ -964,7 +1035,7 @@ pub fn walk_const_param_default<'v, V: Visitor<'v>>(
|
|||
visitor: &mut V,
|
||||
ct: &'v ConstArg<'v>,
|
||||
) -> V::Result {
|
||||
visitor.visit_const_arg(ct)
|
||||
visitor.visit_unambig_const_arg(ct)
|
||||
}
|
||||
|
||||
pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result {
|
||||
|
@ -986,7 +1057,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
|
|||
bound_generic_params,
|
||||
origin: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_ty(bounded_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(bounded_ty));
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
walk_list!(visitor, visit_generic_param, bound_generic_params);
|
||||
}
|
||||
|
@ -999,8 +1070,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
|
|||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
}
|
||||
WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => {
|
||||
try_visit!(visitor.visit_ty(lhs_ty));
|
||||
try_visit!(visitor.visit_ty(rhs_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(lhs_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(rhs_ty));
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
|
@ -1010,13 +1081,13 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>(
|
|||
visitor: &mut V,
|
||||
function_declaration: &'v FnDecl<'v>,
|
||||
) -> V::Result {
|
||||
walk_list!(visitor, visit_ty, function_declaration.inputs);
|
||||
walk_list!(visitor, visit_unambig_ty, function_declaration.inputs);
|
||||
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 {
|
||||
if let FnRetTy::Return(output_ty) = *ret_ty {
|
||||
try_visit!(visitor.visit_ty(output_ty));
|
||||
try_visit!(visitor.visit_unambig_ty(output_ty));
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
@ -1069,7 +1140,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_id(hir_id));
|
||||
match *kind {
|
||||
TraitItemKind::Const(ref ty, default) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
visit_opt!(visitor, visit_nested_body, default);
|
||||
}
|
||||
TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
|
||||
|
@ -1087,7 +1158,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
|
|||
}
|
||||
TraitItemKind::Type(bounds, ref default) => {
|
||||
walk_list!(visitor, visit_param_bound, bounds);
|
||||
visit_opt!(visitor, visit_ty, default);
|
||||
visit_opt!(visitor, visit_unambig_ty, default);
|
||||
}
|
||||
}
|
||||
V::Result::output()
|
||||
|
@ -1125,7 +1196,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_id(impl_item.hir_id()));
|
||||
match *kind {
|
||||
ImplItemKind::Const(ref ty, body) => {
|
||||
try_visit!(visitor.visit_ty(ty));
|
||||
try_visit!(visitor.visit_unambig_ty(ty));
|
||||
visitor.visit_nested_body(body)
|
||||
}
|
||||
ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn(
|
||||
|
@ -1135,7 +1206,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(
|
|||
impl_item.span,
|
||||
impl_item.owner_id.def_id,
|
||||
),
|
||||
ImplItemKind::Type(ref ty) => visitor.visit_ty(ty),
|
||||
ImplItemKind::Type(ref ty) => visitor.visit_unambig_ty(ty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1223,7 +1294,7 @@ pub fn walk_field_def<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_id(*hir_id));
|
||||
try_visit!(visitor.visit_ident(*ident));
|
||||
visit_opt!(visitor, visit_anon_const, default);
|
||||
visitor.visit_ty(*ty)
|
||||
visitor.visit_unambig_ty(*ty)
|
||||
}
|
||||
|
||||
pub fn walk_enum_def<'v, V: Visitor<'v>>(
|
||||
|
@ -1252,18 +1323,6 @@ pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Re
|
|||
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 {
|
||||
try_visit!(visitor.visit_id(lifetime.hir_id));
|
||||
visitor.visit_ident(lifetime.ident)
|
||||
|
@ -1276,11 +1335,11 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(
|
|||
) -> V::Result {
|
||||
match *qpath {
|
||||
QPath::Resolved(ref maybe_qself, ref path) => {
|
||||
visit_opt!(visitor, visit_ty, maybe_qself);
|
||||
visit_opt!(visitor, visit_unambig_ty, maybe_qself);
|
||||
visitor.visit_path(path, id)
|
||||
}
|
||||
QPath::TypeRelative(ref qself, ref segment) => {
|
||||
try_visit!(visitor.visit_ty(qself));
|
||||
try_visit!(visitor.visit_unambig_ty(qself));
|
||||
visitor.visit_path_segment(segment)
|
||||
}
|
||||
QPath::LangItem(..) => V::Result::output(),
|
||||
|
@ -1320,8 +1379,8 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_generic_args(constraint.gen_args));
|
||||
match constraint.kind {
|
||||
AssocItemConstraintKind::Equality { ref term } => match term {
|
||||
Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)),
|
||||
Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)),
|
||||
Term::Ty(ref ty) => try_visit!(visitor.visit_unambig_ty(ty)),
|
||||
Term::Const(ref c) => try_visit!(visitor.visit_unambig_const_arg(c)),
|
||||
},
|
||||
AssocItemConstraintKind::Bound { bounds } => {
|
||||
walk_list!(visitor, visit_param_bound, bounds)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue