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

@ -412,8 +412,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p)
fn visit_pattern_type_pattern(&mut self, pat: &'hir hir::TyPat<'hir>) {
self.insert(pat.span, pat.hir_id, Node::TyPat(pat));
self.with_parent(pat.hir_id, |this| {
intravisit::walk_ty_pat(this, pat);
});
}
fn visit_precise_capturing_arg(

View file

@ -1377,7 +1377,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
}
TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)),
TyKind::Pat(ty, pat) => {
hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
}
TyKind::MacCall(_) => {
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
}

View file

@ -4,10 +4,10 @@ use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::span_bug;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{Ident, Span};
use rustc_span::{Ident, Span, kw};
use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@ -429,4 +429,80 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
}
pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> {
self.arena.alloc(self.lower_ty_pat_mut(pattern))
}
fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> {
// loop here to avoid recursion
let pat_hir_id = self.lower_node_id(pattern.id);
let node = loop {
match &pattern.kind {
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
let mut lower_expr = |e: &Expr| -> &_ {
let kind = if let ExprKind::Path(qself, path) = &e.kind {
hir::ConstArgKind::Path(self.lower_qpath(
e.id,
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
))
} else {
let node_id = self.next_node_id();
let def_id = self.create_def(
self.current_hir_id_owner.def_id,
node_id,
kw::Empty,
DefKind::AnonConst,
e.span,
);
let hir_id = self.lower_node_id(node_id);
let ac = self.arena.alloc(hir::AnonConst {
def_id,
hir_id,
body: self.lower_const_body(pattern.span, Some(e)),
span: self.lower_span(pattern.span),
});
hir::ConstArgKind::Anon(ac)
};
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind })
};
break hir::TyPatKind::Range(
e1.as_deref().map(|e| lower_expr(e)),
e2.as_deref().map(|e| lower_expr(e)),
self.lower_range_end(end, e2.is_some()),
);
}
// return inner to be processed in next loop
PatKind::Paren(inner) => pattern = inner,
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
PatKind::Err(guar) => break hir::TyPatKind::Err(*guar),
PatKind::Deref(..)
| PatKind::Box(..)
| PatKind::Or(..)
| PatKind::Struct(..)
| PatKind::TupleStruct(..)
| PatKind::Tuple(..)
| PatKind::Ref(..)
| PatKind::Expr(..)
| PatKind::Guard(..)
| PatKind::Slice(_)
| PatKind::Ident(..)
| PatKind::Path(..)
| PatKind::Wild
| PatKind::Never
| PatKind::Rest => {
break hir::TyPatKind::Err(
self.dcx().span_err(pattern.span, "pattern not supported in pattern types"),
);
}
}
};
hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
}
}

View file

