diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4d6c81ad6b7..5005c22d4cc 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1463,6 +1463,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } + TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)), TyKind::MacCall(_) => { span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") } @@ -1473,7 +1474,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); hir::TyKind::Err(guar) } - TyKind::Pat(..) => span_bug!(t.span, "pattern types are unimplemented"), TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), }; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f21cd653f96..17028aa9268 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2624,6 +2624,8 @@ pub enum TyKind<'hir> { Infer, /// Placeholder for a type that has failed to be defined. Err(rustc_span::ErrorGuaranteed), + /// Pattern types (`u32 as 1..`) + Pat(&'hir Ty<'hir>, &'hir Pat<'hir>), } #[derive(Debug, Clone, Copy, HashStable_Generic)] diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8c44f21a57b..795884beb0e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -882,6 +882,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul TyKind::AnonAdt(item_id) => { try_visit!(visitor.visit_nested_item(item_id)); } + TyKind::Pat(ty, pat) => { + try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_pat(pat)); + } } V::Result::output() } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index f726f2a7b89..528af8c1ce8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2195,6 +2195,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // handled specially and will not descend into this routine. self.ty_infer(None, hir_ty.span) } + hir::TyKind::Pat(..) => span_bug!(hir_ty.span, "{hir_ty:#?}"), hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar), }; diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index bd528432e70..a590c648d20 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -330,6 +330,11 @@ impl<'a> State<'a> { self.word("_"); } hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"), + hir::TyKind::Pat(ty, pat) => { + self.print_type(ty); + self.word(" is "); + self.print_pat(pat); + } } self.end() } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 1e9c60a540d..870e198d70a 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -157,6 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { | TyKind::Never | TyKind::Tup(_) | TyKind::Path(_) + | TyKind::Pat(..) | TyKind::AnonAdt(_) | TyKind::OpaqueDef(_, _, _) | TyKind::Typeof(_) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index abde360a26f..72c6a714e4d 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -352,6 +352,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { TraitObject, Typeof, Infer, + Pat, Err ] ); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a25a506d9c5..69146728e84 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1782,6 +1782,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), + TyKind::Pat(ty, pat) => Type::Pat(Box::new(clean_ty(ty, cx)), format!("{pat:?}").into()), TyKind::Array(ty, ref length) => { let length = match length { hir::ArrayLen::Infer(..) => "_".to_string(), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 393996cc770..b592bd76e4c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1483,7 +1483,9 @@ pub(crate) enum Type { /// /// This is mostly Rustdoc's version of [`hir::Path`]. /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. - Path { path: Path }, + Path { + path: Path, + }, /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), /// A type parameter. @@ -1500,10 +1502,15 @@ pub(crate) enum Type { /// /// The `String` field is a stringified version of the array's length parameter. Array(Box, Box), + Pat(Box, Box), /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), /// A reference type: `&i32`, `&'a mut Foo` - BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, + BorrowedRef { + lifetime: Option, + mutability: Mutability, + type_: Box, + }, /// A qualified path to an associated item: `::Name` QPath(Box), @@ -1700,6 +1707,7 @@ impl Type { BareFunction(..) => PrimitiveType::Fn, Slice(..) => PrimitiveType::Slice, Array(..) => PrimitiveType::Array, + Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, @@ -1753,6 +1761,7 @@ pub(crate) enum PrimitiveType { Str, Slice, Array, + Pat, Tuple, Unit, RawPointer, @@ -1907,6 +1916,7 @@ impl PrimitiveType { Bool => sym::bool, Char => sym::char, Array => sym::array, + Pat => sym::pat, Slice => sym::slice, Tuple => sym::tuple, Unit => sym::unit, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 312765d3e6d..f82b89fdd5f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1071,6 +1071,10 @@ fn fmt_type<'cx>( write!(f, "]") } }, + clean::Type::Pat(ref t, ref pat) => { + fmt::Display::fmt(&t.print(cx), f)?; + write!(f, " is {pat}") + } clean::Array(ref t, ref n) => match **t { clean::Generic(name) if !f.alternate() => primitive_link( f, diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 51f90e45500..7083999de68 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -668,7 +668,7 @@ fn get_index_type_id( } } // Not supported yet - clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, + clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, } } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index cb50a27326f..8db7becac05 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -573,6 +573,9 @@ impl FromWithTcx for Type { Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, + clean::Type::Pat(t, p) => { + Type::Pat { type_: Box::new((*t).into_tcx(tcx)), pat: p.to_string() } + } ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 164f88faa31..f69ff87c3f7 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 28; +pub const FORMAT_VERSION: u32 = 29; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -562,6 +562,12 @@ pub enum Type { type_: Box, len: String, }, + /// `u32 is 1..` + Pat { + #[serde(rename = "type")] + type_: Box, + pat: String, + }, /// `impl TraitA + TraitB + ...` ImplTrait(Vec), /// `_` diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 560b2acc1c7..eb317c70926 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -821,6 +821,7 @@ impl TyCoercionStability { | TyKind::Array(..) | TyKind::Ptr(_) | TyKind::BareFn(_) + | TyKind::Pat(..) | TyKind::Never | TyKind::Tup(_) | TyKind::Path(_) => Self::Deref, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f8bbe997774..6c3d9329932 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1068,6 +1068,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(ty); self.hash_array_length(len); }, + TyKind::Pat(ty, pat) => { + self.hash_ty(ty); + self.hash_pat(pat); + }, TyKind::Ptr(ref mut_ty) => { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s);