blob: 457957f5fce953dd81a0fa2cc4a202be6923677a [file] [log] [blame]
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<CanonicalUserType<'tcx>> {
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),
}
}