@ -101,6 +101,10 @@ impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
s.s.space();
s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
}
pprust_hir::AnnNode::TyPat(pat) => {
s.s.space();
s.synth_comment(format!("ty pat hir_id: {}", pat.hir_id));
}
pprust_hir::AnnNode::Arm(arm) => {
s.s.space();
s.synth_comment(format!("arm hir_id: {}", arm.hir_id));

View file

@ -1418,6 +1418,14 @@ impl<'hir> Block<'hir> {
}
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct TyPat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub kind: TyPatKind<'hir>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Pat<'hir> {
#[stable_hasher(ignore)]
@ -1591,6 +1599,15 @@ pub enum PatExprKind<'hir> {
Path(QPath<'hir>),
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TyPatKind<'hir> {
/// A range pattern (e.g., `1..=2` or `1..2`).
Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
/// A placeholder for a pattern that wasn't well formed in some way.
Err(ErrorGuaranteed),
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum PatKind<'hir> {
/// Represents a wildcard pattern (i.e., `_`).
@ -3345,7 +3362,7 @@ pub enum TyKind<'hir, Unambig = ()> {
/// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed),
/// Pattern types (`pattern_type!(u32 is 1..)`)
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
/// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
///
@ -4331,6 +4348,7 @@ pub enum Node<'hir> {
AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
TraitRef(&'hir TraitRef<'hir>),
OpaqueTy(&'hir OpaqueTy<'hir>),
TyPat(&'hir TyPat<'hir>),
Pat(&'hir Pat<'hir>),
PatField(&'hir PatField<'hir>),
/// Needed as its own node with its own HirId for tracking
@ -4393,6 +4411,7 @@ impl<'hir> Node<'hir> {
| Node::Block(..)
| Node::Ctor(..)
| Node::Pat(..)
| Node::TyPat(..)
| Node::PatExpr(..)
| Node::Arm(..)
| Node::LetStmt(..)

View file

@ -393,10 +393,8 @@ pub trait Visitor<'v>: Sized {
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
walk_expr_field(self, field)
}
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
// Do nothing. Only a few visitors need to know the details of the pattern type,
// and they opt into it. All other visitors will just choke on our fake patterns
// because they aren't in a body.
fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
walk_ty_pat(self, p)
}
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
walk_generic_param(self, p)
@ -702,6 +700,18 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res
visitor.visit_expr(arm.body)
}
pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
try_visit!(visitor.visit_id(pattern.hir_id));
match pattern.kind {
TyPatKind::Range(lower_bound, upper_bound, _) => {
visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
}
TyPatKind::Err(_) => (),
}
V::Result::output()
}
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
try_visit!(visitor.visit_id(pattern.hir_id));
match pattern.kind {

View file

@ -436,9 +436,6 @@ hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a t
hir_analysis_parenthesized_fn_trait_expansion =
parenthesized trait syntax expands to `{$expanded_type}`
hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end
hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types
.label = this type is the same as the inner type without a pattern
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
.label = not allowed in type signatures
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias

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

View file

@ -18,7 +18,7 @@ use rustc_ast_pretty::pprust::state::MacHeader;
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir::{
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TyPatKind,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, Ident, Span, Symbol, kw};
@ -35,6 +35,7 @@ pub enum AnnNode<'a> {
SubItem(HirId),
Expr(&'a hir::Expr<'a>),
Pat(&'a hir::Pat<'a>),
TyPat(&'a hir::TyPat<'a>),
Arm(&'a hir::Arm<'a>),
}
@ -198,6 +199,7 @@ impl<'a> State<'a> {
Node::TraitRef(a) => self.print_trait_ref(a),
Node::OpaqueTy(o) => self.print_opaque_ty(o),
Node::Pat(a) => self.print_pat(a),
Node::TyPat(a) => self.print_ty_pat(a),
Node::PatField(a) => self.print_patfield(a),
Node::PatExpr(a) => self.print_pat_expr(a),
Node::Arm(a) => self.print_arm(a),
@ -224,6 +226,16 @@ impl<'a> State<'a> {
Node::Err(_) => self.word("/*ERROR*/"),
}
}
fn print_generic_arg(&mut self, generic_arg: &GenericArg<'_>, elide_lifetimes: bool) {
match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => self.print_lifetime(lt),
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => self.print_type(ty.as_unambig_ty()),
GenericArg::Const(ct) => self.print_const_arg(ct.as_unambig_ct()),
GenericArg::Infer(_inf) => self.word("_"),
}
}
}
impl std::ops::Deref for State<'_> {
@ -448,7 +460,7 @@ impl<'a> State<'a> {
hir::TyKind::Pat(ty, pat) => {
self.print_type(ty);
self.word(" is ");
self.print_pat(pat);
self.print_ty_pat(pat);
}
}
self.end()
@ -1797,13 +1809,7 @@ impl<'a> State<'a> {
if nonelided_generic_args {
start_or_comma(self);
self.commasep(Inconsistent, generic_args.args, |s, generic_arg| {
match generic_arg {
GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
GenericArg::Lifetime(_) => {}
GenericArg::Type(ty) => s.print_type(ty.as_unambig_ty()),
GenericArg::Const(ct) => s.print_const_arg(ct.as_unambig_ct()),
GenericArg::Infer(_inf) => s.word("_"),
}
s.print_generic_arg(generic_arg, elide_lifetimes)
});
}
@ -1864,6 +1870,33 @@ impl<'a> State<'a> {
}
}
fn print_ty_pat(&mut self, pat: &hir::TyPat<'_>) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::TyPat(pat));
// Pat isn't normalized, but the beauty of it
// is that it doesn't matter
match pat.kind {
TyPatKind::Range(begin, end, end_kind) => {
if let Some(expr) = begin {
self.print_const_arg(expr);
}
match end_kind {
RangeEnd::Included => self.word("..."),
RangeEnd::Excluded => self.word(".."),
}
if let Some(expr) = end {
self.print_const_arg(expr);
}
}
TyPatKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
}
}
self.ann.post(self, AnnNode::TyPat(pat))
}
fn print_pat(&mut self, pat: &hir::Pat<'_>) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));

View file

@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => true,
hir::Node::Pat(_) => {
hir::Node::TyPat(_) | hir::Node::Pat(_) => {
self.dcx().span_delayed_bug(expr.span, "place expr not allowed in pattern");
true
}

View file

@ -937,6 +937,7 @@ impl<'hir> Map<'hir> {
Node::TraitRef(tr) => tr.path.span,
Node::OpaqueTy(op) => op.span,
Node::Pat(pat) => pat.span,
Node::TyPat(pat) => pat.span,
Node::PatField(field) => field.span,
Node::PatExpr(lit) => lit.span,
Node::Arm(arm) => arm.span,
@ -1212,6 +1213,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Node::TraitRef(_) => node_str("trait ref"),
Node::OpaqueTy(_) => node_str("opaque type"),
Node::Pat(_) => node_str("pat"),
Node::TyPat(_) => node_str("pat ty"),
Node::PatField(_) => node_str("pattern field"),
Node::PatExpr(_) => node_str("pattern literal"),
Node::Param(_) => node_str("param"),

View file

@ -162,7 +162,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
}
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p)
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::TyPat<'hir>) {
intravisit::walk_ty_pat(self, p)
}
}

