1
Fork 0

Use a different hir type for patterns in pattern types than we use in match patterns

This commit is contained in:
Oli Scherer 2025-01-07 10:24:16 +00:00
parent 613bdd4997
commit f0308938ba
27 changed files with 311 additions and 168 deletions

View file

@ -831,8 +831,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::Pat<'tcx>) {
intravisit::walk_pat(self, p)
fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
intravisit::walk_ty_pat(self, p)
}
#[instrument(level = "debug", skip(self))]

View file

@ -18,9 +18,10 @@ use crate::hir_ty_lowering::HirTyLowerer;
mod opaque;
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
use hir::*;
use rustc_middle::ty::Ty;
let tcx = icx.tcx;
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let node = tcx.hir_node(hir_id);
@ -54,7 +55,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
hir_id: arg_hir_id,
kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
..
}) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
}) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
// Anon consts outside the type system.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@ -138,10 +139,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
}
}
fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
use hir::*;
use rustc_middle::ty::Ty;
let tcx = icx.tcx;
match tcx.parent_hir_node(arg_hir_id) {
// Array length const arguments do not have `type_of` fed as there is never a corresponding
// generic parameter definition.
@ -149,7 +152,15 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id == arg_hir_id =>
{
return tcx.types.usize;
tcx.types.usize
}
Node::TyPat(pat) => {
let hir::TyKind::Pat(ty, p) = tcx.parent_hir_node(pat.hir_id).expect_ty().kind else {
bug!()
};
assert_eq!(p.hir_id, pat.hir_id);
icx.lower_ty(ty)
}
// This is not a `bug!` as const arguments in path segments that did not resolve to anything
@ -344,7 +355,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
tcx.typeck(def_id).node_type(hir_id)
}
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
Node::AnonConst(_) => anon_const_type_of(&icx, def_id),
Node::ConstBlock(_) => {
let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());

View file

@ -1605,13 +1605,6 @@ pub(crate) struct OpaqueCapturesHigherRankedLifetime {
pub bad_place: &'static str,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_pattern_type_non_const_range)]
pub(crate) struct NonConstRange {
#[primary_span]
pub span: Span,
}
#[derive(Subdiagnostic)]
pub(crate) enum InvalidReceiverTyHint {
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]

View file

@ -2,13 +2,6 @@ use rustc_macros::Diagnostic;
use rustc_middle::ty::Ty;
use rustc_span::Span;
#[derive(Diagnostic)]
#[diag(hir_analysis_pattern_type_wild_pat)]
pub(crate) struct WildPatTy {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_invalid_base_type)]
pub(crate) struct InvalidBaseType<'tcx> {

View file

@ -53,7 +53,7 @@ use tracing::{debug, instrument};
use crate::bounds::Bounds;
use crate::check::check_abi_fn_ptr;
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, WildPatTy};
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType};
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
use crate::middle::resolve_bound_vars as rbv;
@ -2435,11 +2435,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let ty_span = ty.span;
let ty = self.lower_ty(ty);
let pat_ty = match pat.kind {
hir::PatKind::Wild => {
let err = self.dcx().emit_err(WildPatTy { span: pat.span });
Ty::new_error(tcx, err)
}
hir::PatKind::Range(start, end, include_end) => {
hir::TyPatKind::Range(start, end, include_end) => {
let ty = match ty.kind() {
ty::Int(_) | ty::Uint(_) | ty::Char => ty,
_ => Ty::new_error(
@ -2452,54 +2448,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}),
),
};
let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> {
let (c, c_ty) = match expr.kind {
hir::PatExprKind::Lit { lit, negated } => {
let lit_input =
LitToConstInput { lit: &lit.node, ty, neg: negated };
let ct = tcx.lit_to_const(lit_input);
(ct, ty)
}
hir::PatExprKind::Path(hir::QPath::Resolved(
_,
path @ &hir::Path {
res: Res::Def(DefKind::ConstParam, def_id),
..
},
)) => {
match self.prohibit_generic_args(
path.segments.iter(),
GenericsArgsErrExtend::Param(def_id),
) {
Ok(()) => {
let ty = tcx
.type_of(def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic");
let ct = self.lower_const_param(def_id, expr.hir_id);
(ct, ty)
}
Err(guar) => (
ty::Const::new_error(tcx, guar),
Ty::new_error(tcx, guar),
),
}
}
_ => {
let err = tcx
.dcx()
.emit_err(crate::errors::NonConstRange { span: expr.span });
(ty::Const::new_error(tcx, err), Ty::new_error(tcx, err))
}
};
self.record_ty(expr.hir_id, c_ty, expr.span);
c
};
let start = start.map(expr_to_const);
let end = end.map(expr_to_const);
let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
let include_end = match include_end {
hir::RangeEnd::Included => true,
@ -2509,12 +2459,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
Ty::new_pat(tcx, ty, pat)
}
hir::PatKind::Err(e) => Ty::new_error(tcx, e),
_ => Ty::new_error_with_message(
tcx,
pat.span,
format!("unsupported pattern for pattern type: {pat:#?}"),
),
hir::TyPatKind::Err(e) => Ty::new_error(tcx, e),
};
self.record_ty(pat.hir_id, ty, pat.span);
pat_ty