use std::assert_matches::assert_matches; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::bug; use rustc_middle::ty::{self, CanonicalUserType, TyCtxt}; use tracing::debug; /// Looks up the type associated with this hir-id and applies the /// user-given generic parameters; the hir-id must map to a suitable /// type. pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>( tcx: TyCtxt<'tcx>, typeck_results: &ty::TypeckResults<'tcx>, hir_id: hir::HirId, ) -> Option> { let user_provided_types = typeck_results.user_provided_types(); let mut user_ty = *user_provided_types.get(hir_id)?; debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); let ty = typeck_results.node_type(hir_id); match ty.kind() { ty::Adt(adt_def, ..) => { // This "fixes" user type annotations for tupled ctor patterns for ADTs. // That's because `type_of(ctor_did)` returns a FnDef, but we actually // want to be annotating the type of the ADT itself. It's a bit goofy, // but it's easier to adjust this here rather than in the path lowering // code for patterns in HIR. if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind { // This is either already set up correctly (struct, union, enum, or variant), // or needs adjusting (ctor). Make sure we don't start adjusting other // user annotations like consts or fn calls. assert_matches!( tcx.def_kind(*did), DefKind::Ctor(..) | DefKind::Struct | DefKind::Enum | DefKind::Union | DefKind::Variant ); *did = adt_def.did(); } Some(user_ty) } ty::FnDef(..) => Some(user_ty), _ => bug!("ty: {:?} should not have user provided type {:?} recorded ", ty, user_ty), } }