View file

@ -10,7 +10,7 @@ use rustc_hir::{
AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField,
ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName,
Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
TraitBoundModifiers, Ty, TyKind,
TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::LateContext;
@ -1102,6 +1102,22 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
}
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
TyPatKind::Range(s, e, i) => {
if let Some(s) = s {
self.hash_const_arg(s);
}
if let Some(e) = e {
self.hash_const_arg(e);
}
std::mem::discriminant(&i).hash(&mut self.s);
},
TyPatKind::Err(_) => {},
}
}
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
@ -1247,7 +1263,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
},
TyKind::Pat(ty, pat) => {
self.hash_ty(ty);
self.hash_pat(pat);
self.hash_ty_pat(pat);
},
TyKind::Ptr(mut_ty) => {
self.hash_ty(mut_ty.ty);

View file

@ -6,5 +6,6 @@ type Pat<const START: u32, const END: u32> =
//~^ ERROR type and const arguments are not allowed on const parameter `START`
//~| ERROR generic arguments are not allowed on const parameter `END`
//~| ERROR associated item constraints are not allowed here
//~| ERROR `_` is not allowed within types on item signatures for type aliases
fn main() {}

View file

@ -32,7 +32,13 @@ error[E0229]: associated item constraints are not allowed here
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ^^^^^^^^^^ associated item constraint not allowed here
error: aborting due to 3 previous errors
error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
--> $DIR/bad_const_generics_args_on_const_param.rs:5:64
|
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
| ^ not allowed in type signatures
Some errors have detailed explanations: E0109, E0229.
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0109, E0121, E0229.
For more information about an error, try `rustc --explain E0109`.

View file

@ -8,6 +8,6 @@ type NonNullU32_2 = pattern_type!(u32 is 1..=);
type Positive2 = pattern_type!(i32 is 0..=);
//~^ ERROR: inclusive range with no end
type Wild = pattern_type!(() is _);
//~^ ERROR: wildcard patterns are not permitted for pattern types
//~^ ERROR: pattern not supported in pattern types
fn main() {}

View file

@ -24,7 +24,7 @@ LL - type Positive2 = pattern_type!(i32 is 0..=);
LL + type Positive2 = pattern_type!(i32 is 0..);
|
error: wildcard patterns are not permitted for pattern types
error: pattern not supported in pattern types
--> $DIR/bad_pat.rs:10:33
|
LL | type Wild = pattern_type!(() is _);

View file

@ -9,16 +9,20 @@ use std::pat::pattern_type;
// or still validate correctly.
const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
//~^ ERROR: not a valid base type for range patterns
//~| ERROR: mismatched types
// We want to get the most narrowest version that a pattern could be
const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
//~^ ERROR: not a valid base type for range patterns
//~| ERROR: mismatched types
const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
//~^ ERROR: not a valid base type for range patterns
//~| ERROR: mismatched types
const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
//~^ ERROR: not a valid base type for range patterns
//~| ERROR: mismatched types
const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
//~^ ERROR: not a valid base type for range patterns

View file

@ -11,52 +11,86 @@ LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(
| ^^^
error: `(i32) is 1..=` is not a valid base type for range patterns
--> $DIR/nested.rs:14:35
--> $DIR/nested.rs:15:35
|
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: range patterns only support integers
--> $DIR/nested.rs:14:64
--> $DIR/nested.rs:15:64
|
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
| ^^^^^
error: `(i32) is 1..=` is not a valid base type for range patterns
--> $DIR/nested.rs:17:35
--> $DIR/nested.rs:19:35
|
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: range patterns only support integers
--> $DIR/nested.rs:17:64
--> $DIR/nested.rs:19:64
|
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
| ^^^
error: `()` is not a valid base type for range patterns
--> $DIR/nested.rs:20:35
--> $DIR/nested.rs:23:35
|
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
| ^^
|
note: range patterns only support integers
--> $DIR/nested.rs:20:41
--> $DIR/nested.rs:23:41
|
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
| ^^^
error: `f32` is not a valid base type for range patterns
--> $DIR/nested.rs:23:35
--> $DIR/nested.rs:27:35
|
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
| ^^^
|
note: range patterns only support integers
--> $DIR/nested.rs:23:42
--> $DIR/nested.rs:27:42
|
LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
| ^^^^^^^^^^
error: aborting due to 5 previous errors
error[E0308]: mismatched types
--> $DIR/nested.rs:10:63
|
LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
| ^ expected `(u32) is 1..=`, found integer
|
= note: expected pattern type `(u32) is 1..=`
found type `{integer}`
error[E0308]: mismatched types
--> $DIR/nested.rs:15:67
|
LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
| ^^ expected `(i32) is 1..=`, found integer
|
= note: expected pattern type `(i32) is 1..=`
found type `{integer}`
error[E0308]: mismatched types
--> $DIR/nested.rs:19:66
|
LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
| ^ expected `(i32) is 1..=`, found integer
|
= note: expected pattern type `(i32) is 1..=`
found type `{integer}`
error[E0308]: mismatched types
--> $DIR/nested.rs:23:43
|
LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
| ^ expected `()`, found integer
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,20 +1,16 @@
//! Check that pattern types patterns must be of the type of the base type
//@ known-bug: unknown
//@ failure-status: 101
//@ normalize-stderr: "note: .*\n\n" -> ""
//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
//@ normalize-stderr: "(delayed at compiler/rustc_mir_transform/src/lib.rs:)\d+:\d+" -> "$1:LL:CC"
//@ rustc-env:RUST_BACKTRACE=0
#![feature(pattern_types)]
#![feature(pattern_type_macro)]
use std::pat::pattern_type;
const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
//~^ ERROR: mismatched types
//~| ERROR: mismatched types
const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
//~^ ERROR: mismatched types
//~| ERROR: mismatched types
fn main() {}

View file

@ -1,31 +1,37 @@
error: internal compiler error: ty::ConstKind::Error constructed but no error reported
|
= error: internal compiler error: ty::ConstKind::Error constructed but no error reported
|
= note: delayed at compiler/rustc_mir_build/src/thir/constant.rs:72:21 - disabled backtrace
= error: internal compiler error: mir_const_qualif: MIR had errors
--> $DIR/pattern_type_mismatch.rs:16:1
error[E0308]: mismatched types
--> $DIR/pattern_type_mismatch.rs:8:41
|
LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^ expected `u8`, found `char`
|
note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
--> $DIR/pattern_type_mismatch.rs:16:1
help: if you meant to write a byte literal, prefix with `b`
|
LL | const BAD_NESTING4: pattern_type!(u8 is b'a'..='a') = todo!();
| ~~~~
error[E0308]: mismatched types
--> $DIR/pattern_type_mismatch.rs:8:47
|
LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^ expected `u8`, found `char`
|
help: if you meant to write a byte literal, prefix with `b`
|
LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..=b'a') = todo!();
| ~~~~
error: internal compiler error: mir_const_qualif: MIR had errors
--> $DIR/pattern_type_mismatch.rs:18:1
error[E0308]: mismatched types
--> $DIR/pattern_type_mismatch.rs:12:43
|
LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
--> $DIR/pattern_type_mismatch.rs:18:1
| ^ expected `char`, found `u8`
error[E0308]: mismatched types
--> $DIR/pattern_type_mismatch.rs:12:47
|
LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^ expected `char`, found `u8`
query stack during panic:
end of query stack
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,14 +1,14 @@
//! This test ensures we do not ICE for unimplemented
//! patterns unless the feature gate is enabled.
//! patterns even if the feature gate is enabled.
#![feature(pattern_type_macro)]
#![feature(pattern_type_macro, pattern_types)]
use std::pat::pattern_type;
type Always = pattern_type!(Option<u32> is Some(_));
//~^ ERROR: pattern types are unstable
//~^ ERROR: pattern not supported
type Binding = pattern_type!(Option<u32> is x);
//~^ ERROR: pattern types are unstable
//~^ ERROR: pattern not supported
fn main() {}

View file

@ -1,23 +1,14 @@
error[E0658]: pattern types are unstable
--> $DIR/unimplemented_pat.rs:8:15
error: pattern not supported in pattern types
--> $DIR/unimplemented_pat.rs:8:44
|
LL | type Always = pattern_type!(Option<u32> is Some(_));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(pattern_types)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
| ^^^^^^^
error[E0658]: pattern types are unstable
--> $DIR/unimplemented_pat.rs:11:16
error: pattern not supported in pattern types
--> $DIR/unimplemented_pat.rs:11:45
|
LL | type Binding = pattern_type!(Option<u32> is x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
= help: add `#![feature(pattern_types)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
| ^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.