Add the inline const type annotation in pattern lowering

This commit is contained in:
Nadrieril 2025-03-29 15:13:14 +01:00
parent 50e10b37c0
commit 961c7463d8
2 changed files with 35 additions and 31 deletions

View file

@ -1,6 +1,5 @@
use std::sync::Arc;
use rustc_hir::def::DefKind;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@ -202,35 +201,8 @@ impl<'tcx> MatchPairTree<'tcx> {
None
}
PatKind::ExpandedConstant { subpattern: ref pattern, def_id } => {
PatKind::ExpandedConstant { subpattern: ref pattern, .. } => {
MatchPairTree::for_pattern(place_builder, pattern, cx, &mut subpairs, extra_data);
// Apply a type ascription for the inline constant to the value at `match_pair.place`
if let Some(source) = place
&& matches!(cx.tcx.def_kind(def_id), DefKind::InlineConst)
{
let span = pattern.span;
let parent_id = cx.tcx.typeck_root_def_id(cx.def_id.to_def_id());
let args = ty::InlineConstArgs::new(
cx.tcx,
ty::InlineConstArgsParts {
parent_args: ty::GenericArgs::identity_for_item(cx.tcx, parent_id),
ty: cx.infcx.next_ty_var(span),
},
)
.args;
let user_ty = cx.infcx.canonicalize_user_type_annotation(ty::UserType::new(
ty::UserTypeKind::TypeOf(def_id, ty::UserArgs { args, user_self_ty: None }),
));
let annotation = ty::CanonicalUserTypeAnnotation {
inferred_ty: pattern.ty,
span,
user_ty: Box::new(user_ty),
};
let variance = ty::Contravariant;
extra_data.ascriptions.push(super::Ascription { annotation, source, variance });
}
None
}

View file

@ -13,12 +13,15 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, LangItem, RangeEnd};
use rustc_index::Idx;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::interpret::LitToConstInput;
use rustc_middle::thir::{
Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary,
};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{
self, CanonicalUserTypeAnnotation, Ty, TyCtxt, TypeVisitableExt, TypingMode,
};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::{ErrorGuaranteed, Span};
@ -605,7 +608,36 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
let c = ty::Const::new_unevaluated(self.tcx, ct);
self.const_to_pat(c, ty, id, span).kind
let pattern = self.const_to_pat(c, ty, id, span);
// Apply a type ascription for the inline constant.
// FIXME: reusing the `args` above causes an ICE
let annotation = {
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let args = ty::InlineConstArgs::new(
tcx,
ty::InlineConstArgsParts {
parent_args: ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id),
ty: infcx.next_ty_var(span),
},
)
.args;
infcx.canonicalize_user_type_annotation(ty::UserType::new(ty::UserTypeKind::TypeOf(
def_id.to_def_id(),
ty::UserArgs { args, user_self_ty: None },
)))
};
let annotation =
CanonicalUserTypeAnnotation { user_ty: Box::new(annotation), span, inferred_ty: ty };
PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
// Note that we use `Contravariant` here. See the `variance` field documentation
// for details.
variance: ty::Contravariant,
},
}
}
/// Lowers the kinds of "expression" that can appear in a HIR pattern: