diff options
Diffstat (limited to 'compiler/rustc_hir/src')
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 167 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/intravisit.rs | 211 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/lib.rs | 1 |
3 files changed, 269 insertions, 110 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 02a67a160b6..6f31f6ba2f4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -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)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b733078fff2..abfcdcc31ca 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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) diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 381062b1429..8ec2054bf53 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -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)] |
