From b993b7acb7999cbaaca32ccfbb9fecb16dfcf726 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 2 Feb 2023 13:57:36 +0000 Subject: [PATCH] Actually create ranged int types in the type system. --- compiler/rustc_borrowck/src/lib.rs | 2 + .../src/debuginfo/type_names.rs | 9 ++ .../src/const_eval/valtrees.rs | 7 +- .../src/interpret/eval_context.rs | 2 + .../src/interpret/intrinsics.rs | 3 + .../src/interpret/validity.rs | 1 + .../rustc_const_eval/src/util/type_name.rs | 1 + compiler/rustc_hir_analysis/messages.ftl | 1 + .../rustc_hir_analysis/src/astconv/mod.rs | 90 +++++++++++++++---- .../src/coherence/inherent_impls.rs | 4 + .../src/coherence/orphan.rs | 5 ++ compiler/rustc_hir_analysis/src/errors.rs | 7 ++ .../src/variance/constraints.rs | 14 +++ compiler/rustc_hir_typeck/src/cast.rs | 1 + .../src/infer/canonical/canonicalizer.rs | 1 + .../src/infer/outlives/components.rs | 1 + compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/types.rs | 6 ++ compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/ty/codec.rs | 12 +++ compiler/rustc_middle/src/ty/context.rs | 12 ++- compiler/rustc_middle/src/ty/error.rs | 1 + compiler/rustc_middle/src/ty/fast_reject.rs | 6 ++ compiler/rustc_middle/src/ty/flags.rs | 14 +++ compiler/rustc_middle/src/ty/layout.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 2 + compiler/rustc_middle/src/ty/pattern.rs | 48 ++++++++++ compiler/rustc_middle/src/ty/print/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 3 + compiler/rustc_middle/src/ty/relate.rs | 45 ++++++++++ .../rustc_middle/src/ty/structural_impls.rs | 40 +++++++++ compiler/rustc_middle/src/ty/sty.rs | 13 +++ compiler/rustc_middle/src/ty/util.rs | 15 ++-- compiler/rustc_middle/src/ty/walk.rs | 9 ++ .../src/move_paths/builder.rs | 2 + .../src/dataflow_const_prop.rs | 1 + .../src/canonicalizer.rs | 1 + compiler/rustc_pattern_analysis/src/rustc.rs | 1 + compiler/rustc_privacy/src/lib.rs | 1 + .../rustc_smir/src/rustc_internal/internal.rs | 20 ++++- .../rustc_smir/src/rustc_smir/convert/ty.rs | 17 ++++ .../src/typeid/typeid_itanium_cxx_abi.rs | 14 +++ compiler/rustc_symbol_mangling/src/v0.rs | 19 ++++ .../src/solve/assembly/mod.rs | 3 + .../src/solve/assembly/structural_traits.rs | 7 +- .../src/solve/normalizes_to/mod.rs | 2 + .../src/solve/trait_goals.rs | 1 + .../src/traits/coherence.rs | 1 + .../error_reporting/type_err_ctxt_ext.rs | 1 + .../src/traits/project.rs | 4 +- .../src/traits/query/dropck_outlives.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 5 ++ .../src/traits/select/mod.rs | 9 +- .../src/traits/structural_match.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 6 +- compiler/rustc_ty_utils/src/layout.rs | 25 ++++++ compiler/rustc_ty_utils/src/needs_drop.rs | 6 +- compiler/rustc_ty_utils/src/ty.rs | 2 + compiler/rustc_type_ir/src/interner.rs | 1 + compiler/rustc_type_ir/src/ty_kind.rs | 9 +- compiler/stable_mir/src/ty.rs | 7 ++ compiler/stable_mir/src/visitor.rs | 1 + src/librustdoc/clean/mod.rs | 4 + .../passes/collect_intra_doc_links.rs | 1 + .../clippy/clippy_lints/src/dereference.rs | 3 +- tests/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- tests/ui/type/pattern_types/range_patterns.rs | 9 ++ 68 files changed, 530 insertions(+), 51 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/pattern.rs create mode 100644 tests/ui/type/pattern_types/range_patterns.rs diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b304fb5589f37..5f8fce6af82b8 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1608,6 +1608,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(_) @@ -1646,6 +1647,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 4f9f70648bd88..95fd73aebd81f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -201,6 +201,15 @@ fn push_debuginfo_type_name<'tcx>( } } } + ty::Pat(inner_type, pat) => { + if cpp_like_debuginfo { + output.push_str("pat$<"); + push_debuginfo_type_name(tcx, inner_type, true, output, visited); + write!(output, ",{:?}>", pat).unwrap(); + } else { + write!(output, "{:?}", t).unwrap(); + } + } ty::Slice(inner_type) => { if cpp_like_debuginfo { output.push_str("slice2$<"); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 707bb8d893336..08de770ff4734 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -97,6 +97,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::Leaf(val.assert_int())) } + ty::Pat(..) => const_to_valtree_inner(ecx, &ecx.project_field(place, 0).unwrap(), num_nodes), + ty::RawPtr(_) => { // Not all raw pointers are allowed, as we cannot properly test them for // equality at compile-time (see `ptr_guaranteed_cmp`). @@ -238,7 +240,7 @@ pub fn valtree_to_const_value<'tcx>( let (param_env, ty) = param_env_ty.into_parts(); - match ty.kind() { + match *ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); mir::ConstValue::ZeroSized @@ -251,9 +253,10 @@ pub fn valtree_to_const_value<'tcx>( ), } } + ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), ty::Ref(_, inner_ty, _) => { let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); - let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty); + let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap()); op_to_const(&ecx, &imm.into(), /* for diagnostics */ false) } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index e6370adb983a7..6e367b96624d1 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1014,6 +1014,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)), + ty::Pat(ty, ..) => is_very_trivially_sized(*ty), + // We don't want to do any queries, so there is not much we can do with ADTs. ty::Adt(..) => false, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e9e7d94596f8..b852b71a54900 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -69,6 +69,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => { throw_inval!(TooGeneric) } + ty::Pat(..) => { + unimplemented!("pattern types need to calculate pattern from their pattern") + } ty::Bound(_, _) => bug!("bound ty during ctfe"), ty::Bool | ty::Char diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 8b44b87647dab..b354726863698 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -571,6 +571,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Nothing to check. Ok(true) } + ty::Pat(..) => unimplemented!(), // The above should be all the primitive types. The rest is compound, we // check them by visiting their fields/variants. ty::Adt(..) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 976e42ad76836..e9c0f33dafb6d 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -31,6 +31,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Uint(_) | ty::Float(_) | ty::Str + | ty::Pat(_, _) | ty::Array(_, _) | ty::Slice(_) | ty::RawPtr(_) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index c1aebb4c0fb8f..9fe3a2efbdfe1 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -299,6 +299,7 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function .suggestion = cast the value to `{$cast_ty}` .help = cast the value to `{$cast_ty}` +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} diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 299c7c3f5dc0e..8daabaf2ceadb 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; +use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, TyCtxt, TypeVisitableExt, @@ -2559,25 +2560,76 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } - hir::TyKind::Pat(_ty, pat) => match pat.kind { - hir::PatKind::Wild => { - let err = tcx.dcx().emit_err(WildPatTy { span: pat.span }); - Ty::new_error(tcx, err) - } - hir::PatKind::Binding(_, _, _, _) => todo!(), - hir::PatKind::Struct(_, _, _) => todo!(), - hir::PatKind::TupleStruct(_, _, _) => todo!(), - hir::PatKind::Or(_) => todo!(), - hir::PatKind::Path(_) => todo!(), - hir::PatKind::Tuple(_, _) => todo!(), - hir::PatKind::Box(_) => todo!(), - hir::PatKind::Ref(_, _) => todo!(), - hir::PatKind::Lit(_) => todo!(), - hir::PatKind::Range(_, _, _) => Ty::new_misc_error(tcx), - hir::PatKind::Slice(_, _, _) => todo!(), - hir::PatKind::Never => todo!(), - hir::PatKind::Err(e) => Ty::new_error(tcx, e), - }, + hir::TyKind::Pat(ty, pat) => { + let ty = self.ast_ty_to_ty(ty); + let pat_ty = match pat.kind { + hir::PatKind::Wild => { + let err = tcx.dcx().emit_err(WildPatTy { span: pat.span }); + Ty::new_error(tcx, err) + } + hir::PatKind::Binding(_, _, _, _) => todo!(), + hir::PatKind::Struct(_, _, _) => todo!(), + hir::PatKind::TupleStruct(_, _, _) => todo!(), + hir::PatKind::Or(_) => todo!(), + hir::PatKind::Path(_) => todo!(), + hir::PatKind::Tuple(_, _) => todo!(), + hir::PatKind::Box(_) => todo!(), + hir::PatKind::Ref(_, _) => todo!(), + hir::PatKind::Lit(_) => todo!(), + hir::PatKind::Range(start, end, include_end) => { + let expr_to_const = |expr: &'tcx hir::Expr<'tcx>, neg| -> ty::Const<'tcx> { + match &expr.kind { + hir::ExprKind::Lit(lit) => { + let lit_input = LitToConstInput { lit: &lit.node, ty, neg }; + match tcx.lit_to_const(lit_input) { + Ok(c) => c, + Err(LitToConstError::Reported(err)) => { + ty::Const::new_error(tcx, err, ty) + } + Err(LitToConstError::TypeError) => todo!(), + } + } + _ => { + let err = tcx + .dcx() + .emit_err(crate::errors::NonConstRange { span: expr.span }); + ty::Const::new_error(tcx, err, ty) + } + } + }; + let expr_to_const = |expr, neg| { + let c = expr_to_const(expr, neg); + self.record_ty(expr.hir_id, c.ty(), expr.span); + c + }; + let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| match &expr.kind { + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => expr_to_const(expr, true), + _ => expr_to_const(expr, false), + }; + let expr_to_const = |expr| { + let c = expr_to_const(expr); + 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 include_end = match include_end { + hir::RangeEnd::Included => true, + hir::RangeEnd::Excluded => false, + }; + + let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end }); + Ty::new_pat(tcx, ty, pat) + } + hir::PatKind::Slice(_, _, _) => todo!(), + hir::PatKind::Never => todo!(), + hir::PatKind::Err(e) => Ty::new_error(tcx, e), + }; + self.record_ty(pat.hir_id, ty, pat.span); + pat_ty + } hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar), }; diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index abef365c3ca3c..6860b55f37b25 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -153,6 +153,10 @@ impl<'tcx> InherentCollect<'tcx> { ty::Dynamic(..) => { Err(self.tcx.dcx().emit_err(errors::InherentDyn { span: item_span })) } + ty::Pat(..) => Err(self + .tcx + .dcx() + .span_err(item_span, "cannot define inherent `impl` for pattern types")), ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c1d0e0444b673..cfe74646956a3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -228,6 +228,11 @@ fn do_orphan_check_impl<'tcx>( (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) } + ty::Pat(..) => ( + LocalImpl::Disallow { problematic_kind: "pattern type" }, + NonlocalImpl::DisallowOther, + ), + ty::Bool | ty::Char | ty::Int(..) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index a7e2fcc5d5500..c8fff7cb46b8b 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1513,3 +1513,10 @@ pub struct NotSupportedDelegation<'a> { #[label] pub callee_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_pattern_type_non_const_range)] +pub struct NonConstRange { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index f09594cbbc667..b09012254a928 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -249,6 +249,20 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_ty(current, typ, variance); } + ty::Pat(typ, pat) => { + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + if let Some(start) = start { + self.add_constraints_from_const(current, start, variance); + } + if let Some(end) = end { + self.add_constraints_from_const(current, end, variance); + } + } + } + self.add_constraints_from_ty(current, typ, variance); + } + ty::Slice(typ) => { self.add_constraints_from_ty(current, typ, variance); } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index a720a858f3c13..a35a4ebc131b8 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -130,6 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::CoroutineWitness(..) | ty::RawPtr(_) | ty::Ref(..) + | ty::Pat(..) | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index e4b37f05b778f..57e28a1241786 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -435,6 +435,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { | ty::Tuple(..) | ty::Alias(..) | ty::Foreign(..) + | ty::Pat(..) | ty::Param(..) => { if t.flags().intersects(self.needs_canonical_flags) { t.super_fold_with(self) diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index fc3d8375873b0..6c60bd15521b2 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -93,6 +93,7 @@ fn compute_components<'tcx>( } } + ty::Pat(element, _) | ty::Array(element, _) => { // Don't look into the len const as it doesn't affect regions compute_components(tcx, element, out, visited); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index b6fa2f1f22163..a3fafe75ca64a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -274,6 +274,9 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData` lint_improper_ctypes_opaque = opaque types have no C equivalent +lint_improper_ctypes_pat_help = consider using the patterned type instead + +lint_improper_ctypes_pat_reason = pattern types have no C equivalent lint_improper_ctypes_slice_help = consider using a raw pointer instead lint_improper_ctypes_slice_reason = slices have no C equivalent diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index a86fe2db2b2d5..8817f7c1598cc 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1335,6 +1335,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: Some(fluent::lint_improper_ctypes_char_help), }, + ty::Pat(..) => FfiUnsafe { + ty, + reason: fluent::lint_improper_ctypes_pat_reason, + help: Some(fluent::lint_improper_ctypes_pat_help), + }, + ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => { FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None } } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e745913fabc37..074cef7543a01 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -91,6 +91,7 @@ macro_rules! arena_types { [decode] attribute: rustc_ast::Attribute, [] name_set: rustc_data_structures::unord::UnordSet, [] ordered_name_set: rustc_data_structures::fx::FxIndexSet, + [] pats: rustc_middle::ty::PatternKind<'tcx>, // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 69ae05ca820a3..822b7b75e12fb 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -147,6 +147,12 @@ impl<'tcx, E: TyEncoder>> Encodable for ty::Const<'tcx> { } } +impl<'tcx, E: TyEncoder>> Encodable for ty::Pattern<'tcx> { + fn encode(&self, e: &mut E) { + self.0.0.encode(e); + } +} + impl<'tcx, E: TyEncoder>> Encodable for ConstAllocation<'tcx> { fn encode(&self, e: &mut E) { self.inner().encode(e) @@ -363,6 +369,12 @@ impl<'tcx, D: TyDecoder>> Decodable for ty::Const<'tcx> { } } +impl<'tcx, D: TyDecoder>> Decodable for ty::Pattern<'tcx> { + fn decode(decoder: &mut D) -> Self { + decoder.interner().mk_pat(Decodable::decode(decoder)) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [ty::ValTree<'tcx>] { fn decode(decoder: &mut D) -> &'tcx Self { decoder diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6807eacb7f177..6a65dd7d920c5 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -26,9 +26,9 @@ use crate::traits::solve::{ }; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind, - ImplPolarity, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, - PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, - Visibility, + ImplPolarity, List, ParamConst, ParamTy, Pattern, PatternKind, PolyExistentialPredicate, + PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, + TyKind, TyVid, Visibility, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; @@ -91,6 +91,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; + type Pat = Pattern<'tcx>; type Tys = &'tcx List>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; @@ -173,6 +174,7 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, WithCachedTypeInfo>>, + pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, @@ -200,6 +202,7 @@ impl<'tcx> CtxtInterners<'tcx> { projs: Default::default(), place_elems: Default::default(), const_: Default::default(), + pat: Default::default(), const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), @@ -1413,6 +1416,7 @@ macro_rules! nop_list_lift { nop_lift! {type_; Ty<'a> => Ty<'tcx>} nop_lift! {region; Region<'a> => Region<'tcx>} nop_lift! {const_; Const<'a> => Const<'tcx>} +nop_lift! {pat; Pattern<'a> => Pattern<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} nop_lift! {predicate; Clause<'a> => Clause<'tcx>} @@ -1528,6 +1532,7 @@ impl<'tcx> TyCtxt<'tcx> { Param, Infer, Alias, + Pat, Foreign )?; @@ -1656,6 +1661,7 @@ macro_rules! direct_interners { // crate only, and have a corresponding `mk_` function. direct_interners! { region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>, + pat: pub mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>, const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 0e44878524bf0..2d19123cbf55d 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -285,6 +285,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(def, _) => def.descr().into(), ty::Foreign(_) => "extern type".into(), ty::Array(..) => "array".into(), + ty::Pat(..) => "pattern type".into(), ty::Slice(_) => "slice".into(), ty::RawPtr(_) => "raw pointer".into(), ty::Ref(.., mutbl) => match mutbl { diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index b71919adc58fa..6fb2c675d6684 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -19,6 +19,7 @@ pub enum SimplifiedType { Str, Array, Slice, + Pat, Ref(Mutability), Ptr(Mutability), Never, @@ -120,6 +121,7 @@ pub fn simplify_type<'tcx>( ty::Str => Some(SimplifiedType::Str), ty::Array(..) => Some(SimplifiedType::Array), ty::Slice(..) => Some(SimplifiedType::Slice), + ty::Pat(..) => Some(SimplifiedType::Pat), ty::RawPtr(ptr) => Some(SimplifiedType::Ptr(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { @@ -229,6 +231,7 @@ impl DeepRejectCtxt { | ty::Slice(..) | ty::RawPtr(..) | ty::Dynamic(..) + | ty::Pat(..) | ty::Ref(..) | ty::Never | ty::Tuple(..) @@ -266,6 +269,9 @@ impl DeepRejectCtxt { } _ => false, }, + ty::Pat(obl_ty, _) => { + matches!(k, &ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty)) + } ty::Slice(obl_ty) => { matches!(k, &ty::Slice(impl_ty) if self.types_may_unify(obl_ty, impl_ty)) } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0c1d10914146f..fa49503b1a1a5 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -192,6 +192,20 @@ impl FlagComputation { self.add_const(len); } + &ty::Pat(ty, pat) => { + self.add_ty(ty); + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + if let Some(start) = start { + self.add_const(start) + } + if let Some(end) = end { + self.add_const(end) + } + } + } + } + &ty::Slice(tt) => self.add_ty(tt), ty::RawPtr(m) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 25473f52c039e..085b0943df89b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -812,6 +812,7 @@ where | ty::FnDef(..) | ty::CoroutineWitness(..) | ty::Foreign(..) + | ty::Pat(_, _) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a5d9e0fcf44cd..a29a6e1a5a481 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -86,6 +86,7 @@ pub use self::context::{ pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; +pub use self::pattern::{Pattern, PatternKind}; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::BoundRegionKind::*; pub use self::sty::{ @@ -116,6 +117,7 @@ pub mod fold; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; +pub mod pattern; pub mod print; pub mod relate; pub mod trait_def; diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs new file mode 100644 index 0000000000000..ab1cc9f0a979f --- /dev/null +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -0,0 +1,48 @@ +use std::fmt; + +use crate::ty; +use rustc_data_structures::intern::Interned; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Pattern<'tcx>(pub Interned<'tcx, PatternKind<'tcx>>); + +impl<'tcx> std::ops::Deref for Pattern<'tcx> { + type Target = PatternKind<'tcx>; + + fn deref(&self) -> &Self::Target { + &*self.0 + } +} + +impl<'tcx> fmt::Debug for Pattern<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", **self) + } +} + +impl<'tcx> fmt::Debug for PatternKind<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + PatternKind::Range { start, end, include_end } => { + if let Some(start) = start { + write!(f, "{start}")?; + } + write!(f, "..")?; + if include_end { + write!(f, "=")?; + } + if let Some(end) = end { + write!(f, "{end}")?; + } + Ok(()) + } + } + } +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] +pub enum PatternKind<'tcx> { + Range { start: Option>, end: Option>, include_end: bool }, +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index f32b7b0852abc..c78349e882ad5 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -242,7 +242,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Dynamic(data, ..) => data.principal_def_id(), - ty::Array(subty, _) | ty::Slice(subty) => { + ty::Pat(subty, _) | ty::Array(subty, _) | ty::Slice(subty) => { characteristic_def_id_of_type_cached(subty, visited) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 4028de27cae14..2e8bbc178b58a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -633,6 +633,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::Int(t) => p!(write("{}", t.name_str())), ty::Uint(t) => p!(write("{}", t.name_str())), ty::Float(t) => p!(write("{}", t.name_str())), + ty::Pat(ty, pat) => { + p!("(", print(ty), ") is ", write("{pat:?}")) + } ty::RawPtr(ref tm) => { p!(write( "*{} ", diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8543bd0bbdd96..74339c62ab01b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -13,6 +13,8 @@ use rustc_hir::def_id::DefId; use rustc_target::spec::abi; use std::iter; +use super::Pattern; + pub type RelateResult<'tcx, T> = Result>; #[derive(Clone, Debug)] @@ -401,6 +403,29 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { } } +impl<'tcx> Relate<'tcx> for Pattern<'tcx> { + #[inline] + fn relate>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + match (&*a, &*b) { + ( + &ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a }, + &ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b }, + ) => { + let start = relation.relate(start_a, start_b)?; + let end = relation.relate(end_a, end_b)?; + if inc_a != inc_b { + todo!() + } + Ok(relation.tcx().mk_pat(ty::PatternKind::Range { start, end, include_end: inc_a })) + } + } + } +} + /// Relates `a` and `b` structurally, calling the relation for all nested values. /// Any semantic equality, e.g. of projections, and inference variables have to be /// handled by the caller. @@ -549,6 +574,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_alias(tcx, a_kind, alias_ty)) } + (&ty::Pat(a_ty, a_pat), &ty::Pat(b_ty, b_pat)) => { + let ty = relation.relate(a_ty, b_ty)?; + let pat = relation.relate(a_pat, b_pat)?; + Ok(Ty::new_pat(tcx, ty, pat)) + } + _ => Err(TypeError::Sorts(expected_found(relation, a, b))), } } @@ -753,6 +784,20 @@ impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::Binder<'tcx, T> { } } +impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for Option { + fn relate>( + relation: &mut R, + a: Self, + b: Self, + ) -> RelateResult<'tcx, Self> { + match (a, b) { + (None, None) => Ok(None), + (Some(a), Some(b)) => relation.relate(a, b).map(Some), + _ => Err(TypeError::Mismatch), + } + } +} + impl<'tcx> Relate<'tcx> for GenericArg<'tcx> { fn relate>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 11b579a1f85b6..a6d60d7b7d09c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -19,6 +19,8 @@ use std::ops::ControlFlow; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Region}; +use super::Pattern; + impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { @@ -209,6 +211,22 @@ impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { } } +impl<'tcx> DebugWithInfcx> for Pattern<'tcx> { + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match &**this.data { + ty::PatternKind::Range { start, end, include_end } => f + .debug_struct("Pattern::Range") + .field("start", start) + .field("end", end) + .field("include_end", include_end) + .finish(), + } + } +} + impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { WithInfcx::with_no_infcx(self).fmt(f) @@ -543,6 +561,22 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { } } +impl<'tcx> TypeFoldable> for Pattern<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + let pat = (*self).clone().try_fold_with(folder)?; + Ok(if pat == *self { self } else { folder.interner().mk_pat(pat) }) + } +} + +impl<'tcx> TypeVisitable> for Pattern<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { + (**self).visit_with(visitor) + } +} + impl<'tcx> TypeFoldable> for Ty<'tcx> { fn try_fold_with>>( self, @@ -585,6 +619,7 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { } ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), + ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?), ty::Bool | ty::Char @@ -634,6 +669,11 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty::Closure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), + ty::Pat(ty, pat) => { + ty.visit_with(visitor)?; + pat.visit_with(visitor) + } + ty::Bool | ty::Char | ty::Str diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8cf5fc8013f1d..ccc5073b93c5c 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1970,6 +1970,11 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Alias(kind, alias_ty)) } + #[inline] + pub fn new_pat(tcx: TyCtxt<'tcx>, base: Ty<'tcx>, pat: ty::Pattern<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Pat(base, pat)) + } + #[inline] pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { Ty::new_alias(tcx, ty::Opaque, AliasTy::new(tcx, def_id, args)) @@ -2686,6 +2691,8 @@ impl<'tcx> Ty<'tcx> { Ty::new_projection(tcx, assoc_items[0], tcx.mk_args(&[self.into()])) } + ty::Pat(ty, _) => ty.discriminant_ty(tcx), + ty::Bool | ty::Char | ty::Int(_) @@ -2764,6 +2771,7 @@ impl<'tcx> Ty<'tcx> { ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), ty::Infer(ty::TyVar(_)) + | ty::Pat(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { @@ -2844,6 +2852,8 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), + ty::Pat(ty, _) => ty.is_trivially_sized(tcx), + ty::Adt(def, _args) => def.sized_constraint(tcx).skip_binder().is_empty(), ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false, @@ -2886,6 +2896,8 @@ impl<'tcx> Ty<'tcx> { field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy) } + ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(), + // Sometimes traits aren't implemented for every ABI or arity, // because we can't be generic over everything yet. ty::FnPtr(..) => false, @@ -2965,6 +2977,7 @@ impl<'tcx> Ty<'tcx> { | Foreign(_) | Str | Array(_, _) + | Pat(_, _) | Slice(_) | RawPtr(_) | Ref(_, _, _) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index ef621f29bfd71..4e6f0c8811c54 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -249,6 +249,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, + ty::Pat(inner, _) => { + f(); + ty = inner; + } + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { @@ -1115,7 +1120,7 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) | ty::FnPtr(_) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze), - ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), + ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_freeze(), ty::Adt(..) | ty::Bound(..) | ty::Closure(..) @@ -1154,7 +1159,7 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) | ty::FnPtr(_) => true, ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin), - ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), + ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => ty.is_trivially_unpin(), ty::Adt(..) | ty::Bound(..) | ty::Closure(..) @@ -1270,7 +1275,7 @@ impl<'tcx> Ty<'tcx> { // // Because this function is "shallow", we return `true` for these composites regardless // of the type(s) contained within. - ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, + ty::Pat(..) | ty::Ref(..) | ty::Array(..) | ty::Slice(_) | ty::Tuple(..) => true, // Raw pointers use bitwise comparison. ty::RawPtr(_) | ty::FnPtr(_) => true, @@ -1395,7 +1400,7 @@ pub fn needs_drop_components<'tcx>( ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), - ty::Slice(ty) => needs_drop_components(tcx, ty), + ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(tcx, ty), ty::Array(elem_ty, size) => { match needs_drop_components(tcx, elem_ty) { Ok(v) if v.is_empty() => Ok(v), @@ -1459,7 +1464,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // we'll just perform trait selection. ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Adt(..) => false, - ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), + ty::Array(ty, _) | ty::Slice(ty) | ty::Pat(ty, _) => is_trivially_const_drop(ty), ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty)), } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 9050716db9d38..368b05c8cc138 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -151,6 +151,15 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::Bound(..) | ty::Foreign(..) => {} + ty::Pat(ty, pat) => { + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + stack.extend(start.map(Into::into)); + stack.extend(end.map(Into::into)); + } + } + stack.push(ty.into()); + } ty::Array(ty, len) => { stack.push(len.into()); stack.push(ty.into()); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 38ee26c5a876e..1778524a96035 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -150,6 +150,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(_) @@ -186,6 +187,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ad12bce9b0232..73cf593285052 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -685,6 +685,7 @@ fn try_write_constant<'tcx>( // Unsupported for now. ty::Array(_, _) + | ty::Pat(_, _) // Do not attempt to support indirection in constants. | ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index db1aee1190359..6fa87aca65609 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -329,6 +329,7 @@ impl, I: Interner> TypeFolder | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) + | ty::Pat(_, _) | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 87e70d68c1b46..b0592f9c79816 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -421,6 +421,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { | ty::RawPtr(_) | ty::FnDef(_, _) | ty::FnPtr(_) + | ty::Pat(_, _) | ty::Dynamic(_, _, _) | ty::Closure(_, _) | ty::Coroutine(_, _) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 519303fc3aa96..51f35b07992b5 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -278,6 +278,7 @@ where | ty::Tuple(..) | ty::RawPtr(..) | ty::Ref(..) + | ty::Pat(..) | ty::FnPtr(..) | ty::Param(..) | ty::Bound(..) diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index 5689e8f3b3d94..c21b6eb60ee93 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -14,8 +14,8 @@ use stable_mir::mir::{Mutability, Safety}; use stable_mir::ty::{ Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, Const, DynKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, - GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Region, RigidTy, Span, TermKind, - TraitRef, Ty, UintTy, VariantDef, VariantIdx, + GenericArgKind, GenericArgs, IndexedVal, IntTy, Movability, Pattern, Region, RigidTy, Span, + TermKind, TraitRef, Ty, UintTy, VariantDef, VariantIdx, }; use stable_mir::{CrateItem, CrateNum, DefId}; @@ -75,6 +75,19 @@ impl<'tcx> RustcInternal<'tcx> for Ty { } } +impl<'tcx> RustcInternal<'tcx> for Pattern { + type T = rustc_ty::Pattern<'tcx>; + fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T { + tables.tcx.mk_pat(match self { + Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range { + start: start.as_ref().map(|c| ty_const(c, tables)), + end: end.as_ref().map(|c| ty_const(c, tables)), + include_end: *include_end, + }, + }) + } +} + impl<'tcx> RustcInternal<'tcx> for RigidTy { type T = rustc_ty::TyKind<'tcx>; @@ -89,6 +102,9 @@ impl<'tcx> RustcInternal<'tcx> for RigidTy { RigidTy::Array(ty, cnst) => { rustc_ty::TyKind::Array(ty.internal(tables), ty_const(cnst, tables)) } + RigidTy::Pat(ty, pat) => { + rustc_ty::TyKind::Pat(ty.internal(tables), pat.internal(tables)) + } RigidTy::Adt(def, args) => { rustc_ty::TyKind::Adt(def.internal(tables), args.internal(tables)) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index c0ecbfb991413..fbfa705bfbcf2 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -357,6 +357,9 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::Array(ty, constant) => { TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables))) } + ty::Pat(ty, pat) => { + TyKind::RigidTy(RigidTy::Pat(ty.stable(tables), pat.stable(tables))) + } ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => { TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables))) @@ -411,6 +414,20 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { } } +impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { + type T = stable_mir::ty::Pattern; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + match **self { + ty::PatternKind::Range { start, end, include_end } => stable_mir::ty::Pattern::Range { + start: start.stable(tables), + end: end.stable(tables), + include_end, + }, + } + } +} + impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { type T = stable_mir::ty::Const; diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 0cc82ac7506cb..761cda9546eb1 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -534,6 +534,16 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + ty::Pat(ty0, pat) => { + // u3patIE as vendor extended type + let mut s = String::from("u3patI"); + s.push_str(&encode_ty(tcx, *ty0, dict, options)); + write!(s, "{:?}", **pat).unwrap(); + s.push('E'); + compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); + typeid.push_str(&s); + } + ty::Slice(ty0) => { // u5sliceIE as vendor extended type let mut s = String::from("u5sliceI"); @@ -840,6 +850,10 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, options), len); } + ty::Pat(ty0, pat) => { + ty = Ty::new_pat(tcx, transform_ty(tcx, *ty0, options), *pat); + } + ty::Slice(ty0) => { ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, options)); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e89a640767f22..4b0cec866d810 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -404,6 +404,25 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { mt.ty.print(self)?; } + ty::Pat(ty, pat) => { + self.push("T"); + ty.print(self)?; + match *pat { + ty::PatternKind::Range { start, end, include_end } => { + if let Some(start) = start { + self.print_const(start)?; + } + let _ = write!(self.out, "_"); + if let Some(end) = end { + self.print_const(end)?; + } + + let _ = write!(self.out, "{:x}_", include_end as u8); + } + } + self.push("E"); + } + ty::Array(ty, len) => { self.push("A"); ty.print(self)?; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index caf9470b4c646..01cbb4026fbe4 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -425,6 +425,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) @@ -640,6 +641,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) @@ -796,6 +798,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 274a75a125c58..877897cd02781 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -48,7 +48,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( Ok(vec![element_ty]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]), + ty::Pat(element_ty, _) | ty::Array(element_ty, _) | ty::Slice(element_ty) => { + Ok(vec![element_ty]) + } ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet @@ -127,6 +129,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Array(..) + | ty::Pat(..) | ty::Closure(..) | ty::Never | ty::Dynamic(_, _, ty::DynStar) @@ -170,6 +173,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( | ty::Float(_) | ty::Char | ty::RawPtr(..) + | ty::Pat(..) | ty::Never | ty::Ref(_, _, Mutability::Not) | ty::Array(..) => Err(NoSolution), @@ -276,6 +280,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index ccee6f8eb29b9..ab8ae68c38ce5 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -386,6 +386,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Uint(..) | ty::Float(..) | ty::Array(..) + | ty::Pat(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) @@ -629,6 +630,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::Uint(..) | ty::Float(..) | ty::Array(..) + | ty::Pat(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index be07927568446..311fe7e416fac 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -953,6 +953,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Float(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ecbb92ca5b996..5b805835e3727 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -816,6 +816,7 @@ where | ty::Float(..) | ty::Str | ty::FnDef(..) + | ty::Pat(..) | ty::FnPtr(_) | ty::Array(..) | ty::Slice(..) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 149dcffe333de..872b23f933c81 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1876,6 +1876,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Coroutine(..) => Some(18), ty::Foreign(..) => Some(19), ty::CoroutineWitness(..) => Some(20), + ty::Pat(..) => Some(21), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index abbc2066eac16..f0dd0ca35af49 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1847,6 +1847,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Foreign(_) | ty::Str | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) @@ -1896,7 +1897,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Float(_) | ty::Str | ty::Array(..) - | ty::Slice(_) + | ty::Pat(..) + | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 138bc6129f7c7..730a5f5eb342f 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -42,8 +42,8 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Foreign(..) | ty::Error(_) => true, - // [T; N] and [T] have same properties as T. - ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), + // `T is PAT` [T; N] and [T] have same properties as T. + ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, *ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *all* of them are trivial. @@ -218,7 +218,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( // these types never have a destructor } - ty::Array(ety, _) | ty::Slice(ety) => { + ty::Pat(ety, _) | ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element rustc_data_structures::stack::ensure_sufficient_stack(|| { dtorck_constraint_for_ty_inner(tcx, param_env, span, depth + 1, *ety, constraints) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 342b12ba49848..dee3792d72881 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -482,6 +482,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Foreign(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) @@ -614,6 +615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Float(_) | ty::Str | ty::Array(_, _) + | ty::Pat(_, _) | ty::Slice(_) | ty::Adt(..) | ty::RawPtr(_) @@ -947,6 +949,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::Closure(..) | ty::Coroutine(..) @@ -1023,6 +1026,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::FnDef(_, _) + | ty::Pat(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) @@ -1081,6 +1085,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Foreign(..) | ty::Str | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6a6adcbb680ea..fe2e55eceee31 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2119,6 +2119,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])), ), + ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])), + ty::Adt(def, args) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here @@ -2178,6 +2180,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { Where(obligation.predicate.rebind(tys.iter().collect())) } + ty::Pat(ty, _) => { + // (*) binder moved here + Where(obligation.predicate.rebind(vec![ty])) + } + ty::Coroutine(coroutine_def_id, args) => { match self.tcx().coroutine_movability(coroutine_def_id) { hir::Movability::Static => None, @@ -2293,7 +2300,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { t.rebind(vec![element_ty]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => t.rebind(vec![element_ty]), + ty::Pat(ty, _) | ty::Array(ty, _) | ty::Slice(ty) => t.rebind(vec![ty]), ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 868a8a3e8b85f..b5c1f61cabb7a 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -127,7 +127,7 @@ impl<'tcx> TypeVisitor> for Search<'tcx> { return ControlFlow::Continue(()); } - ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => { + ty::Pat(..) | ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => { // First check all contained types and then tell the caller to continue searching. return ty.super_visit_with(self); } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0f8d9c6bf4bdb..b0e89a790af7d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -615,11 +615,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // Can only infer to `ty::Float(_)`. ty::Infer(ty::FloatVar(_)) => {} - ty::Slice(subty) => { - self.require_sized(subty, traits::SliceOrArrayElem); - } - - ty::Array(subty, _) => { + ty::Pat(subty, _) | ty::Slice(subty) | ty::Array(subty, _) => { self.require_sized(subty, traits::SliceOrArrayElem); // Note that we handle the len is implicitly checked while walking `arg`. } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 2fc4bfd4aa31c..d2c727cfe69ff 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -124,6 +124,31 @@ fn layout_of_uncached<'tcx>( debug_assert!(!ty.has_non_region_infer()); Ok(match *ty.kind() { + ty::Pat(ty, pat) => { + let layout = cx.layout_of(ty)?.layout; + let mut abi = layout.abi(); + match *pat { + ty::PatternKind::Range { start, end, include_end } => { + if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut abi { + if let Some(start) = start { + scalar.valid_range_mut().start = start.eval_bits(tcx, param_env); + } + if let Some(end) = end { + let mut end = end.eval_bits(tcx, param_env); + if !include_end { + end = end.wrapping_sub(1); + } + scalar.valid_range_mut().end = end; + } + + tcx.mk_layout(LayoutS { abi, ..LayoutS::clone(&layout.0) }) + } else { + bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") + } + } + } + } + // Basic scalars. ty::Bool => tcx.mk_layout(LayoutS::scalar( cx, diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 08e5476ae43b7..e795500224666 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -188,7 +188,11 @@ where queue_type(self, required); } } - ty::Alias(..) | ty::Array(..) | ty::Placeholder(_) | ty::Param(_) => { + ty::Pat(..) + | ty::Alias(..) + | ty::Array(..) + | ty::Placeholder(_) + | ty::Param(_) => { if ty == component { // Return the type to the caller: they may be able // to normalize further than we can. diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2158aacab03d8..84bf9cae3d6d2 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -30,6 +30,8 @@ fn sized_constraint_for_ty<'tcx>( Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), }, + Pat(ty, _) => sized_constraint_for_ty(tcx, adtdef, *ty), + Adt(adt, args) => { // recursive case let adt_tys = adt.sized_constraint(tcx); diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 188910ecc52d1..db8c2325cb645 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -40,6 +40,7 @@ pub trait Interner: Sized { type BoundExistentialPredicates: Copy + DebugWithInfcx + Hash + Ord; type PolyFnSig: Copy + DebugWithInfcx + Hash + Ord; type AllocId: Copy + Debug + Hash + Ord; + type Pat: Copy + Debug + Hash + PartialEq + Eq + PartialOrd + Ord + DebugWithInfcx; // Kinds of consts type Const: Copy diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 859000fb6cb18..3f0a14450f231 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -156,6 +156,10 @@ pub enum TyKind { /// An array with the given length. Written as `[T; N]`. Array(I::Ty, I::Const), + /// A pattern subtype. Takes any type and restricts it to its pattern. + /// Only supports integer range patterns for now. + Pat(I::Ty, I::Pat), + /// The pointee of an array slice. Written as `[T]`. Slice(I::Ty), @@ -327,6 +331,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Placeholder(_) => 23, Infer(_) => 24, Error(_) => 25, + Pat(_, _) => 26, } } @@ -347,6 +352,7 @@ impl PartialEq for TyKind { (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d == b_d && a_s == b_s, (Foreign(a_d), Foreign(b_d)) => a_d == b_d, (Array(a_t, a_c), Array(b_t, b_c)) => a_t == b_t && a_c == b_c, + (Pat(a_t, a_c), Pat(b_t, b_c)) => a_t == b_t && a_c == b_c, (Slice(a_t), Slice(b_t)) => a_t == b_t, (RawPtr(a_t), RawPtr(b_t)) => a_t == b_t, (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => a_r == b_r && a_t == b_t && a_m == b_m, @@ -369,7 +375,7 @@ impl PartialEq for TyKind { _ => { debug_assert!( tykind_discriminant(self) != tykind_discriminant(other), - "This branch must be unreachable, maybe the match is missing an arm? self = self = {self:?}, other = {other:?}" + "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}" ); false } @@ -409,6 +415,7 @@ impl DebugWithInfcx for TyKind { Foreign(d) => f.debug_tuple("Foreign").field(d).finish(), Str => write!(f, "str"), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), + Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &this.wrap(t), &this.wrap(p)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), RawPtr(TypeAndMut { ty, mutbl }) => { match mutbl { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index eba2ac57012b9..6f22bdb11c2f1 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -99,6 +99,12 @@ impl Ty { } } +/// Represents a pattern in the type system +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum Pattern { + Range { start: Option, end: Option, include_end: bool }, +} + /// Represents a constant in MIR or from the Type system. #[derive(Clone, Debug, Eq, PartialEq)] pub struct Const { @@ -454,6 +460,7 @@ pub enum RigidTy { Foreign(ForeignDef), Str, Array(Ty, Const), + Pat(Ty, Pattern), Slice(Ty), RawPtr(Ty, Mutability), Ref(Region, Ty, Mutability), diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs index 65e42879d618b..2d7159f87fec3 100644 --- a/compiler/stable_mir/src/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -139,6 +139,7 @@ impl Visitable for RigidTy { t.visit(visitor)?; c.visit(visitor) } + RigidTy::Pat(t, _p) => t.visit(visitor), RigidTy::Slice(inner) => inner.visit(visitor), RigidTy::RawPtr(ty, _) => ty.visit(visitor), RigidTy::Ref(reg, ty, _) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6ada5118a58bc..c6034ef65c3b1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2057,6 +2057,10 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Float(float_ty) => Primitive(float_ty.into()), ty::Str => Primitive(PrimitiveType::Str), ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))), + ty::Pat(ty, pat) => Type::Pat( + Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), + format!("{pat:?}").into_boxed_str(), + ), ty::Array(ty, mut n) => { n = n.normalize(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 30b3e5c784dc1..ac812a13a3886 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -511,6 +511,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { ty::Str => Res::Primitive(Str), ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit), ty::Tuple(_) => Res::Primitive(Tuple), + ty::Pat(..) => Res::Primitive(Pat), ty::Array(..) => Res::Primitive(Array), ty::Slice(_) => Res::Primitive(Slice), ty::RawPtr(_) => Res::Primitive(RawPointer), diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index cb6e91754d5db..3fb5ae82ec01c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -871,7 +871,8 @@ impl TyCoercionStability { | ty::Int(_) | ty::Uint(_) | ty::Array(..) - | ty::Float(_) + | ty::Pat(..) + | ty::Float(_) | ty::RawPtr(..) | ty::FnPtr(_) | ty::Str diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 61d27ec69f4d2..bb4aa28a278a5 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE) +error: symbol-name(_ZN5basic4main17h9665e7d31226619bE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h9308686d0228fa1d) +error: demangling(basic::main::h9665e7d31226619b) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index eb65f3b58fff8..8d9c76ab8d15d 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hc2493b0ba50ab18dE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h84ab5dafbd2a1508) +error: demangling(issue_60925::foo::Foo::foo::hc2493b0ba50ab18d) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs new file mode 100644 index 0000000000000..5f5a614faf55f --- /dev/null +++ b/tests/ui/type/pattern_types/range_patterns.rs @@ -0,0 +1,9 @@ +#![feature(pattern_types)] +#![feature(core_pattern_type)] +#![allow(incomplete_features)] + +// check-pass + +fn main() { + let x: std::pat::pattern_type!(u32 is 1..) = todo!(); +}