Thread pattern types through the HIR

This commit is contained in:
Oli Scherer 2023-01-31 11:54:06 +00:00
parent c340e67dec
commit c4efc25bfa
15 changed files with 48 additions and 5 deletions

View File

@ -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(_) => { TyKind::MacCall(_) => {
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") 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) hir::TyKind::Err(guar)
} }
TyKind::Pat(..) => span_bug!(t.span, "pattern types are unimplemented"),
TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"),
}; };

View File

@ -2624,6 +2624,8 @@ pub enum TyKind<'hir> {
Infer, 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 (`u32 as 1..`)
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
} }
#[derive(Debug, Clone, Copy, HashStable_Generic)] #[derive(Debug, Clone, Copy, HashStable_Generic)]

View File

@ -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) => { TyKind::AnonAdt(item_id) => {
try_visit!(visitor.visit_nested_item(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() V::Result::output()
} }

View File

@ -2195,6 +2195,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// handled specially and will not descend into this routine. // handled specially and will not descend into this routine.
self.ty_infer(None, hir_ty.span) 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), hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar),
}; };

View File

@ -330,6 +330,11 @@ impl<'a> State<'a> {
self.word("_"); self.word("_");
} }
hir::TyKind::AnonAdt(..) => self.word("/* anonymous adt */"), 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() self.end()
} }

View File

@ -157,6 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
| TyKind::Never | TyKind::Never
| TyKind::Tup(_) | TyKind::Tup(_)
| TyKind::Path(_) | TyKind::Path(_)
| TyKind::Pat(..)
| TyKind::AnonAdt(_) | TyKind::AnonAdt(_)
| TyKind::OpaqueDef(_, _, _) | TyKind::OpaqueDef(_, _, _)
| TyKind::Typeof(_) | TyKind::Typeof(_)

View File

@ -352,6 +352,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
TraitObject, TraitObject,
Typeof, Typeof,
Infer, Infer,
Pat,
Err Err
] ]
); );

View File

@ -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)) } BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
} }
TyKind::Slice(ty) => Slice(Box::new(clean_ty(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) => { TyKind::Array(ty, ref length) => {
let length = match length { let length = match length {
hir::ArrayLen::Infer(..) => "_".to_string(), hir::ArrayLen::Infer(..) => "_".to_string(),

View File

@ -1483,7 +1483,9 @@ pub(crate) enum Type {
/// ///
/// This is mostly Rustdoc's version of [`hir::Path`]. /// This is mostly Rustdoc's version of [`hir::Path`].
/// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. /// 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` /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static`
DynTrait(Vec<PolyTrait>, Option<Lifetime>), DynTrait(Vec<PolyTrait>, Option<Lifetime>),
/// A type parameter. /// A type parameter.
@ -1500,10 +1502,15 @@ pub(crate) enum Type {
/// ///
/// The `String` field is a stringified version of the array's length parameter. /// The `String` field is a stringified version of the array's length parameter.
Array(Box<Type>, Box<str>), Array(Box<Type>, Box<str>),
Pat(Box<Type>, Box<str>),
/// A raw pointer type: `*const i32`, `*mut i32` /// A raw pointer type: `*const i32`, `*mut i32`
RawPointer(Mutability, Box<Type>), RawPointer(Mutability, Box<Type>),
/// A reference type: `&i32`, `&'a mut Foo` /// A reference type: `&i32`, `&'a mut Foo`
BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> }, BorrowedRef {
lifetime: Option<Lifetime>,
mutability: Mutability,
type_: Box<Type>,
},
/// A qualified path to an associated item: `<Type as Trait>::Name` /// A qualified path to an associated item: `<Type as Trait>::Name`
QPath(Box<QPathData>), QPath(Box<QPathData>),
@ -1700,6 +1707,7 @@ impl Type {
BareFunction(..) => PrimitiveType::Fn, BareFunction(..) => PrimitiveType::Fn,
Slice(..) => PrimitiveType::Slice, Slice(..) => PrimitiveType::Slice,
Array(..) => PrimitiveType::Array, Array(..) => PrimitiveType::Array,
Type::Pat(..) => PrimitiveType::Pat,
RawPointer(..) => PrimitiveType::RawPointer, RawPointer(..) => PrimitiveType::RawPointer,
QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
Generic(_) | Infer | ImplTrait(_) => return None, Generic(_) | Infer | ImplTrait(_) => return None,
@ -1753,6 +1761,7 @@ pub(crate) enum PrimitiveType {
Str, Str,
Slice, Slice,
Array, Array,
Pat,
Tuple, Tuple,
Unit, Unit,
RawPointer, RawPointer,
@ -1907,6 +1916,7 @@ impl PrimitiveType {
Bool => sym::bool, Bool => sym::bool,
Char => sym::char, Char => sym::char,
Array => sym::array, Array => sym::array,
Pat => sym::pat,
Slice => sym::slice, Slice => sym::slice,
Tuple => sym::tuple, Tuple => sym::tuple,
Unit => sym::unit, Unit => sym::unit,

View File

@ -1071,6 +1071,10 @@ fn fmt_type<'cx>(
write!(f, "]") 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::Array(ref t, ref n) => match **t {
clean::Generic(name) if !f.alternate() => primitive_link( clean::Generic(name) if !f.alternate() => primitive_link(
f, f,

View File

@ -668,7 +668,7 @@ fn get_index_type_id(
} }
} }
// Not supported yet // Not supported yet
clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None, clean::Type::Pat(..) | clean::Generic(_) | clean::ImplTrait(_) | clean::Infer => None,
} }
} }

View File

@ -573,6 +573,9 @@ impl FromWithTcx<clean::Type> for Type {
Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Tuple(t) => Type::Tuple(t.into_tcx(tcx)),
Slice(t) => Type::Slice(Box::new((*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() }, 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)), ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)),
Infer => Type::Infer, Infer => Type::Infer,
RawPointer(mutability, type_) => Type::RawPointer { RawPointer(mutability, type_) => Type::RawPointer {

View File

@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
/// rustdoc format-version. /// 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 /// 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 /// 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<Type>, type_: Box<Type>,
len: String, len: String,
}, },
/// `u32 is 1..`
Pat {
#[serde(rename = "type")]
type_: Box<Type>,
pat: String,
},
/// `impl TraitA + TraitB + ...` /// `impl TraitA + TraitB + ...`
ImplTrait(Vec<GenericBound>), ImplTrait(Vec<GenericBound>),
/// `_` /// `_`

View File

@ -821,6 +821,7 @@ impl TyCoercionStability {
| TyKind::Array(..) | TyKind::Array(..)
| TyKind::Ptr(_) | TyKind::Ptr(_)
| TyKind::BareFn(_) | TyKind::BareFn(_)
| TyKind::Pat(..)
| TyKind::Never | TyKind::Never
| TyKind::Tup(_) | TyKind::Tup(_)
| TyKind::Path(_) => Self::Deref, | TyKind::Path(_) => Self::Deref,

View File

@ -1068,6 +1068,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_ty(ty); self.hash_ty(ty);
self.hash_array_length(len); self.hash_array_length(len);
}, },
TyKind::Pat(ty, pat) => {
self.hash_ty(ty);
self.hash_pat(pat);
},
TyKind::Ptr(ref mut_ty) => { TyKind::Ptr(ref mut_ty) => {
self.hash_ty(mut_ty.ty); self.hash_ty(mut_ty.ty);
mut_ty.mutbl.hash(&mut self.s); mut_ty.mutbl.hash(&mut self.s);