From d1720e2339b7f58e200144a9eefc4bf1846a1aaa Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 22 Nov 2022 15:53:50 +0000 Subject: [PATCH 01/10] Add pattern types to the compiler --- .../src/debuginfo/type_names.rs | 9 ++++ .../src/const_eval/valtrees.rs | 5 +- .../src/interpret/intrinsics.rs | 3 ++ .../src/interpret/validity.rs | 1 + .../rustc_const_eval/src/util/type_name.rs | 1 + .../locales/en-US/lint.ftl | 3 ++ .../src/coherence/inherent_impls.rs | 3 ++ .../src/variance/constraints.rs | 10 ++++ compiler/rustc_hir_typeck/src/cast.rs | 1 + .../src/infer/canonical/canonicalizer.rs | 1 + compiler/rustc_infer/src/infer/freshen.rs | 1 + .../src/infer/outlives/components.rs | 1 + 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 | 3 ++ 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 ++ .../rustc_middle/src/ty/structural_impls.rs | 21 ++++++++ compiler/rustc_middle/src/ty/sty.rs | 7 +++ compiler/rustc_middle/src/ty/util.rs | 15 ++++-- compiler/rustc_middle/src/ty/walk.rs | 9 ++++ compiler/rustc_privacy/src/lib.rs | 1 + .../src/typeid/typeid_itanium_cxx_abi.rs | 22 ++++++++- compiler/rustc_symbol_mangling/src/v0.rs | 12 +++++ .../src/solve/assembly.rs | 2 + .../solve/trait_goals/structural_traits.rs | 7 ++- .../src/traits/coherence.rs | 1 + .../src/traits/error_reporting/mod.rs | 1 + .../src/traits/project.rs | 6 ++- .../src/traits/query/dropck_outlives.rs | 4 +- .../src/traits/select/candidate_assembly.rs | 2 + .../src/traits/select/mod.rs | 9 +++- .../src/traits/structural_match.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 6 +-- compiler/rustc_traits/src/chalk/lowering.rs | 1 + compiler/rustc_traits/src/dropck_outlives.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 18 +++++++ compiler/rustc_ty_utils/src/ty.rs | 2 + compiler/rustc_type_ir/src/lib.rs | 2 + compiler/rustc_type_ir/src/sty.rs | 25 ++++++++++ src/librustdoc/clean/mod.rs | 4 ++ src/librustdoc/clean/types.rs | 14 +++++- src/librustdoc/html/format.rs | 14 ++++++ src/librustdoc/html/render/search_index.rs | 1 + src/librustdoc/json/conversions.rs | 3 +- .../passes/collect_intra_doc_links.rs | 1 + src/rustdoc-json-types/lib.rs | 6 +++ .../clippy/clippy_lints/src/dereference.rs | 1 + 55 files changed, 342 insertions(+), 28 deletions(-) create mode 100644 compiler/rustc_middle/src/ty/pattern.rs diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 1599ccbb2594c..31bca32bab4db 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -194,6 +194,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 498c008738793..fdec0747274c0 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -96,6 +96,8 @@ pub(crate) fn const_to_valtree_inner<'tcx>( Ok(ty::ValTree::Leaf(val.assert_int())) } + ty::Pat(..) => const_to_valtree_inner(ecx, &ecx.mplace_field(&place, 0).unwrap(), num_nodes), + // Raw pointers are not allowed in type level constants, as we cannot properly test them for // equality at compile-time (see `ptr_guaranteed_cmp`). // Technically we could allow function pointers (represented as `ty::Instance`), but this is not guaranteed to @@ -265,7 +267,7 @@ pub fn valtree_to_const_value<'tcx>( let (param_env, ty) = param_env_ty.into_parts(); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); - match ty.kind() { + match *ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); ConstValue::ZeroSized @@ -276,6 +278,7 @@ pub fn valtree_to_const_value<'tcx>( "ValTrees for Bool, Int, Uint, Float or Char should have the form ValTree::Leaf" ), }, + ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), ty::Ref(_, _, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { let mut place = match ty.kind() { ty::Ref(_, inner_ty, _) => { diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index f87e4fbc1a178..e9668fb1e3c2e 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -83,6 +83,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 19e359986a12e..fa3fd936f33f1 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -584,6 +584,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 c4122f6649814..657721fd19fd2 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -40,6 +40,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_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index d63ff77d8e255..d9fffc6a8ae23 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -237,6 +237,9 @@ lint_improper_ctypes_128bit = 128-bit integers don't currently have a known stab lint_improper_ctypes_char_reason = the `char` type has no C equivalent lint_improper_ctypes_char_help = consider using `u32` or `libc::wchar_t` instead +lint_improper_ctypes_pat_reason = pattern types have no C equivalent +lint_improper_ctypes_pat_help = consider using the patterned type instead + lint_improper_ctypes_non_exhaustive = this enum is non-exhaustive lint_improper_ctypes_non_exhaustive_variant = this enum has non-exhaustive variants diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index dfb9824094346..44ccebe232ba9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -208,6 +208,9 @@ impl<'tcx> InherentCollect<'tcx> { .note("define and implement a new trait or type instead") .emit(); } + ty::Pat(..) => { + self.tcx.sess.span_err(ty.span, "cannot define inherent `impl` for pattern types"); + } ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 5e4d82b6fd569..e85dd66fd5998 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -231,6 +231,16 @@ 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 } => { + self.add_constraints_from_const(current, start, variance); + 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 712f9b87aed0a..2feb5efe99f96 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -132,6 +132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::GeneratorWitness(..) | 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 091635e6c73c0..86f85d554bf86 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -454,6 +454,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> 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/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 8f53b1ccdf458..86ad11997a6c2 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -201,6 +201,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) + | ty::Pat(..) | ty::FnPtr(_) | ty::Dynamic(..) | ty::Never diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 3d86279b03cc6..362e2b0b3ea71 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -92,6 +92,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/src/types.rs b/compiler/rustc_lint/src/types.rs index be47a3e238c1c..4c5219c9f8958 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -999,6 +999,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 f816d614500a0..a77185198e6ee 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -99,6 +99,7 @@ macro_rules! arena_types { [] tys: rustc_type_ir::WithCachedTypeInfo>, [] predicates: rustc_type_ir::WithCachedTypeInfo>, [] consts: rustc_middle::ty::ConstData<'tcx>, + [] 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 8cc8286c1dbe6..f92c45d4052ab 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -139,6 +139,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) @@ -315,6 +321,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.interner().arena.alloc_from_iter( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0b16270ea9874..fa2ef667972da 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -19,9 +19,9 @@ use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar, FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, - ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, - ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, - Visibility, + ParamTy, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, + TypeckResults, UintTy, Visibility, }; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast as ast; @@ -96,6 +96,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type SubstsRef = ty::SubstsRef<'tcx>; type DefId = DefId; type Ty = Ty<'tcx>; + type Pat = Pattern<'tcx>; type Const = ty::Const<'tcx>; type Region = Region<'tcx>; type TypeAndMut = TypeAndMut<'tcx>; @@ -140,6 +141,7 @@ pub struct CtxtInterners<'tcx> { projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, ConstData<'tcx>>, + pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, @@ -161,6 +163,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(), @@ -1196,6 +1199,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>} @@ -1483,6 +1487,7 @@ impl<'tcx> TyCtxt<'tcx> { Param, Infer, Alias, + Pat, Foreign )?; @@ -1609,6 +1614,7 @@ macro_rules! direct_interners { direct_interners! { region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, const_: mk_const_internal(ConstData<'tcx>): Const -> Const<'tcx>, + pat: mk_pat(PatternKind<'tcx>): Pattern -> Pattern<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 5d394f71f0d76..70a9cd3cc3dae 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -287,6 +287,8 @@ impl<'tcx> Ty<'tcx> { } "array".into() } + ty::Pat(ty, _) if ty.is_simple_ty() => format!("pattern `{}`", self).into(), + ty::Pat(..) => "pattern".into(), ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(), ty::Slice(_) => "slice".into(), ty::RawPtr(tymut) => { @@ -363,6 +365,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 f785fb5c4b9be..1f7d21f4e62a0 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -21,6 +21,7 @@ pub enum SimplifiedType { StrSimplifiedType, ArraySimplifiedType, SliceSimplifiedType, + PatSimplifiedType, RefSimplifiedType(Mutability), PtrSimplifiedType(Mutability), NeverSimplifiedType, @@ -97,6 +98,7 @@ pub fn simplify_type<'tcx>( ty::Str => Some(StrSimplifiedType), ty::Array(..) => Some(ArraySimplifiedType), ty::Slice(..) => Some(SliceSimplifiedType), + ty::Pat(..) => Some(PatSimplifiedType), ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { @@ -199,6 +201,7 @@ impl DeepRejectCtxt { | ty::Slice(..) | ty::RawPtr(..) | ty::Dynamic(..) + | ty::Pat(..) | ty::Ref(..) | ty::Never | ty::Tuple(..) @@ -238,6 +241,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 b7eafc4b43738..96869a75cb777 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -195,6 +195,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 66b9d96e69577..465363549a3cf 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -646,6 +646,7 @@ where | ty::FnDef(..) | ty::GeneratorWitness(..) | 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 4af29fcbfb586..6a27f8d92a714 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -88,6 +88,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::{ @@ -119,6 +120,7 @@ pub mod fold; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; +pub mod pattern; pub mod print; pub mod query; pub mod relate; diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs new file mode 100644 index 0000000000000..bc417505ef830 --- /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: ty::Const<'tcx>, end: ty::Const<'tcx> }, +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index c302c461195aa..799772cf52ee6 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -247,7 +247,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 ae7c20fff0c34..c49d0f8fb37d5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -649,6 +649,9 @@ pub trait PrettyPrinter<'tcx>: 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/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 2de886a3e817f..8658419ed3cea 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 std::rc::Rc; use std::sync::Arc; +use super::Pattern; + impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { @@ -573,6 +575,19 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> { } } +impl<'tcx> TypeFoldable<'tcx> 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.tcx().mk_pat(pat) }) + } +} + +impl<'tcx> TypeVisitable<'tcx> for Pattern<'tcx> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + (**self).visit_with(visitor) + } +} + impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { fn try_fold_with>(self, folder: &mut F) -> Result { folder.try_fold_binder(self) @@ -657,6 +672,7 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> { ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), ty::Closure(did, substs) => ty::Closure(did, substs.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 @@ -703,6 +719,11 @@ impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> { ty::Closure(_did, ref substs) => substs.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 6a7b23e40a779..93c3746f533a7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2158,6 +2158,8 @@ impl<'tcx> Ty<'tcx> { tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()])) } + ty::Pat(ty, _) => ty.discriminant_ty(tcx), + ty::Bool | ty::Char | ty::Int(_) @@ -2234,6 +2236,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(_)) => { @@ -2305,6 +2308,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, _substs) => def.sized_constraint(tcx).0.is_empty(), ty::Alias(..) | ty::Param(_) => false, @@ -2349,6 +2354,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, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 60076c8cb5f99..c1e01ea323703 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -260,6 +260,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::Tuple(_) => break, + ty::Pat(inner, _) => { + f(); + ty = inner; + } + ty::Alias(..) => { let normalized = normalize(ty); if ty == normalized { @@ -903,7 +908,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(..) @@ -942,7 +947,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(..) @@ -1056,7 +1061,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, @@ -1182,7 +1187,7 @@ pub fn needs_drop_components<'tcx>( ty::Dynamic(..) | ty::Error(_) => Err(AlwaysRequiresDrop), - ty::Slice(ty) => needs_drop_components(*ty, target_layout), + ty::Pat(ty, _) | ty::Slice(ty) => needs_drop_components(*ty, target_layout), ty::Array(elem_ty, size) => { match needs_drop_components(*elem_ty, target_layout) { Ok(v) if v.is_empty() => Ok(v), @@ -1245,7 +1250,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // we'll just perform trait selection. ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(_) | 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 708a5e4d059e8..1bdb43ac91359 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 } => { + stack.push(start.into()); + stack.push(end.into()); + } + } + stack.push(ty.into()); + } ty::Array(ty, len) => { stack.push(len.into()); stack.push(ty.into()); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9a5d3cceb914e..a14b6a9f142aa 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -263,6 +263,7 @@ where | ty::Str | ty::Never | ty::Array(..) + | ty::Pat(..) | ty::Slice(..) | ty::Tuple(..) | ty::RawPtr(..) 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 0759b95bd94c8..c082cc6413728 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 @@ -521,6 +521,21 @@ 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)); + match **pat { + ty::PatternKind::Range { start, end } => { + s.push_str(&encode_const(tcx, start, dict, options)); + s.push_str(&encode_const(tcx, end, dict, options)); + } + } + 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"); @@ -676,8 +691,11 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } ty::Array(ty0, len) => { - let len = len.kind().try_to_scalar().unwrap().to_u64().unwrap(); - ty = tcx.mk_array(transform_ty(tcx, *ty0, options), len); + ty = tcx.mk_ty(ty::Array(transform_ty(tcx, *ty0, options), *len)); + } + + ty::Pat(ty0, pat) => { + ty = tcx.mk_ty(ty::Pat(transform_ty(tcx, *ty0, options), *pat)); } ty::Slice(ty0) => { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 0d446d654dc5c..4b90b1218d640 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -419,6 +419,18 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { self = mt.ty.print(self)?; } + ty::Pat(ty, pat) => { + self.push("T"); + self = ty.print(self)?; + match *pat { + ty::PatternKind::Range { start, end } => { + self = self.print_const(start)?; + self = self.print_const(end)?; + } + } + self.push("E"); + } + ty::Array(ty, len) => { self.push("A"); self = ty.print(self)?; diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index d23b550621e17..9093a75b57241 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -330,6 +330,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Dynamic(..) | ty::Closure(..) | ty::Generator(..) + | ty::Pat(..) | ty::GeneratorWitness(_) | ty::Never | ty::Tuple(_) @@ -377,6 +378,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::FnDef(_, _) + | ty::Pat(_, _) | ty::FnPtr(_) | ty::Alias(..) | ty::Closure(..) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs index c2a19372f18c4..df5c08ab2558d 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs @@ -39,7 +39,9 @@ pub(super) 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(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet @@ -108,6 +110,7 @@ pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Pat(ty, _) => Ok(vec![ty]), ty::Adt(def, substs) => { let sized_crit = def.sized_constraint(infcx.tcx); @@ -158,6 +161,7 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( } ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Pat(ty, _) => Ok(vec![ty]), ty::Closure(_, substs) => Ok(vec![substs.as_closure().tupled_upvars_ty()]), @@ -218,6 +222,7 @@ pub(crate) fn extract_tupled_inputs_and_output_from_callable<'tcx>( | ty::Never | ty::Tuple(_) | ty::Alias(_, _) + | ty::Pat(_, _) | ty::Param(_) | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ecee0bf7a6d1b..78b345ff1d44c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -642,6 +642,7 @@ impl<'tcx> TypeVisitor<'tcx> for OrphanChecker<'tcx> { | 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/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 98917430d241d..b29f2e7aee013 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1891,6 +1891,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Generator(..) => Some(16), ty::Foreign(..) => Some(17), ty::GeneratorWitness(..) => Some(18), + ty::Pat(..) => Some(19), 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 fbc7eccedc883..02aa0f08a3a96 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1596,7 +1596,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Foreign(_) | ty::Str | ty::Array(..) - | ty::Slice(_) + | ty::Pat(..) + | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..) @@ -1645,7 +1646,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 0f21813bc40ae..93080eb74e50f 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -37,8 +37,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. 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 87d574ff107b2..e3800792567e6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -761,6 +761,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Foreign(_) | ty::Array(..) + | ty::Pat(..) | ty::Slice(_) | ty::Closure(..) | ty::Generator(..) @@ -821,6 +822,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::RawPtr(_) | ty::Ref(_, _, _) | ty::FnDef(_, _) + | ty::Pat(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f90da95d51668..45eaa38663de9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2052,6 +2052,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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, substs) => { let sized_crit = def.sized_constraint(self.tcx()); // (*) binder moved here @@ -2116,6 +2118,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Where(obligation.predicate.rebind(tys.iter().collect())) } + ty::Pat(ty, _) => { + // (*) binder moved here + Where(obligation.predicate.rebind(vec![ty])) + } + ty::Generator(_, substs, hir::Movability::Movable) => { if self.tcx().features().generator_clone { let resolved_upvars = @@ -2227,7 +2234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, '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(ref 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 f398fb06c187a..1697b8a9897ae 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -161,7 +161,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { } } - 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 767e31ddf781a..cc8eefc99a4f5 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -565,11 +565,7 @@ impl<'tcx> WfPredicates<'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_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 9712abb708f27..cf35c7b2f7359 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -343,6 +343,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substs.lower_into(interner), ), ty::GeneratorWitness(_) => unimplemented!(), + ty::Pat(..) => unimplemented!(), ty::Never => chalk_ir::TyKind::Never, ty::Tuple(types) => { chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner)) diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 481b56e111ea0..69eac6af94353 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -168,7 +168,7 @@ fn dtorck_constraint_for_ty<'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(tcx, span, for_ty, depth + 1, *ety, constraints) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 0f25579c7bfa1..993a9108c3355 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -112,6 +112,24 @@ 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 } => { + if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut abi { + scalar.valid_range_mut().start = + start.eval_bits(tcx, param_env, start.ty()); + scalar.valid_range_mut().end = end.eval_bits(tcx, param_env, end.ty()); + + tcx.intern_layout(LayoutS { abi, ..LayoutS::clone(&layout.0) }) + } else { + bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") + } + } + } + } + // Basic scalars. ty::Bool => tcx.intern_layout(LayoutS::scalar( cx, diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 13a7664869016..f81215c018366 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -26,6 +26,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, substs) => { // recursive case let adt_tys = adt.sized_constraint(tcx); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 44004cb0be1e9..f588fe155fe29 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -33,6 +33,8 @@ pub trait Interner { type SubstsRef: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type DefId: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Ty: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; + /// A pattern type pattern. + type Pat: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Const: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type Region: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; type TypeAndMut: Clone + Debug + Hash + PartialEq + Eq + PartialOrd + Ord; diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index 5f29588ae4d26..6c49adaf90840 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -201,6 +201,10 @@ pub enum TyKind { /// A placeholder for a type which could not be computed; this is /// propagated to avoid useless error messages. Error(I::ErrorGuaranteed), + + /// A pattern subtype. Takes any type and restricts it to its pattern. + /// Only supports integer range patterns for now. + Pat(I::Ty, I::Pat), } impl TyKind { @@ -241,6 +245,7 @@ const fn tykind_discriminant(value: &TyKind) -> usize { Placeholder(_) => 23, Infer(_) => 24, Error(_) => 25, + Pat(_, _) => 26, } } @@ -254,6 +259,7 @@ impl Clone for TyKind { Uint(u) => Uint(*u), Float(f) => Float(*f), Adt(d, s) => Adt(d.clone(), s.clone()), + Pat(t, c) => Pat(t.clone(), c.clone()), Foreign(d) => Foreign(d.clone()), Str => Str, Array(t, c) => Array(t.clone(), c.clone()), @@ -290,6 +296,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, @@ -345,6 +352,7 @@ impl Ord for TyKind { (Adt(a_d, a_s), Adt(b_d, b_s)) => a_d.cmp(b_d).then_with(|| a_s.cmp(b_s)), (Foreign(a_d), Foreign(b_d)) => a_d.cmp(b_d), (Array(a_t, a_c), Array(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), + (Pat(a_t, a_c), Pat(b_t, b_c)) => a_t.cmp(b_t).then_with(|| a_c.cmp(b_c)), (Slice(a_t), Slice(b_t)) => a_t.cmp(b_t), (RawPtr(a_t), RawPtr(b_t)) => a_t.cmp(b_t), (Ref(a_r, a_t, a_m), Ref(b_r, b_t, b_m)) => { @@ -422,6 +430,10 @@ impl hash::Hash for TyKind { } GeneratorWitness(g) => g.hash(state), Tuple(t) => t.hash(state), + Pat(t, p) => { + t.hash(state); + p.hash(state); + } Alias(i, p) => { i.hash(state); p.hash(state); @@ -449,6 +461,7 @@ impl fmt::Debug for TyKind { Uint(u) => f.debug_tuple_field1_finish("Uint", u), Float(float) => f.debug_tuple_field1_finish("Float", float), Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s), + Pat(f0, f1) => f.debug_tuple_field2_finish("Pat", f0, f1), Foreign(d) => f.debug_tuple_field1_finish("Foreign", d), Str => f.write_str("Str"), Array(t, c) => f.debug_tuple_field2_finish("Array", t, c), @@ -481,6 +494,7 @@ where I::SubstsRef: Encodable, I::DefId: Encodable, I::Ty: Encodable, + I::Pat: Encodable, I::Const: Encodable, I::Region: Encodable, I::TypeAndMut: Encodable, @@ -516,6 +530,10 @@ where adt.encode(e); substs.encode(e); }), + Pat(ty, pat) => e.emit_enum_variant(disc, |e| { + ty.encode(e); + pat.encode(e); + }), Foreign(def_id) => e.emit_enum_variant(disc, |e| { def_id.encode(e); }), @@ -612,6 +630,7 @@ where I::InferTy: Decodable, I::PredicateKind: Decodable, I::AllocId: Decodable, + I::Pat: Decodable, { fn decode(d: &mut D) -> Self { match Decoder::read_usize(d) { @@ -641,6 +660,7 @@ where 23 => Placeholder(Decodable::decode(d)), 24 => Infer(Decodable::decode(d)), 25 => Error(Decodable::decode(d)), + 26 => Pat(Decodable::decode(d), Decodable::decode(d)), _ => panic!( "{}", format!( @@ -660,6 +680,7 @@ where I::DefId: HashStable, I::SubstsRef: HashStable, I::Ty: HashStable, + I::Pat: HashStable, I::Const: HashStable, I::TypeAndMut: HashStable, I::PolyFnSig: HashStable, @@ -699,6 +720,10 @@ where adt.hash_stable(__hcx, __hasher); substs.hash_stable(__hcx, __hasher); } + Pat(ty, pat) => { + ty.hash_stable(__hcx, __hasher); + pat.hash_stable(__hcx, __hasher); + } Foreign(def_id) => { def_id.hash_stable(__hcx, __hasher); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 34a7068e5da53..7cdde31e85943 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1709,6 +1709,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))), + ty::Pat(ty, pat) => Type::Pat( + Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), + format!("{pat:?}").into_boxed_str(), + ), ty::Array(ty, mut n) => { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a020ccd53b842..6b38f6dd0da6f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1613,7 +1613,9 @@ pub(crate) enum Type { /// /// This is mostly Rustdoc's version of [`hir::Path`]. /// It has to be different because Rustdoc's [`PathSegment`] can contain cleaned generics. - Path { path: Path }, + Path { + path: Path, + }, /// A `dyn Trait` object: `dyn for<'a> Trait<'a> + Send + 'static` DynTrait(Vec, Option), /// A type parameter. @@ -1630,10 +1632,15 @@ pub(crate) enum Type { /// /// The `String` field is a stringified version of the array's length parameter. Array(Box, Box), + Pat(Box, Box), /// A raw pointer type: `*const i32`, `*mut i32` RawPointer(Mutability, Box), /// A reference type: `&i32`, `&'a mut Foo` - BorrowedRef { lifetime: Option, mutability: Mutability, type_: Box }, + BorrowedRef { + lifetime: Option, + mutability: Mutability, + type_: Box, + }, /// A qualified path to an associated item: `::Name` QPath(Box), @@ -1758,6 +1765,7 @@ impl Type { BareFunction(..) => PrimitiveType::Fn, Slice(..) => PrimitiveType::Slice, Array(..) => PrimitiveType::Array, + Type::Pat(..) => PrimitiveType::Pat, RawPointer(..) => PrimitiveType::RawPointer, QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache), Generic(_) | Infer | ImplTrait(_) => return None, @@ -1810,6 +1818,7 @@ pub(crate) enum PrimitiveType { Slice, Array, Tuple, + Pat, Unit, RawPointer, Reference, @@ -1955,6 +1964,7 @@ impl PrimitiveType { Str => sym::str, Bool => sym::bool, Char => sym::char, + Pat => sym::pat, Array => sym::array, Slice => sym::slice, Tuple => sym::tuple, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 33404a7683597..9219341af4091 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1031,6 +1031,20 @@ fn fmt_type<'cx>( write!(f, "]") } }, + clean::Type::Pat(ref t, ref n) => match **t { + clean::Generic(name) if !f.alternate() => { + primitive_link(f, PrimitiveType::Pat, &format!("{name} is {n}", n = Escape(n)), cx) + } + _ => { + fmt::Display::fmt(&t.print(cx), f)?; + write!(f, " is ")?; + if f.alternate() { + write!(f, "{n}") + } else { + primitive_link(f, PrimitiveType::Pat, &format!("{n}", n = Escape(n)), cx) + } + } + }, clean::RawPointer(m, ref t) => { let m = match m { hir::Mutability::Mut => "mut", diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 5b0caac099bc3..f2e2e9cf86d63 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -369,6 +369,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option { | clean::Tuple(_) | clean::Slice(_) | clean::Array(_, _) + | clean::Type::Pat(_, _) | clean::QPath { .. } | clean::Infer => None, } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index bd95ec18650b3..b4d7eef77e7ac 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -484,7 +484,7 @@ pub(crate) fn from_trait_bound_modifier( impl FromWithTcx for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::{ - Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Primitive, QPath, + Array, BareFunction, BorrowedRef, Generic, ImplTrait, Infer, Pat, Primitive, QPath, RawPointer, Slice, Tuple, }; @@ -500,6 +500,7 @@ impl FromWithTcx for Type { Tuple(t) => Type::Tuple(t.into_tcx(tcx)), Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))), Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s.to_string() }, + Pat(t, s) => Type::Pat { type_: Box::new((*t).into_tcx(tcx)), pat: s.to_string() }, ImplTrait(g) => Type::ImplTrait(g.into_tcx(tcx)), Infer => Type::Infer, RawPointer(mutability, type_) => Type::RawPointer { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 075951312a639..dc97322eea211 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -528,6 +528,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/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 387d5787dfcb2..628558c5ead76 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -565,6 +565,12 @@ pub enum Type { type_: Box, len: String, }, + /// u32 is 0..=100 + Pat { + #[serde(rename = "type")] + type_: Box, + pat: String, + }, /// `impl TraitA + TraitB + ...` ImplTrait(Vec), /// `_` diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 05f2b92c03709..a00ae6d8235d1 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1410,6 +1410,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc | ty::Int(_) | ty::Uint(_) | ty::Array(..) + | ty::Pat(..) | ty::Float(_) | ty::RawPtr(..) | ty::FnPtr(_) => Position::DerefStable(precedence, true).into(), From 92861669b6c7bcb56d5f18170a7b21524a0f830b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 24 Nov 2022 14:21:33 +0000 Subject: [PATCH 02/10] Allow range pattern types to allow the entire range (heh) of possible ranges --- .../src/variance/constraints.rs | 10 +++++++--- compiler/rustc_middle/src/ty/pattern.rs | 2 +- compiler/rustc_middle/src/ty/walk.rs | 6 +++--- .../src/typeid/typeid_itanium_cxx_abi.rs | 7 +------ compiler/rustc_symbol_mangling/src/v0.rs | 13 ++++++++++--- compiler/rustc_ty_utils/src/layout.rs | 16 ++++++++++++---- 6 files changed, 34 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index e85dd66fd5998..1c8578bd78aae 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -233,9 +233,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::Pat(typ, pat) => { match *pat { - ty::PatternKind::Range { start, end } => { - self.add_constraints_from_const(current, start, variance); - self.add_constraints_from_const(current, end, variance); + 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); diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index bc417505ef830..ab1cc9f0a979f 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -44,5 +44,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum PatternKind<'tcx> { - Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> }, + Range { start: Option>, end: Option>, include_end: bool }, } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 1bdb43ac91359..c80bb98cfa1ab 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -153,9 +153,9 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) ty::Pat(ty, pat) => { match *pat { - ty::PatternKind::Range { start, end } => { - stack.push(start.into()); - stack.push(end.into()); + ty::PatternKind::Range { start, end, include_end: _ } => { + stack.extend(start.map(Into::into)); + stack.extend(end.map(Into::into)); } } stack.push(ty.into()); 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 c082cc6413728..5515b377a2db9 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 @@ -525,12 +525,7 @@ fn encode_ty<'tcx>( // u3patIE as vendor extended type let mut s = String::from("u3patI"); s.push_str(&encode_ty(tcx, *ty0, dict, options)); - match **pat { - ty::PatternKind::Range { start, end } => { - s.push_str(&encode_const(tcx, start, dict, options)); - s.push_str(&encode_const(tcx, end, dict, options)); - } - } + write!(s, "{:?}", **pat).unwrap(); s.push('E'); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 4b90b1218d640..14e8db794035d 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -423,9 +423,16 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { self.push("T"); self = ty.print(self)?; match *pat { - ty::PatternKind::Range { start, end } => { - self = self.print_const(start)?; - self = self.print_const(end)?; + ty::PatternKind::Range { start, end, include_end } => { + if let Some(start) = start { + self = self.print_const(start)?; + } + let _ = write!(self.out, "_"); + if let Some(end) = end { + self = self.print_const(end)?; + } + + let _ = write!(self.out, "{:x}_", include_end as u8); } } self.push("E"); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 993a9108c3355..48f4d32c80005 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -116,11 +116,19 @@ fn layout_of_uncached<'tcx>( let layout = cx.layout_of(ty)?.layout; let mut abi = layout.abi(); match *pat { - ty::PatternKind::Range { start, end } => { + ty::PatternKind::Range { start, end, include_end } => { if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut abi { - scalar.valid_range_mut().start = - start.eval_bits(tcx, param_env, start.ty()); - scalar.valid_range_mut().end = end.eval_bits(tcx, param_env, end.ty()); + if let Some(start) = start { + scalar.valid_range_mut().start = + start.eval_bits(tcx, param_env, start.ty()); + } + if let Some(end) = end { + let mut end = end.eval_bits(tcx, param_env, end.ty()); + if !include_end { + end = end.wrapping_sub(1); + } + scalar.valid_range_mut().end = end; + } tcx.intern_layout(LayoutS { abi, ..LayoutS::clone(&layout.0) }) } else { From 38d4b9e87e965c3a8fcaf14445810eb947d8d74d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 29 Nov 2022 07:54:53 +0000 Subject: [PATCH 03/10] Remove redundant tracing statement --- compiler/rustc_hir_analysis/src/coherence/builtin.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 76668f7e9ac4b..73cfb4b6ed344 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -358,8 +358,6 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef } pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { - debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - // this provider should only get invoked for local def-ids let impl_did = impl_did.expect_local(); let span = tcx.def_span(impl_did); From 6a9b00825440057aa2c55f262f89dd7e0e148482 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Jan 2023 19:11:56 +0000 Subject: [PATCH 04/10] Simplify accessing locals in a MirPatch --- compiler/rustc_middle/src/mir/mod.rs | 10 +++++----- compiler/rustc_middle/src/mir/patch.rs | 6 ++++++ compiler/rustc_middle/src/mir/tcx.rs | 2 +- compiler/rustc_mir_dataflow/src/elaborate_drops.rs | 4 ++-- .../rustc_mir_dataflow/src/impls/borrowed_locals.rs | 2 +- compiler/rustc_mir_transform/src/const_goto.rs | 2 +- .../rustc_mir_transform/src/early_otherwise_branch.rs | 8 ++++---- compiler/rustc_mir_transform/src/elaborate_drops.rs | 6 ++++++ compiler/rustc_mir_transform/src/shim.rs | 7 ++++++- compiler/rustc_mir_transform/src/sroa.rs | 2 +- 10 files changed, 33 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4da893e4c0716..e1a0e304449aa 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -75,20 +75,20 @@ pub use self::pretty::{ pub type LocalDecls<'tcx> = IndexVec>; pub trait HasLocalDecls<'tcx> { - fn local_decls(&self) -> &LocalDecls<'tcx>; + fn local_decl(&self, local: Local) -> &LocalDecl<'tcx>; } impl<'tcx> HasLocalDecls<'tcx> for LocalDecls<'tcx> { #[inline] - fn local_decls(&self) -> &LocalDecls<'tcx> { - self + fn local_decl(&self, local: Local) -> &LocalDecl<'tcx> { + &self[local] } } impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { #[inline] - fn local_decls(&self) -> &LocalDecls<'tcx> { - &self.local_decls + fn local_decl(&self, local: Local) -> &LocalDecl<'tcx> { + &self.local_decls[local] } } diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 24fe3b47256e2..13de6b644176d 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -17,6 +17,12 @@ pub struct MirPatch<'tcx> { } impl<'tcx> MirPatch<'tcx> { + pub fn local_decl<'a>(&'a self, body: &'a Body<'tcx>, local: Local) -> &'a LocalDecl<'tcx> { + body.local_decls + .get(local) + .unwrap_or_else(|| &self.new_locals[local.as_usize() - body.local_decls.len()]) + } + pub fn new(body: &Body<'tcx>) -> Self { let mut result = MirPatch { patch_map: IndexVec::from_elem(None, &body.basic_blocks), diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 599f0b9d3fab4..a9e7e8feccb40 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -127,7 +127,7 @@ impl<'tcx> Place<'tcx> { { projection .iter() - .fold(PlaceTy::from_ty(local_decls.local_decls()[local].ty), |place_ty, &elem| { + .fold(PlaceTy::from_ty(local_decls.local_decl(local).ty), |place_ty, &elem| { place_ty.projection_ty(tcx, elem) }) } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 7836ae2e7b76f..1819464c6fd30 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -95,7 +95,7 @@ impl Unwind { } } -pub trait DropElaborator<'a, 'tcx>: fmt::Debug { +pub trait DropElaborator<'a, 'tcx>: fmt::Debug + HasLocalDecls<'tcx> { /// The type representing paths that can be moved out of. /// /// Users can move out of individual fields of a struct, such as `a.b.c`. This type is used to @@ -195,7 +195,7 @@ where 'tcx: 'b, { fn place_ty(&self, place: Place<'tcx>) -> Ty<'tcx> { - place.ty(self.elaborator.body(), self.tcx()).ty + place.ty(&*self.elaborator, self.tcx()).ty } fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 0f8e86d1d6679..91199048b82f9 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -24,7 +24,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { // bottom = unborrowed - BitSet::new_empty(body.local_decls().len()) + BitSet::new_empty(body.local_decls.len()) } fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) { diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index 40eefda4f0763..8c53e1a2b723f 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -84,7 +84,7 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { let target_bb_terminator = target_bb.terminator(); let (discr, targets) = target_bb_terminator.kind.as_switch()?; if discr.place() == Some(*place) { - let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty; + let switch_ty = place.ty(self.body, self.tcx).ty; // We now know that the Switch matches on the const place, and it is statementless // Now find which value in the Switch matches the const value. let const_value = diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 8a7b027ddda7e..d73f7fbff130d 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -131,7 +131,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { Operand::Copy(x) => Operand::Copy(*x), Operand::Constant(x) => Operand::Constant(x.clone()), }; - let parent_ty = parent_op.ty(body.local_decls(), tcx); + let parent_ty = parent_op.ty(body, tcx); let statements_before = bbs[parent].statements.len(); let parent_end = Location { block: parent, statement_index: statements_before }; @@ -268,7 +268,7 @@ fn may_hoist<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, place: Place<'tcx>) -> // `otherwise` branch in `BBC, BBD` in the input to our transformation, which would // have invalidated the data when computing `discriminant(P)` // So dereferencing here is correct. - ProjectionElem::Deref => match place.ty(body.local_decls(), tcx).ty.kind() { + ProjectionElem::Deref => match place.ty(body, tcx).ty.kind() { ty::Ref(..) => {} _ => return false, }, @@ -317,7 +317,7 @@ fn evaluate_candidate<'tcx>( } = &bbs[parent].terminator().kind else { return None }; - let parent_ty = parent_discr.ty(body.local_decls(), tcx); + let parent_ty = parent_discr.ty(body, tcx); let parent_dest = { let poss = targets.otherwise(); // If the fallthrough on the parent is trivially unreachable, we can let the @@ -338,7 +338,7 @@ fn evaluate_candidate<'tcx>( } = &child_terminator.kind else { return None }; - let child_ty = child_discr.ty(body.local_decls(), tcx); + let child_ty = child_discr.ty(body, tcx); if child_ty != parent_ty { return None; } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 65f4956d23acd..5cc6d5d93de6e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -156,6 +156,12 @@ impl fmt::Debug for Elaborator<'_, '_, '_> { } } +impl<'tcx> HasLocalDecls<'tcx> for Elaborator<'_, '_, 'tcx> { + fn local_decl(&self, local: Local) -> &LocalDecl<'tcx> { + self.ctxt.patch.local_decl(self.ctxt.body, local) + } +} + impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { type Path = MovePathIndex; diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index dace540fa29d2..9e4983e89fe12 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -190,7 +190,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) BorrowKind::Mut { allow_two_phase_borrow: false }, tcx.mk_place_deref(dropee_ptr), ); - let ref_ty = reborrow.ty(body.local_decls(), tcx); + let ref_ty = reborrow.ty(&body, tcx); dropee_ptr = body.local_decls.push(LocalDecl::new(ref_ty, span)).into(); let new_statements = [ StatementKind::Assign(Box::new((dropee_ptr, reborrow))), @@ -270,6 +270,11 @@ impl fmt::Debug for DropShimElaborator<'_, '_> { Ok(()) } } +impl<'tcx> HasLocalDecls<'tcx> for DropShimElaborator<'_, 'tcx> { + fn local_decl(&self, local: Local) -> &LocalDecl<'tcx> { + self.patch.local_decl(self.body, local) + } +} impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { type Path = (); diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 42124f5a4808d..e5af1c2adb29d 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -32,7 +32,7 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { fn escaping_locals(body: &Body<'_>) -> BitSet { let mut set = BitSet::new_empty(body.local_decls.len()); set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count)); - for (local, decl) in body.local_decls().iter_enumerated() { + for (local, decl) in body.local_decls.iter_enumerated() { if decl.ty.is_union() || decl.ty.is_enum() { set.insert(local); } From 832c927903a9fbcc1257c1e4b65d987218b23134 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 25 Jan 2023 16:22:48 +0000 Subject: [PATCH 05/10] Actually create ranged types --- compiler/rustc_borrowck/src/lib.rs | 5 + compiler/rustc_borrowck/src/type_check/mod.rs | 72 ++++++++++- .../src/debuginfo/metadata.rs | 1 + compiler/rustc_codegen_ssa/src/base.rs | 3 + compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 +- .../rustc_const_eval/src/interpret/cast.rs | 12 +- .../src/interpret/validity.rs | 31 ++++- .../rustc_const_eval/src/interpret/visitor.rs | 53 +++++++- .../src/transform/validate.rs | 26 ++++ .../rustc_hir_analysis/src/collect/type_of.rs | 32 ++++- compiler/rustc_hir_typeck/src/cast.rs | 18 +++ .../src/fn_ctxt/suggestions.rs | 10 +- compiler/rustc_lint/src/types.rs | 11 +- compiler/rustc_middle/src/mir/mod.rs | 2 + compiler/rustc_middle/src/mir/syntax.rs | 4 + compiler/rustc_middle/src/thir.rs | 6 + compiler/rustc_middle/src/thir/visit.rs | 1 + compiler/rustc_middle/src/ty/cast.rs | 11 +- compiler/rustc_middle/src/ty/consts/kind.rs | 6 + .../rustc_middle/src/ty/consts/valtree.rs | 6 + compiler/rustc_middle/src/ty/context.rs | 5 + compiler/rustc_middle/src/ty/fast_reject.rs | 11 +- compiler/rustc_middle/src/ty/layout.rs | 12 +- compiler/rustc_middle/src/ty/print/pretty.rs | 36 +++++- compiler/rustc_middle/src/ty/relate.rs | 4 + compiler/rustc_middle/src/ty/sty.rs | 33 +++-- .../rustc_mir_build/src/build/matches/mod.rs | 5 +- .../src/build/matches/simplify.rs | 5 + .../rustc_mir_build/src/build/matches/test.rs | 2 + .../rustc_mir_build/src/check_unsafety.rs | 1 + .../src/thir/pattern/const_to_pat.rs | 9 ++ .../src/thir/pattern/deconstruct_pat.rs | 1 + .../rustc_mir_build/src/thir/pattern/mod.rs | 1 + .../rustc_mir_dataflow/src/elaborate_drops.rs | 35 ++++- .../src/elaborate_box_derefs.rs | 29 ++++- .../rustc_mir_transform/src/pass_manager.rs | 1 + compiler/rustc_monomorphize/src/collector.rs | 7 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 2 +- .../src/traits/select/mod.rs | 21 ++- compiler/rustc_traits/src/chalk/lowering.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 27 +++- library/core/src/num/nonzero.rs | 33 +++-- library/core/src/ptr/non_null.rs | 16 ++- library/core/src/time.rs | 68 ++++++---- library/std/src/os/fd/owned.rs | 12 +- library/std/src/sys/unix/time.rs | 29 ++++- .../const_prop/boxes.main.ConstProp.diff | 4 +- .../inline_into_box_place.main.Inline.diff | 34 ++--- ...67_inline_as_ref_as_mut.b.Inline.after.mir | 2 +- ...67_inline_as_ref_as_mut.d.Inline.after.mir | 2 +- .../unsafe-borrow-match.mirunsafeck.stderr | 14 ++ .../attributes/unsafe/unsafe-borrow-match.rs | 18 +++ .../unsafe-borrow-match.thirunsafeck.stderr | 14 ++ .../unsafe-borrow-tuple.mirunsafeck.stderr | 16 +++ .../attributes/unsafe/unsafe-borrow-tuple.rs | 17 +++ .../unsafe-borrow-tuple.thirunsafeck.stderr | 16 +++ .../consts/const-eval/raw-bytes.64bit.stderr | 120 +++++++++--------- tests/ui/consts/const-eval/raw-bytes.rs | 29 ++--- tests/ui/consts/const-eval/ub-nonnull.rs | 22 ++-- tests/ui/consts/const-eval/ub-nonnull.stderr | 34 ++--- .../ui/impl-trait/unsafety-checking-cycle.rs | 2 +- tests/ui/layout/valid_range_oob.rs | 2 +- tests/ui/layout/valid_range_oob.stderr | 11 +- tests/ui/lint/invalid_value.stderr | 14 -- tests/ui/mir/ssa-analysis-regression-50041.rs | 7 +- tests/ui/unique/unique-autoderef-index.rs | 29 ++++- tests/ui/unique/unique-object-move.rs | 8 +- tests/ui/unsafe/ranged_ints.mir.stderr | 4 +- tests/ui/unsafe/ranged_ints.rs | 2 +- tests/ui/unsafe/ranged_ints.thir.stderr | 4 +- tests/ui/unsafe/ranged_ints2.rs | 2 +- tests/ui/unsafe/ranged_ints2_const.rs | 12 +- tests/ui/unsafe/ranged_ints3.rs | 2 +- tests/ui/unsafe/ranged_ints3_const.rs | 8 +- tests/ui/unsafe/ranged_ints3_match.rs | 4 +- .../ui/unsafe/ranged_ints4.mirunsafeck.stderr | 4 +- tests/ui/unsafe/ranged_ints4.rs | 4 +- .../unsafe/ranged_ints4.thirunsafeck.stderr | 4 +- .../ranged_ints4_const.mirunsafeck.stderr | 4 +- tests/ui/unsafe/ranged_ints4_const.rs | 8 +- .../ranged_ints4_const.thirunsafeck.stderr | 4 +- tests/ui/unsafe/ranged_ints_const.mir.stderr | 4 +- tests/ui/unsafe/ranged_ints_const.rs | 4 +- tests/ui/unsafe/ranged_ints_const.thir.stderr | 4 +- tests/ui/unsafe/ranged_ints_macro.rs | 2 +- .../unsafe/unsafe-assign.mirunsafeck.stderr | 17 ++- tests/ui/unsafe/unsafe-assign.rs | 11 +- .../unsafe/unsafe-assign.thirunsafeck.stderr | 17 ++- .../unsafe/unsafe-borrow.mirunsafeck.stderr | 20 +-- tests/ui/unsafe/unsafe-borrow.rs | 32 +---- .../unsafe/unsafe-borrow.thirunsafeck.stderr | 20 +-- 91 files changed, 941 insertions(+), 392 deletions(-) create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-match.mirunsafeck.stderr create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-match.rs create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-match.thirunsafeck.stderr create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-tuple.mirunsafeck.stderr create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-tuple.rs create mode 100644 tests/ui/attributes/unsafe/unsafe-borrow-tuple.thirunsafeck.stderr diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 73ea7314b75cc..b5a9a86c2215a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2103,6 +2103,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ProjectionElem::Deref => { let base_ty = place_base.ty(self.body(), self.infcx.tcx).ty; + let base_ty = match *base_ty.kind() { + ty::Pat(inner, _) => inner, + _ => base_ty, + }; + // Check the kind of deref to decide match base_ty.kind() { ty::Ref(_, _, mutbl) => { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 81bd4c2a783e9..e488f757619d8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -433,6 +433,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } + #[instrument(level = "trace", skip(self))] fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { self.super_rvalue(rvalue, location); let rval_ty = rvalue.ty(self.body(), self.tcx()); @@ -517,14 +518,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { /// Checks that the types internal to the `place` match up with /// what would be expected. + #[instrument(level = "trace", skip(self), ret)] fn sanitize_place( &mut self, place: &Place<'tcx>, location: Location, context: PlaceContext, ) -> PlaceTy<'tcx> { - debug!("sanitize_place: {:?}", place); - let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty); for elem in place.projection.iter() { @@ -630,6 +630,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } } + #[instrument(level = "trace", skip(self), ret)] fn sanitize_projection( &mut self, base: PlaceTy<'tcx>, @@ -637,7 +638,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place: &Place<'tcx>, location: Location, ) -> PlaceTy<'tcx> { - debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place); let tcx = self.tcx(); let base_ty = base.ty; match pi { @@ -1310,6 +1310,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_operand(discr, term_location); let switch_ty = discr.ty(body, tcx); + let switch_ty = switch_ty.strip_pattern().unwrap_or(switch_ty); if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() { span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty); } @@ -2107,6 +2108,66 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } } + CastKind::Patternize => { + let ty_from = op.ty(body, tcx); + let cast_ty_to = CastTy::from_ty(*ty); + match cast_ty_to { + Some(CastTy::Pat(to)) => { + if let Err(terr) = self.eq_types( + ty_from, + to, + location.to_locations(), + ConstraintCategory::Cast, + ) { + span_mirbug!( + self, + rvalue, + "relating {:?} with {:?} yields {:?}", + ty_from, + to, + terr + ) + } + } + _ => { + span_mirbug!( + self, + rvalue, + "Invalid Patternize cast {ty_from} -> {ty}", + ) + } + } + } + CastKind::StripPattern => { + let ty_from = op.ty(body, tcx); + let cast_ty_from = CastTy::from_ty(ty_from); + match cast_ty_from { + Some(CastTy::Pat(from)) => { + if let Err(terr) = self.eq_types( + *ty, + from, + location.to_locations(), + ConstraintCategory::Cast, + ) { + span_mirbug!( + self, + rvalue, + "relating {:?} with {:?} yields {:?}", + ty, + from, + terr + ) + } + } + _ => { + span_mirbug!( + self, + rvalue, + "Invalid StripPattern cast {ty_from} -> {ty}", + ) + } + } + } CastKind::IntToFloat => { let ty_from = op.ty(body, tcx); let cast_ty_from = CastTy::from_ty(ty_from); @@ -2427,6 +2488,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ProjectionElem::Deref => { let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty; + let base_ty = match *base_ty.kind() { + ty::Pat(inner, _) => inner, + _ => base_ty, + }; + debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); match base_ty.kind() { ty::Ref(ref_region, _, mutbl) => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index b6eb5ee183fa3..7f510b4b0712e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -462,6 +462,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), // Type parameters from polymorphized functions. ty::Param(_) => build_param_type_di_node(cx, t), + ty::Pat(inner, _) => return type_di_node(cx, inner), _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), }; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 32d3cfe6fc650..f75b1d136cf6c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -256,6 +256,9 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. (bx.bitcast(lldata, lldata_ty), bx.bitcast(llextra, llextra_ty)) } + (&ty::Pat(a, a_pat), &ty::Pat(b, b_pat)) if a_pat == b_pat => { + unsize_ptr(bx, src, a, b, old_info) + } _ => bug!("unsize_ptr: called on bad types"), } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 23196c8cbaea1..dbc5bf1a7f969 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -219,7 +219,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty), } } - mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => { + mir::CastKind::Patternize + | mir::CastKind::StripPattern + | mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => { // This is a no-op at the LLVM level. operand.val } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index b2c847d3fd8dd..d9b9256bc3df0 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -25,6 +25,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { use rustc_middle::mir::CastKind::*; // FIXME: In which cases should we trigger UB when the source is uninit? match cast_kind { + Patternize | StripPattern => { + self.copy_op(src, dest, true)?; + } + Pointer(PointerCast::Unsize) => { let cast_ty = self.layout_of(cast_ty)?; self.unsize_into(src, cast_ty, dest)?; @@ -368,10 +372,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dest: &PlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {:?}", *src, src.layout.ty, cast_ty.ty); - match (&src.layout.ty.kind(), &cast_ty.ty.kind()) { + let (src_ty, target_ty) = match (src.layout.ty.kind(), cast_ty.ty.kind()) { + (&ty::Pat(a, pat_a), &ty::Pat(b, pat_b)) if pat_a == pat_b => (a, b), + _ => (src.layout.ty, cast_ty.ty), + }; + match (src_ty.kind(), target_ty.kind()) { (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(TypeAndMut { ty: c, .. })) | (&ty::RawPtr(TypeAndMut { ty: s, .. }), &ty::RawPtr(TypeAndMut { ty: c, .. })) => { - self.unsize_into_ptr(src, dest, *s, *c) + self.unsize_into_ptr(src, dest, s, c) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index fa3fd936f33f1..ef7909b2bd4a4 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -491,7 +491,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; - match ty.kind() { + match *ty.kind() { + ty::Pat(inner, _) => { + let mut value = value.clone(); + value.layout.ty = inner; + // First visit the inner type to report more targetted errors + // if the value is already not valid at the inner type. + self.visit_value(&value)?; + // Then check the extra pattern restrictions. + let scalar = self.read_immediate(&value, "initialized scalar value")?; + match (*scalar, value.layout.abi) { + (Immediate::Scalar(scalar), Abi::Scalar(s)) + | (Immediate::ScalarPair(scalar, _), Abi::ScalarPair(s, _)) => { + self.visit_scalar(scalar, s)? + } + other => span_bug!( + self.ecx.cur_span(), + "invalid abi {other:?} for pattern type {ty:?}" + ), + } + Ok(true) + } ty::Bool => { let value = self.read_scalar(value, "a boolean")?; try_validation!( @@ -545,11 +565,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } ty::Ref(_, ty, mutbl) => { if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) - && *mutbl == Mutability::Mut + && mutbl == Mutability::Mut { // A mutable reference inside a const? That does not seem right (except if it is // a ZST). - let layout = self.ecx.layout_of(*ty)?; + let layout = self.ecx.layout_of(ty)?; if !layout.is_zst() { throw_validation_failure!(self.path, { "mutable reference in a `const`" }); } @@ -584,7 +604,6 @@ 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(..) @@ -779,7 +798,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Abi::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. - let scalar = self.read_scalar(op, "initiailized scalar value")?; + let scalar = self.read_scalar(op, "initialized scalar value")?; self.visit_scalar(scalar, scalar_layout)?; } } @@ -789,7 +808,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // the other must be init. if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { let (a, b) = - self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair(); + self.read_immediate(op, "initialized scalar value")?.to_scalar_pair(); self.visit_scalar(a, a_layout)?; self.visit_scalar(b, b_layout)?; } diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index f9efc2418dbbc..e31f8c4833f84 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -49,6 +49,9 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized { ecx: &InterpCx<'mir, 'tcx, M>, field: usize, ) -> InterpResult<'tcx, Self>; + + /// Strip a layer of pattern types to get at the inner type + fn strip_pat_ty(self) -> Self; } /// A thing that we can project into given *mutable* access to `ecx`, and that has a layout. @@ -88,6 +91,9 @@ pub trait ValueMut<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized { ecx: &mut InterpCx<'mir, 'tcx, M>, field: usize, ) -> InterpResult<'tcx, Self>; + + /// Strip a layer of pattern types to get at the inner type + fn strip_pat_ty(self) -> Self; } // We cannot have a general impl which shows that Value implies ValueMut. (When we do, it says we @@ -131,6 +137,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> for OpTy<'tc ) -> InterpResult<'tcx, Self> { ecx.operand_field(self, field) } + + #[inline(always)] + fn strip_pat_ty(mut self) -> Self { + let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else { + bug!("NonNull must contain a pattern type, but had {}", self.layout.ty) + }; + self.layout.ty = raw_ptr_ty; + self + } } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> @@ -179,6 +194,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> ) -> InterpResult<'tcx, Self> { ecx.operand_field(self, field) } + + #[inline(always)] + fn strip_pat_ty(mut self) -> Self { + let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else { + bug!("NonNull must contain a pattern type, but had {}", self.layout.ty) + }; + self.layout.ty = raw_ptr_ty; + self + } } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> @@ -220,6 +244,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> Value<'mir, 'tcx, M> ) -> InterpResult<'tcx, Self> { ecx.mplace_field(self, field) } + + #[inline(always)] + fn strip_pat_ty(mut self) -> Self { + let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else { + bug!("NonNull must contain a pattern type, but had {}", self.layout.ty) + }; + self.layout.ty = raw_ptr_ty; + self + } } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> @@ -269,6 +302,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> ) -> InterpResult<'tcx, Self> { ecx.mplace_field(self, field) } + + #[inline(always)] + fn strip_pat_ty(mut self) -> Self { + let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else { + bug!("NonNull must contain a pattern type, but had {}", self.layout.ty) + }; + self.layout.ty = raw_ptr_ty; + self + } } impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> @@ -320,6 +362,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueMut<'mir, 'tcx, M> ) -> InterpResult<'tcx, Self> { ecx.place_field(self, field) } + + #[inline(always)] + fn strip_pat_ty(mut self) -> Self { + let ty::Pat(raw_ptr_ty, _) = *self.layout.ty.kind() else { + bug!("NonNull must contain a pattern type, but had {}", self.layout.ty) + }; + self.layout.ty = raw_ptr_ty; + self + } } macro_rules! make_value_visitor { @@ -466,7 +517,7 @@ macro_rules! make_value_visitor { ); // ... that contains a `NonNull`... (gladly, only a single field here) assert_eq!(nonnull_ptr.layout().fields.count(), 1); - let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?; // the actual raw ptr + let raw_ptr = nonnull_ptr.project_field(self.ecx(), 0)?.strip_pat_ty(); // the actual raw ptr // ... whose only field finally is a raw ptr we can dereference. self.visit_box(&raw_ptr)?; diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index dd168a9ac3cd3..892586ad5acea 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -627,6 +627,32 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { ); } } + CastKind::StripPattern => { + if let ty::Pat(ty, _) = op_ty.kind() { + if ty != target_type { + self.fail(location, format!("Trying to convert types from {ty} to {target_type} while stripping pattern")); + } + } else { + self.fail( + location, + format!("{op_ty} is not a pattern type during pattern stripping"), + ); + } + } + CastKind::Patternize => { + if let ty::Pat(ty, _) = *target_type.kind() { + if ty != op_ty { + self.fail(location, format!("Trying to convert types from {ty} to {target_type} while patternizing")); + } + } else { + self.fail( + location, + format!( + "{target_type} is not a pattern type during patternization" + ), + ); + } + } } } Rvalue::Repeat(_, _) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 5e388a2f2babb..f9a7221c1bf28 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -11,6 +11,7 @@ use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; +use rustc_target::abi::Size; use super::ItemCtxt; use super::{bad_placeholder, is_suggestable_infer_ty}; @@ -389,7 +390,36 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } }, - Node::Field(field) => icx.to_ty(field.ty), + Node::Field(field) => { + let ty = icx.to_ty(field.ty); + trace!(?ty); + let parent = tcx.parent(def_id.to_def_id()); + let nest = |start, end| { + trace!(?ty, ?start, ?end); + // FIXME: use nested as type of constant instead of u128 + let to_const = |i| + Some(tcx.mk_const(ty::ScalarInt::try_from_uint(i?, Size::from_bytes(16)).unwrap(), tcx.types.u128)); + let start = to_const(start); + let end = to_const(end); + trace!(?ty, ?start, ?end); + tcx.mk_pat_ty(ty, tcx.mk_pat(ty::PatternKind::Range { start, end, include_end: end.is_some() })) + }; + match tcx.layout_scalar_valid_range(parent) { + (std::ops::Bound::Included(start), std::ops::Bound::Included(end)) => { + nest(Some(start), Some(end)) + }, + (std::ops::Bound::Included(start), std::ops::Bound::Unbounded) => { + nest(Some(start), None) + }, + (std::ops::Bound::Unbounded, std::ops::Bound::Included(end)) => nest(None, Some(end)), + (std::ops::Bound::Excluded(_), _) | + (_, std::ops::Bound::Excluded(_)) => span_bug!(field.span, "scalar range attributes can't produce excluded bounds"), + // No attributes + (std::ops::Bound::Unbounded, std::ops::Bound::Unbounded) => { + ty + }, + } + }, Node::Expr(&Expr { kind: ExprKind::Closure { .. }, .. }) => { tcx.typeck(def_id).node_type(hir_id) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 2feb5efe99f96..0e83a0f5619bb 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -755,6 +755,22 @@ impl<'a, 'tcx> CastCheck<'tcx> { let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty)) { + (Some(Pat(from)), _) => { + if let Some(mut diag) = fcx.demand_eqtype_diag(self.span, self.cast_ty, from) { + diag.span_label(self.span, "pattern type casts removing the pattern cannote also change the patterned type"); + let err = diag.emit(); + return Err(CastError::ErrorGuaranteed(err)); + } + return Ok(CastKind::StripPattern); + } + (_, Some(Pat(to))) => { + if let Some(mut diag) = fcx.demand_eqtype_diag(self.span, to, self.expr_ty) { + diag.span_label(self.span, "pattern type casts adding the pattern cannot also change the patterned type"); + let err = diag.emit(); + return Err(CastError::ErrorGuaranteed(err)); + } + return Ok(CastKind::Patternize); + } (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { @@ -814,6 +830,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { } match (t_from, t_cast) { + (Pat(_), _) | (_, Pat(_)) => Err(CastError::IllegalCast), + // These types have invariants! can't cast into them. (_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6046e55c65c18..ced2d9c9bcde1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -277,10 +277,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some((sp, msg, suggestion, applicability, verbose, annotation)) = self.check_ref(expr, found, expected) { - if verbose { - err.span_suggestion_verbose(sp, &msg, suggestion, applicability); - } else { - err.span_suggestion(sp, &msg, suggestion, applicability); + if !sp.is_empty() || !suggestion.is_empty() { + if verbose { + err.span_suggestion_verbose(sp, &msg, suggestion, applicability); + } else { + err.span_suggestion(sp, &msg, suggestion, applicability); + } } if annotation { let suggest_annotation = match expr.peel_drop_temps().kind { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 4c5219c9f8958..92ecfc96e3869 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -707,9 +707,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option tcx.mk_mach_int(ty), - ty::Uint(ty) => tcx.mk_mach_uint(ty), - ty::RawPtr(ty_mut) => tcx.mk_ptr(ty_mut), + ty::Int(_) | ty::Uint(_) | ty::RawPtr(_) => ty, // As these types are always non-null, the nullable equivalent of // Option of these types are their raw pointer counterparts. ty::Ref(_region, ty, mutbl) => tcx.mk_ptr(ty::TypeAndMut { ty, mutbl }), @@ -718,6 +716,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option _> to represent it. ty } + ty::Pat(inner, _) => return get_nullable_type(cx, inner), // We should only ever reach this case if ty_is_known_nonnull is extended // to other types. @@ -999,11 +998,7 @@ 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::Pat(inner, _) => self.check_type_for_ffi(cache, inner), 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/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e1a0e304449aa..2b8524e94138f 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1954,6 +1954,8 @@ impl<'tcx> Rvalue<'tcx> { | CastKind::PtrToPtr | CastKind::Pointer(_) | CastKind::PointerFromExposedAddress + | CastKind::StripPattern + | CastKind::Patternize | CastKind::DynStar, _, _, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 52c2b10cbbea9..3a6e1aa498616 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1181,6 +1181,10 @@ pub enum CastKind { IntToFloat, PtrToPtr, FnPtrToPtr, + /// A cast from a `T is 1..10` type to `T`. + StripPattern, + /// An unsafe cast from `T` to `T is 1..10`. + Patternize, } #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 5f320708c8416..9a9b5dcc31c9b 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -660,6 +660,11 @@ pub enum PatKind<'tcx> { value: mir::ConstantKind<'tcx>, }, + /// A refinement type like `u32 is 1..100` + PatTy { + value: Box>, + }, + Range(Box>), /// Matches against a slice, checking the length and extracting elements. @@ -814,6 +819,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { } write!(f, "{}", subpattern) } + PatKind::PatTy { ref value } => write!(f, "{value}"), PatKind::Constant { value } => write!(f, "{}", value), PatKind::Range(box PatRange { lo, hi, end }) => { write!(f, "{}", lo)?; diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 79a0e75aa7c78..46675462fbb55 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -230,6 +230,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' } } Constant { value: _ } => {} + PatTy { value } => visitor.visit_pat(value), Range(_) => {} Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { for subpattern in prefix.iter() { diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index e65585955199f..af7847cbd20c1 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -23,7 +23,7 @@ impl IntTy { } // Valid types for the result of a non-coercion cast -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum CastTy<'tcx> { /// Various types that are represented as ints and handled mostly /// in the same way, merged for easier matching. @@ -36,6 +36,8 @@ pub enum CastTy<'tcx> { Ptr(ty::TypeAndMut<'tcx>), /// Casting into a `dyn*` value. DynStar, + /// pattern types: `SomeType is 1..100`. + Pat(Ty<'tcx>), } /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) @@ -54,6 +56,8 @@ pub enum CastKind { FnPtrPtrCast, FnPtrAddrCast, DynStarCast, + StripPattern, + Patternize, } impl<'tcx> CastTy<'tcx> { @@ -72,6 +76,7 @@ impl<'tcx> CastTy<'tcx> { ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), ty::FnPtr(..) => Some(CastTy::FnPtr), ty::Dynamic(_, _, ty::DynStar) => Some(CastTy::DynStar), + ty::Pat(t, _) => Some(CastTy::Pat(t)), _ => None, } } @@ -82,6 +87,10 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin let from = CastTy::from_ty(from_ty); let cast = CastTy::from_ty(cast_ty); let cast_kind = match (from, cast) { + // Casting away the pattern is always fine, we just lose information. + (Some(CastTy::Pat(from)), _) if from == cast_ty => mir::CastKind::StripPattern, + (_, Some(CastTy::Pat(cast))) if from_ty == cast => mir::CastKind::Patternize, + (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { mir::CastKind::PointerExposeAddress } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index d9721863a58c8..78bf131405e77 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -95,6 +95,12 @@ pub enum Expr<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(Expr<'_>, 24); +impl<'tcx> From for ConstKind<'tcx> { + fn from(v: ty::ScalarInt) -> Self { + Self::Value(v.into()) + } +} + #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstKind<'_>, 32); diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index a803fca0d5b89..fab643518847d 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -35,6 +35,12 @@ pub enum ValTree<'tcx> { Branch(&'tcx [ValTree<'tcx>]), } +impl<'tcx> From for ValTree<'tcx> { + fn from(v: ScalarInt) -> Self { + Self::Leaf(v) + } +} + impl<'tcx> ValTree<'tcx> { pub fn zst() -> Self { Self::Branch(&[]) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index fa2ef667972da..ee03fa3c0d2bd 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1864,6 +1864,11 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) } + #[inline] + pub fn mk_pat_ty(self, ty: Ty<'tcx>, pat: Pattern<'tcx>) -> Ty<'tcx> { + self.mk_ty(Pat(ty, pat)) + } + #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 1f7d21f4e62a0..50547a74147a1 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -21,7 +21,6 @@ pub enum SimplifiedType { StrSimplifiedType, ArraySimplifiedType, SliceSimplifiedType, - PatSimplifiedType, RefSimplifiedType(Mutability), PtrSimplifiedType(Mutability), NeverSimplifiedType, @@ -98,7 +97,7 @@ pub fn simplify_type<'tcx>( ty::Str => Some(StrSimplifiedType), ty::Array(..) => Some(ArraySimplifiedType), ty::Slice(..) => Some(SliceSimplifiedType), - ty::Pat(..) => Some(PatSimplifiedType), + ty::Pat(..) => None, ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { @@ -184,7 +183,7 @@ impl DeepRejectCtxt { } pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -> bool { - match impl_ty.kind() { + match *impl_ty.kind() { // Start by checking whether the type in the impl may unify with // pretty much everything. Just return `true` in that case. ty::Param(_) | ty::Error(_) | ty::Alias(..) => return true, @@ -201,12 +200,12 @@ impl DeepRejectCtxt { | ty::Slice(..) | ty::RawPtr(..) | ty::Dynamic(..) - | ty::Pat(..) | ty::Ref(..) | ty::Never | ty::Tuple(..) | ty::FnPtr(..) | ty::Foreign(..) => {} + ty::Pat(ty, _) => return self.types_may_unify(obligation_ty, ty), ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) @@ -241,9 +240,7 @@ impl DeepRejectCtxt { } _ => false, }, - ty::Pat(obl_ty, _) => { - matches!(k, &ty::Pat(impl_ty, _) if self.types_may_unify(obl_ty, impl_ty)) - } + ty::Pat(obl_ty, _) => 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/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 465363549a3cf..bc30cbb767f3d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -646,11 +646,17 @@ where | ty::FnDef(..) | ty::GeneratorWitness(..) | ty::Foreign(..) - | ty::Pat(_, _) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) } + // Pattern types are transparent from a layout perspective except + // for the change in valid values. + ty::Pat(ty, _) => { + let inner_layout = TyAndLayout { ty, layout: this.layout }; + field_ty_or_layout(inner_layout, cx, i) + } + // Potentially-fat pointers. ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { assert!(i < this.fields.count()); @@ -820,6 +826,10 @@ where let pointee_info = match *this.ty.kind() { + ty::Pat(inner, _) => tcx + .layout_of(param_env.and(inner)) + .ok() + .and_then(|layout| Self::ty_and_layout_pointee_info_at(layout, cx, offset)), ty::RawPtr(mt) if offset.bytes() == 0 => { tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo { size: layout.size, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c49d0f8fb37d5..6d08f474f3ca5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -650,7 +650,35 @@ pub trait PrettyPrinter<'tcx>: 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:?}")) + match *ty.kind() { + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Never + | ty::Tuple(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Infer(..) + | ty::Error(..) + | ty::Param(..) + | ty::Bound(..) + | ty::Adt(..) + | ty::Foreign(..) + | ty::Placeholder(..) + | ty::Alias(..) + | ty::Array(..) + | ty::Slice(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::Closure(..) + | ty::Str => p!(print(ty)), + ty::Pat(..) | ty::Ref(..) | ty::Dynamic(..) | ty::RawPtr(..) => { + p!("(", print(ty), ")") + } + } + p!(" is ", write("{pat:?}")) } ty::RawPtr(ref tm) => { p!(write( @@ -1751,15 +1779,17 @@ impl<'t> TyCtxt<'t> { self.def_path_str_with_substs(def_id, &[]) } + #[instrument(level = "trace", skip(self), ret)] pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { let ns = guess_def_namespace(self, def_id); - debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); + trace!(?ns); FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer() } + #[instrument(level = "trace", skip(self), ret)] pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String { let ns = guess_def_namespace(self, def_id); - debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); + trace!(?ns); FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer() } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 65fd8d9753de1..2c29202fb7a8b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -579,6 +579,10 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( } } + (&ty::Pat(a_t, pat_a), &ty::Pat(b_t, pat_b)) if pat_a == pat_b => { + Ok(tcx.mk_pat_ty(relation.relate(a_t, b_t)?, pat_a)) + } + _ => Err(TypeError::Sorts(expected_found(relation, a, b))), } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 93c3746f533a7..6303af8773b16 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1927,17 +1927,19 @@ impl<'tcx> Ty<'tcx> { /// contents are abstract to rustc.) #[inline] pub fn is_scalar(self) -> bool { - matches!( - self.kind(), - Bool | Char - | Int(_) - | Float(_) - | Uint(_) - | FnDef(..) - | FnPtr(_) - | RawPtr(_) - | Infer(IntVar(_) | FloatVar(_)) - ) + match *self.kind() { + Bool + | Char + | Int(_) + | Float(_) + | Uint(_) + | FnDef(..) + | FnPtr(_) + | RawPtr(_) + | Infer(IntVar(_) | FloatVar(_)) => true, + ty::Pat(inner, _) => inner.is_scalar(), + _ => false, + } } /// Returns `true` if this type is a floating point type. @@ -2049,6 +2051,15 @@ impl<'tcx> Ty<'tcx> { } } + #[inline] + /// Obtain the type part of a `type is pat` type. + pub fn strip_pattern(self) -> Option { + match *self.kind() { + ty::Pat(inner, _) => Some(inner), + _ => None, + } + } + /// Returns the type of `ty[i]`. pub fn builtin_index(self) -> Option> { match self.kind() { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 0961ce11e2f9a..947fe96af002a 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -763,7 +763,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {} + PatKind::PatTy { .. } + | PatKind::Constant { .. } + | PatKind::Range { .. } + | PatKind::Wild => {} PatKind::Deref { ref subpattern } => { self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index f6b1955fdec4d..18cc83c1a774d 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -173,6 +173,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Ok(()) } + PatKind::PatTy { ref value } => { + candidate.match_pairs.push(MatchPair::new(match_pair.place, value, self)); + Ok(()) + } + PatKind::Binding { name: _, mutability: _, diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index ad7a568a23181..7aa133f9187a0 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -75,6 +75,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::AscribeUserType { .. } | PatKind::Array { .. } | PatKind::Wild + | PatKind::PatTy { .. } | PatKind::Binding { .. } | PatKind::Leaf { .. } | PatKind::Deref { .. } => self.error_simplifyable(match_pair), @@ -108,6 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatKind::Slice { .. } | PatKind::Array { .. } + | PatKind::PatTy { .. } | PatKind::Wild | PatKind::Or { .. } | PatKind::Binding { .. } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 03a7f2d70faeb..3d740561bc3ed 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -206,6 +206,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { PatKind::Binding { .. } // match is conditional on having this value | PatKind::Constant { .. } + | PatKind::PatTy { .. } | PatKind::Variant { .. } | PatKind::Leaf { .. } | PatKind::Deref { .. } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index b0d24af958dd7..7a4b405d26347 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -482,6 +482,15 @@ impl<'tcx> ConstToPat<'tcx> { } PatKind::Constant { value: cv } } + ty::Pat(inner, _) => { + let cv = match cv { + mir::ConstantKind::Ty(c) => mir::ConstantKind::Ty(tcx.mk_const(c.kind(), *inner)), + mir::ConstantKind::Unevaluated(_, _) => cv, + mir::ConstantKind::Val(v, _) => mir::ConstantKind::Val(v, *inner), + }; + let value = self.recur(cv, mir_structural_match_violation)?; + PatKind::PatTy { value } + }, _ => { self.saw_const_match_error.set(true); let err = InvalidPattern { span, non_sm_ty: cv.ty() }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index aba5429da435f..a21c34ed6780b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1287,6 +1287,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { match &pat.kind { PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat), + PatKind::PatTy { value } => return mkpat(value), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = Fields::empty(); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3a6ef87c9c662..9b4e4d9603682 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -794,6 +794,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { PatKind::Deref { subpattern: subpattern.fold_with(folder) } } PatKind::Constant { value } => PatKind::Constant { value }, + PatKind::PatTy { ref value } => PatKind::PatTy { value: value.fold_with(folder) }, PatKind::Range(ref range) => PatKind::Range(range.clone()), PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice { prefix: prefix.fold_with(folder), diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 1819464c6fd30..681e6b17f5218 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -2,12 +2,12 @@ use rustc_hir as hir; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::patch::MirPatch; -use rustc_middle::mir::*; +use rustc_middle::mir::{self, *}; use rustc_middle::traits::Reveal; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{Size, VariantIdx}; use std::{fmt, iter}; /// The value of an inserted drop flag. @@ -415,19 +415,44 @@ where let nonnull_ty = unique_ty.ty_adt_def().unwrap().non_enum_variant().fields[0].ty(self.tcx(), substs); let ptr_ty = self.tcx().mk_imm_ptr(substs[0].expect_ty()); + let ptr_pat_ty = self.tcx().mk_pat_ty( + ptr_ty, + self.tcx().mk_pat(ty::PatternKind::Range { + start: Some(self.tcx().mk_const( + ty::ScalarInt::try_from_int(1, Size::from_bytes(16)).unwrap(), + self.tcx().types.u128, + )), + end: None, + include_end: false, + }), + ); let unique_place = self.tcx().mk_place_field(self.place, Field::new(0), unique_ty); let nonnull_place = self.tcx().mk_place_field(unique_place, Field::new(0), nonnull_ty); - let ptr_place = self.tcx().mk_place_field(nonnull_place, Field::new(0), ptr_ty); - let interior = self.tcx().mk_place_deref(ptr_place); let interior_path = self.elaborator.deref_subpath(self.path); let succ = self.box_free_block(adt, substs, self.succ, self.unwind); + + let ptr_place = self.tcx().mk_place_field(nonnull_place, Field::new(0), ptr_pat_ty); + + let ptr_tmp = self.new_temp(ptr_ty); + + let interior = self.tcx().mk_place_deref(Place::from(ptr_tmp)); + let unwind_succ = self.unwind.map(|unwind| self.box_free_block(adt, substs, unwind, Unwind::InCleanup)); - self.drop_subpath(interior, interior_path, succ, unwind_succ) + let block = self.drop_subpath(interior, interior_path, succ, unwind_succ); + + let loc = mir::Location { block, statement_index: 0 }; + self.elaborator.patch().add_assign( + loc, + ptr_tmp.into(), + Rvalue::Cast(CastKind::StripPattern, Operand::Copy(ptr_place), ptr_ty), + ); + + block } #[instrument(level = "debug", ret)] diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 932134bd6318f..9adb1a15e3605 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -8,7 +8,8 @@ use rustc_index::vec::Idx; use rustc_middle::mir::patch::MirPatch; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::Size; /// Constructs the types used when accessing a Box's pointer pub fn build_ptr_tys<'tcx>( @@ -21,6 +22,17 @@ pub fn build_ptr_tys<'tcx>( let unique_ty = tcx.bound_type_of(unique_did).subst(tcx, substs); let nonnull_ty = tcx.bound_type_of(nonnull_did).subst(tcx, substs); let ptr_ty = tcx.mk_imm_ptr(pointee); + let ptr_ty = tcx.mk_pat_ty( + ptr_ty, + tcx.mk_pat(ty::PatternKind::Range { + start: Some(tcx.mk_const( + ty::ScalarInt::try_from_int(1, Size::from_bytes(16)).unwrap(), + tcx.types.u128, + )), + end: None, + include_end: false, + }), + ); (unique_ty, nonnull_ty, ptr_ty) } @@ -68,15 +80,20 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { let (unique_ty, nonnull_ty, ptr_ty) = build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did); - let ptr_local = self.patch.new_internal(ptr_ty, source_info.span); + let raw_ptr_ty = ptr_ty.strip_pattern().unwrap(); + let ptr_local = self.patch.new_internal(raw_ptr_ty, source_info.span); self.patch.add_assign( location, Place::from(ptr_local), - Rvalue::Use(Operand::Copy( - Place::from(place.local) - .project_deeper(&build_projection(unique_ty, nonnull_ty, ptr_ty), tcx), - )), + Rvalue::Cast( + CastKind::StripPattern, + Operand::Copy( + Place::from(place.local) + .project_deeper(&build_projection(unique_ty, nonnull_ty, ptr_ty), tcx), + ), + raw_ptr_ty, + ), ); place.local = ptr_local; diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index e1b65823a5a9c..6940caceb9e0f 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -151,6 +151,7 @@ fn run_passes_inner<'tcx>( } } +#[instrument(level = "trace", skip(tcx, body))] pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index ec1de3056872b..5a3257c302049 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1081,10 +1081,10 @@ fn find_vtable_types_for_unsizing<'tcx>( } }; - match (&source_ty.kind(), &target_ty.kind()) { + match (source_ty.kind(), target_ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { - ptr_vtable(*a, *b) + ptr_vtable(a, b) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) @@ -1112,6 +1112,9 @@ fn find_vtable_types_for_unsizing<'tcx>( target_fields[coerce_index].ty(*tcx, target_substs), ) } + (&ty::Pat(source_ty, a), &ty::Pat(target_ty, b)) if a == b => { + find_vtable_types_for_unsizing(tcx, source_ty, target_ty) + } _ => bug!( "find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}", source_ty, 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 5515b377a2db9..9c3a37c17649d 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 @@ -690,7 +690,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } ty::Pat(ty0, pat) => { - ty = tcx.mk_ty(ty::Pat(transform_ty(tcx, *ty0, options), *pat)); + ty = tcx.mk_pat_ty(transform_ty(tcx, *ty0, options), *pat); } ty::Slice(ty0) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 45eaa38663de9..82695ad18949e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2098,6 +2098,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Bool | ty::Float(_) | ty::Char + | ty::Pat(..) | ty::RawPtr(..) | ty::Never | ty::Ref(_, _, hir::Mutability::Not) @@ -2118,11 +2119,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Where(obligation.predicate.rebind(tys.iter().collect())) } - ty::Pat(ty, _) => { - // (*) binder moved here - Where(obligation.predicate.rebind(vec![ty])) - } - ty::Generator(_, substs, hir::Movability::Movable) => { if self.tcx().features().generator_clone { let resolved_upvars = @@ -2382,7 +2378,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result>, ()> { let placeholder_obligation = self.infcx.replace_bound_vars_with_placeholders(obligation.predicate); - let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; + let mut placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; + if let ty::Pat(..) = *placeholder_obligation_trait_ref.self_ty().kind() { + // We can't do implementations for ranged types yet, so we just pick the unranged ones, + // even if that is unsound if those traits have methods with mutable references. + placeholder_obligation_trait_ref.substs = self.infcx.tcx.mk_substs( + placeholder_obligation_trait_ref.substs.iter().map(|arg| match arg.unpack() { + ty::GenericArgKind::Type(ty) => match *ty.kind() { + ty::Pat(ty, _) => ty.into(), + _ => arg, + }, + _ => arg, + }), + ); + } let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id); diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index cf35c7b2f7359..ccb597cb768d2 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -343,7 +343,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substs.lower_into(interner), ), ty::GeneratorWitness(_) => unimplemented!(), - ty::Pat(..) => unimplemented!(), + ty::Pat(inner, _) => return inner.lower_into(interner), ty::Never => chalk_ir::TyKind::Never, ty::Tuple(types) => { chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner)) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 48f4d32c80005..b5593208e5ebb 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -113,24 +113,39 @@ fn layout_of_uncached<'tcx>( Ok(match *ty.kind() { ty::Pat(ty, pat) => { - let layout = cx.layout_of(ty)?.layout; - let mut abi = layout.abi(); + let layout = cx.layout_of(ty)?; match *pat { ty::PatternKind::Range { start, end, include_end } => { + let mut abi = layout.abi; if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut abi { + let full_range = WrappingRange::full(scalar.size(cx)); if let Some(start) = start { - scalar.valid_range_mut().start = - start.eval_bits(tcx, param_env, start.ty()); + let start = start.kind().eval(tcx, param_env); + let start = start.try_to_bits(Size::from_bytes(16)).unwrap(); + assert!( + full_range.contains(start), + "{:?} does not contain {start}", + full_range + ); + scalar.valid_range_mut().start = start; } if let Some(end) = end { - let mut end = end.eval_bits(tcx, param_env, end.ty()); + let end = end.kind().eval(tcx, param_env); + let mut end = end.try_to_bits(Size::from_bytes(16)).unwrap(); if !include_end { end = end.wrapping_sub(1); } + assert!( + full_range.contains(end), + "{:?} does not contain {end}", + full_range + ); scalar.valid_range_mut().end = end; } - tcx.intern_layout(LayoutS { abi, ..LayoutS::clone(&layout.0) }) + tcx.intern_layout(LayoutS { abi, ..LayoutS::clone(&layout.layout.0) }) + } else if layout.is_zst() { + return layout_of_uncached(cx, ty); } else { bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index fbda8f82b1bd9..1f66a18d6dc6a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -35,13 +35,30 @@ macro_rules! nonzero_integers { #[doc = concat!("assert_eq!(size_of::>(), size_of::<", stringify!($Int), ">());")] /// ``` #[$stability] - #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] + #[derive(Copy, Clone, Eq, Ord, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = stringify!($Ty)] pub struct $Ty($Int); + #[$stability] + impl PartialEq for $Ty { + fn eq(&self, other: &Self) -> bool { + self.0 as $Int == other.0 as $Int + } + } + + #[$stability] + impl crate::marker::StructuralPartialEq for $Ty {} + + #[$stability] + impl PartialOrd for $Ty { + fn partial_cmp(&self, other: &Self) -> Option { + (self.0 as $Int).partial_cmp(&(other.0 as $Int)) + } + } + impl $Ty { /// Creates a non-zero without checking whether the value is non-zero. /// This results in undefined behaviour if the value is zero. @@ -60,7 +77,7 @@ macro_rules! nonzero_integers { concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument"), (n: $Int) => n != 0 ); - Self(n) + Self(n as _) } } @@ -72,7 +89,7 @@ macro_rules! nonzero_integers { pub const fn new(n: $Int) -> Option { if n != 0 { // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) + Some(unsafe { Self(n as _) }) } else { None } @@ -83,7 +100,7 @@ macro_rules! nonzero_integers { #[inline] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] pub const fn get(self) -> $Int { - self.0 + self.0 as _ } } @@ -94,7 +111,7 @@ macro_rules! nonzero_integers { #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] #[inline] fn from(nonzero: $Ty) -> Self { - nonzero.0 + nonzero.0 as $Int } } @@ -218,7 +235,7 @@ macro_rules! nonzero_leading_trailing_zeros { #[inline] pub const fn leading_zeros(self) -> u32 { // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. - unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } + unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 } } /// Returns the number of trailing zeros in the binary representation @@ -242,7 +259,7 @@ macro_rules! nonzero_leading_trailing_zeros { #[inline] pub const fn trailing_zeros(self) -> u32 { // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. - unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } + unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 } } } @@ -492,7 +509,7 @@ macro_rules! nonzero_unsigned_operations { without modifying the original"] #[inline] pub const fn ilog10(self) -> u32 { - super::int_log10::$Int(self.0) + super::int_log10::$Int(self.0 as _) } } )+ diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 8c1a648860555..d153fb05377a9 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -198,7 +198,7 @@ impl NonNull { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); - NonNull { pointer: ptr as _ } + NonNull { pointer: ptr as *const T as _ } } } @@ -271,7 +271,7 @@ impl NonNull { pub fn addr(self) -> NonZeroUsize { // SAFETY: The pointer is guaranteed by the type to be non-null, // meaning that the address will be non-zero. - unsafe { NonZeroUsize::new_unchecked(self.pointer.addr()) } + unsafe { NonZeroUsize::new_unchecked((self.pointer as *const T).addr()) } } /// Creates a new pointer with the given address. @@ -285,7 +285,11 @@ impl NonNull { #[unstable(feature = "strict_provenance", issue = "95228")] pub fn with_addr(self, addr: NonZeroUsize) -> Self { // SAFETY: The result of `ptr::from::with_addr` is non-null because `addr` is guaranteed to be non-zero. - unsafe { NonNull::new_unchecked(self.pointer.with_addr(addr.get()) as *mut _) } + unsafe { + NonNull::new_unchecked( + (self.pointer as *const T).cast_mut().with_addr(addr.get()) as *mut _ + ) + } } /// Creates a new pointer by mapping `self`'s address to a new one. @@ -323,7 +327,7 @@ impl NonNull { #[must_use] #[inline(always)] pub const fn as_ptr(self) -> *mut T { - self.pointer as *mut T + self.pointer as *const T as *mut T } /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`] @@ -778,7 +782,7 @@ impl const From<&mut T> for NonNull { #[inline] fn from(reference: &mut T) -> Self { // SAFETY: A mutable reference cannot be null. - unsafe { NonNull { pointer: reference as *mut T } } + unsafe { NonNull { pointer: reference as *mut T as *const T as _ } } } } @@ -792,6 +796,6 @@ impl const From<&T> for NonNull { fn from(reference: &T) -> Self { // SAFETY: A reference cannot be null, so the conditions for // new_unchecked() are respected. - unsafe { NonNull { pointer: reference as *const T } } + unsafe { NonNull { pointer: reference as *const T as _ } } } } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index ba1cb6efa04b6..ec0cc1c7e7ea9 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -29,17 +29,29 @@ const NANOS_PER_MICRO: u32 = 1_000; const MILLIS_PER_SEC: u64 = 1_000; const MICROS_PER_SEC: u64 = 1_000_000; -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Clone, Copy, Eq, Ord, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] #[rustc_layout_scalar_valid_range_end(999_999_999)] struct Nanoseconds(u32); +impl PartialEq for Nanoseconds { + fn eq(&self, other: &Self) -> bool { + self.0 as u32 == other.0 as u32 + } +} + +impl PartialOrd for Nanoseconds { + fn partial_cmp(&self, other: &Self) -> Option { + (self.0 as u32).partial_cmp(&(other.0 as u32)) + } +} + impl Default for Nanoseconds { #[inline] fn default() -> Self { // SAFETY: 0 is within the valid range - unsafe { Nanoseconds(0) } + unsafe { Nanoseconds(crate::mem::transmute(0)) } } } @@ -203,7 +215,7 @@ impl Duration { }; let nanos = nanos % NANOS_PER_SEC; // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + Duration { secs, nanos: unsafe { crate::mem::transmute(nanos) } } } /// Creates a new `Duration` from the specified number of whole seconds. @@ -307,7 +319,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[inline] pub const fn is_zero(&self) -> bool { - self.secs == 0 && self.nanos.0 == 0 + self.secs == 0 && self.subsec_nanos() == 0 } /// Returns the number of _whole_ seconds contained by this `Duration`. @@ -358,7 +370,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_millis(&self) -> u32 { - self.nanos.0 / NANOS_PER_MILLI + self.subsec_nanos() / NANOS_PER_MILLI } /// Returns the fractional part of this `Duration`, in whole microseconds. @@ -381,7 +393,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_micros(&self) -> u32 { - self.nanos.0 / NANOS_PER_MICRO + self.subsec_nanos() / NANOS_PER_MICRO } /// Returns the fractional part of this `Duration`, in nanoseconds. @@ -404,7 +416,7 @@ impl Duration { #[must_use] #[inline] pub const fn subsec_nanos(&self) -> u32 { - self.nanos.0 + self.nanos.0 as _ } /// Returns the total number of whole milliseconds contained by this `Duration`. @@ -422,7 +434,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_millis(&self) -> u128 { - self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128 + self.secs as u128 * MILLIS_PER_SEC as u128 + (self.subsec_nanos() / NANOS_PER_MILLI) as u128 } /// Returns the total number of whole microseconds contained by this `Duration`. @@ -440,7 +452,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_micros(&self) -> u128 { - self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128 + self.secs as u128 * MICROS_PER_SEC as u128 + (self.subsec_nanos() / NANOS_PER_MICRO) as u128 } /// Returns the total number of nanoseconds contained by this `Duration`. @@ -458,7 +470,7 @@ impl Duration { #[must_use] #[inline] pub const fn as_nanos(&self) -> u128 { - self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128 + self.secs as u128 * NANOS_PER_SEC as u128 + self.subsec_nanos() as u128 } /// Checked `Duration` addition. Computes `self + other`, returning [`None`] @@ -481,7 +493,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_add(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { - let mut nanos = self.nanos.0 + rhs.nanos.0; + let mut nanos = self.subsec_nanos() + rhs.subsec_nanos(); if nanos >= NANOS_PER_SEC { nanos -= NANOS_PER_SEC; if let Some(new_secs) = secs.checked_add(1) { @@ -541,11 +553,11 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_sub(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { - let nanos = if self.nanos.0 >= rhs.nanos.0 { - self.nanos.0 - rhs.nanos.0 + let nanos = if self.subsec_nanos() >= rhs.subsec_nanos() { + self.subsec_nanos() - rhs.subsec_nanos() } else if let Some(sub_secs) = secs.checked_sub(1) { secs = sub_secs; - self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 + self.subsec_nanos() + NANOS_PER_SEC - rhs.subsec_nanos() } else { return None; }; @@ -599,7 +611,7 @@ impl Duration { #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn checked_mul(self, rhs: u32) -> Option { // Multiply nanoseconds as u64, because it cannot overflow that way. - let total_nanos = self.nanos.0 as u64 * rhs as u64; + let total_nanos = self.subsec_nanos() as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; if let Some(s) = self.secs.checked_mul(rhs as u64) { @@ -659,7 +671,7 @@ impl Duration { let secs = self.secs / (rhs as u64); let carry = self.secs - secs * (rhs as u64); let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64); - let nanos = self.nanos.0 / rhs + (extra_nanos as u32); + let nanos = self.subsec_nanos() / rhs + (extra_nanos as u32); debug_assert!(nanos < NANOS_PER_SEC); Some(Duration::new(secs, nanos)) } else { @@ -683,7 +695,7 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f64(&self) -> f64 { - (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64) + (self.secs as f64) + (self.subsec_nanos() as f64) / (NANOS_PER_SEC as f64) } /// Returns the number of seconds contained by this `Duration` as `f32`. @@ -702,7 +714,7 @@ impl Duration { #[inline] #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] pub const fn as_secs_f32(&self) -> f32 { - (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) + (self.secs as f32) + (self.subsec_nanos() as f32) / (NANOS_PER_SEC as f32) } /// Creates a new `Duration` from the specified number of seconds represented @@ -993,13 +1005,13 @@ macro_rules! sum_durations { for entry in $iter { total_secs = total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); - total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) { + total_nanos = match total_nanos.checked_add(entry.subsec_nanos() as u64) { Some(n) => n, None => { total_secs = total_secs .checked_add(total_nanos / NANOS_PER_SEC as u64) .expect("overflow in iter::sum over durations"); - (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64 + (total_nanos % NANOS_PER_SEC as u64) + entry.subsec_nanos() as u64 } }; } @@ -1191,27 +1203,27 @@ impl fmt::Debug for Duration { let prefix = if f.sign_plus() { "+" } else { "" }; if self.secs > 0 { - fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") - } else if self.nanos.0 >= NANOS_PER_MILLI { + fmt_decimal(f, self.secs, self.subsec_nanos(), NANOS_PER_SEC / 10, prefix, "s") + } else if self.subsec_nanos() >= NANOS_PER_MILLI { fmt_decimal( f, - (self.nanos.0 / NANOS_PER_MILLI) as u64, - self.nanos.0 % NANOS_PER_MILLI, + (self.subsec_nanos() / NANOS_PER_MILLI) as u64, + self.subsec_nanos() % NANOS_PER_MILLI, NANOS_PER_MILLI / 10, prefix, "ms", ) - } else if self.nanos.0 >= NANOS_PER_MICRO { + } else if self.subsec_nanos() >= NANOS_PER_MICRO { fmt_decimal( f, - (self.nanos.0 / NANOS_PER_MICRO) as u64, - self.nanos.0 % NANOS_PER_MICRO, + (self.subsec_nanos() / NANOS_PER_MICRO) as u64, + self.subsec_nanos() % NANOS_PER_MICRO, NANOS_PER_MICRO / 10, prefix, "µs", ) } else { - fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns") + fmt_decimal(f, self.subsec_nanos() as u64, 0, 1, prefix, "ns") } } } diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index c41e093a7e5c6..9a491885899ba 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -73,7 +73,7 @@ impl BorrowedFd<'_> { pub const unsafe fn borrow_raw(fd: RawFd) -> Self { assert!(fd != u32::MAX as RawFd); // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd, _phantom: PhantomData } } + unsafe { Self { fd: fd as _, _phantom: PhantomData as _ } } } } @@ -126,7 +126,7 @@ impl BorrowedFd<'_> { impl AsRawFd for BorrowedFd<'_> { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd as i32 } } @@ -134,7 +134,7 @@ impl AsRawFd for BorrowedFd<'_> { impl AsRawFd for OwnedFd { #[inline] fn as_raw_fd(&self) -> RawFd { - self.fd + self.fd as i32 } } @@ -142,7 +142,7 @@ impl AsRawFd for OwnedFd { impl IntoRawFd for OwnedFd { #[inline] fn into_raw_fd(self) -> RawFd { - let fd = self.fd; + let fd = self.as_raw_fd(); forget(self); fd } @@ -160,7 +160,7 @@ impl FromRawFd for OwnedFd { unsafe fn from_raw_fd(fd: RawFd) -> Self { assert_ne!(fd, u32::MAX as RawFd); // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) - unsafe { Self { fd } } + unsafe { Self { fd: fd as _ } } } } @@ -174,7 +174,7 @@ impl Drop for OwnedFd { // the file descriptor was closed or not, and if we retried (for // something like EINTR), we might close another valid file descriptor // opened after we closed ours. - let _ = libc::close(self.fd); + let _ = libc::close(self.fd as i32); } } } diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 2daad981b73e9..c580b31f6cc4b 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -9,12 +9,24 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; pub const TIMESPEC_MAX: libc::timespec = libc::timespec { tv_sec: ::MAX, tv_nsec: 1_000_000_000 - 1 }; -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Eq, Ord, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(0)] #[rustc_layout_scalar_valid_range_end(999_999_999)] struct Nanoseconds(u32); +impl PartialOrd for Nanoseconds { + fn partial_cmp(&self, other: &Self) -> Option { + (self.0 as u32).partial_cmp(&(other.0 as u32)) + } +} + +impl PartialEq for Nanoseconds { + fn eq(&self, other: &Self) -> bool { + (self.0 as u32) == (other.0 as u32) + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SystemTime { pub(in crate::sys::unix) t: Timespec, @@ -68,7 +80,7 @@ impl Timespec { const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec { assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64); // SAFETY: The assert above checks tv_nsec is within the valid range - Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } } + Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32 as _) } } } pub fn sub_timespec(&self, other: &Timespec) -> Result { @@ -86,12 +98,15 @@ impl Timespec { // // Ideally this code could be rearranged such that it more // directly expresses the lower-cost behavior we want from it. - let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 { - ((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0) + let (secs, nsec) = if self.tv_nsec.0 as u32 >= other.tv_nsec.0 as u32 { + ( + (self.tv_sec - other.tv_sec) as u64, + self.tv_nsec.0 as u32 - other.tv_nsec.0 as u32, + ) } else { ( (self.tv_sec - other.tv_sec - 1) as u64, - self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0, + self.tv_nsec.0 as u32 + (NSEC_PER_SEC as u32) - other.tv_nsec.0 as u32, ) }; @@ -113,7 +128,7 @@ impl Timespec { // Nano calculations can't overflow because nanos are <1B which fit // in a u32. - let mut nsec = other.subsec_nanos() + self.tv_nsec.0; + let mut nsec = other.subsec_nanos() + self.tv_nsec.0 as u32; if nsec >= NSEC_PER_SEC as u32 { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; @@ -129,7 +144,7 @@ impl Timespec { .and_then(|secs| self.tv_sec.checked_sub(secs))?; // Similar to above, nanos can't overflow. - let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32; + let mut nsec = self.tv_nsec.0 as u32 as i32 - other.subsec_nanos() as i32; if nsec < 0 { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; diff --git a/tests/mir-opt/const_prop/boxes.main.ConstProp.diff b/tests/mir-opt/const_prop/boxes.main.ConstProp.diff index 5ec421eb2edd9..005e36886cb1d 100644 --- a/tests/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -35,11 +35,11 @@ bb1: { StorageLive(_7); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 _7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:+1:14: +1:22 - _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:19: +1:21 + _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: (*const i32) is 1..) as *const i32 (StripPattern); // scope 0 at $DIR/boxes.rs:+1:19: +1:21 (*_8) = const 42_i32; // scope 0 at $DIR/boxes.rs:+1:19: +1:21 _3 = move _7; // scope 0 at $DIR/boxes.rs:+1:14: +1:22 StorageDead(_7); // scope 0 at $DIR/boxes.rs:+1:21: +1:22 - _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 + _9 = (((_3.0: std::ptr::Unique).0: std::ptr::NonNull).0: (*const i32) is 1..) as *const i32 (StripPattern); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 _2 = (*_9); // scope 0 at $DIR/boxes.rs:+1:13: +1:22 _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:+1:13: +1:26 StorageDead(_2); // scope 0 at $DIR/boxes.rs:+1:25: +1:26 diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff index a28da146e3786..1cd37ee11d301 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff @@ -9,16 +9,17 @@ let mut _4: *mut u8; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 let mut _5: std::boxed::Box>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 - let mut _7: *const std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 -+ let mut _8: &mut std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -+ let mut _9: std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + let mut _7: *const std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 + let mut _8: *const std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 ++ let mut _9: &mut std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ let mut _10: std::vec::Vec; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 scope 1 { debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11 } scope 2 { } + scope 3 (inlined Vec::::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43 -+ let mut _10: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ let mut _11: alloc::raw_vec::RawVec; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + } bb0: { @@ -34,13 +35,13 @@ bb1: { StorageLive(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 _5 = ShallowInitBox(move _4, std::vec::Vec); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 - _7 = (((_5.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -- (*_7) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -+ StorageLive(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -+ _8 = &mut (*_7); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + _8 = (((_5.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: (*const std::vec::Vec) is 1..) as *const std::vec::Vec (StripPattern); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 +- (*_8) = Vec::::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + StorageLive(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ _10 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _9 = &mut (*_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_10); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_11); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _11 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL // mir::Constant - // + span: $DIR/inline_into_box_place.rs:8:33: 8:41 - // + user_ty: UserType(1) @@ -51,13 +52,13 @@ + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) + // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } -+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ (_9.0: alloc::raw_vec::RawVec) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL -+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ Deinit(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (_10.0: alloc::raw_vec::RawVec) = move _11; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (_10.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_11); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (*_9) = move _10; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageDead(_10); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 -+ StorageDead(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 _1 = move _5; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 _0 = const (); // scope 0 at $DIR/inline_into_box_place.rs:+0:11: +2:2 @@ -77,6 +78,7 @@ - } - - bb5 (cleanup): { +- _7 = (((_5.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: (*const std::vec::Vec) is 1..) as *const std::vec::Vec (StripPattern); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 - _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 - // mir::Constant - // + span: $DIR/inline_into_box_place.rs:8:42: 8:43 diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index b6aff30149fad..fc16ff72c655f 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -22,7 +22,7 @@ fn b(_1: &mut Box) -> &mut T { StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _7 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _8 = (((_7.0: std::ptr::Unique).0: std::ptr::NonNull).0: (*const T) is 1..) as *const T (StripPattern); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _6 = &mut (*_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 4f9342247d70e..6609c388b0ee1 100644 --- a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -16,7 +16,7 @@ fn d(_1: &Box) -> &T { StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _3 = &(*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 _4 = deref_copy (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL - _5 = (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _5 = (((_4.0: std::ptr::Unique).0: std::ptr::NonNull).0: (*const T) is 1..) as *const T (StripPattern); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _2 = &(*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL _0 = &(*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-match.mirunsafeck.stderr b/tests/ui/attributes/unsafe/unsafe-borrow-match.mirunsafeck.stderr new file mode 100644 index 0000000000000..8096969f6296d --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-match.mirunsafeck.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/unsafe-borrow-match.rs:13:17 + | +LL | match &mut foo { + | -------- this expression has type `&mut NonZero<_>` +LL | NonZero((a,)) => *a = 0_i32 as _, + | ^^^^ expected pattern, found tuple + | + = note: expected pattern type `_ is 1..` + found tuple `(_,)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-match.rs b/tests/ui/attributes/unsafe/unsafe-borrow-match.rs new file mode 100644 index 0000000000000..335da966b45d4 --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-match.rs @@ -0,0 +1,18 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn mtch() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1_i32,) as _) }; + match &mut foo { + NonZero((a,)) => *a = 0_i32 as _, + //~^ ERROR: mismatched type + } +} + +fn main() {} diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-match.thirunsafeck.stderr b/tests/ui/attributes/unsafe/unsafe-borrow-match.thirunsafeck.stderr new file mode 100644 index 0000000000000..8096969f6296d --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-match.thirunsafeck.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/unsafe-borrow-match.rs:13:17 + | +LL | match &mut foo { + | -------- this expression has type `&mut NonZero<_>` +LL | NonZero((a,)) => *a = 0_i32 as _, + | ^^^^ expected pattern, found tuple + | + = note: expected pattern type `_ is 1..` + found tuple `(_,)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-tuple.mirunsafeck.stderr b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.mirunsafeck.stderr new file mode 100644 index 0000000000000..ecba758c2e56a --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.mirunsafeck.stderr @@ -0,0 +1,16 @@ +error[E0282]: type annotations needed + --> $DIR/unsafe-borrow-tuple.rs:12:18 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^ cannot infer type + +error[E0609]: no field `0` on type `_ is 1..` + --> $DIR/unsafe-borrow-tuple.rs:12:24 + | +LL | let a = &mut foo.0.0; + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-tuple.rs b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.rs new file mode 100644 index 0000000000000..a40115169eec8 --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.rs @@ -0,0 +1,17 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn tuple_struct() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,) as _) }; + let a = &mut foo.0.0; + //~^ ERROR: type annotations needed + //~| ERROR: no field `0` on type `_ is 1..` +} + +fn main() {} diff --git a/tests/ui/attributes/unsafe/unsafe-borrow-tuple.thirunsafeck.stderr b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.thirunsafeck.stderr new file mode 100644 index 0000000000000..ecba758c2e56a --- /dev/null +++ b/tests/ui/attributes/unsafe/unsafe-borrow-tuple.thirunsafeck.stderr @@ -0,0 +1,16 @@ +error[E0282]: type annotations needed + --> $DIR/unsafe-borrow-tuple.rs:12:18 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^ cannot infer type + +error[E0609]: no field `0` on type `_ is 1..` + --> $DIR/unsafe-borrow-tuple.rs:12:24 + | +LL | let a = &mut foo.0.0; + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index e4c5e62f6bd3a..dc47ddb7f19a8 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -54,10 +54,10 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:54:1 + --> $DIR/raw-bytes.rs:53:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -65,10 +65,10 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:57:1 + --> $DIR/raw-bytes.rs:56:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 1, align: 1) { @@ -76,10 +76,10 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:59:1 + --> $DIR/raw-bytes.rs:58:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { @@ -87,10 +87,10 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:65:1 + --> $DIR/raw-bytes.rs:64:1 | -LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42_u32 as _) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 42, but expected something in the range 10..=30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -98,10 +98,10 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:71:1 + --> $DIR/raw-bytes.rs:70:1 | -LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20_u32 as _) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { @@ -109,10 +109,10 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:74:1 + --> $DIR/raw-bytes.rs:73:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 16, align: 8) { @@ -120,7 +120,7 @@ LL | const NULL_FAT_PTR: NonNull = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:82:1 + --> $DIR/raw-bytes.rs:80:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) @@ -131,7 +131,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:86:1 + --> $DIR/raw-bytes.rs:84:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) @@ -142,7 +142,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:90:1 + --> $DIR/raw-bytes.rs:88:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null reference @@ -153,7 +153,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:93:1 + --> $DIR/raw-bytes.rs:91:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a null box @@ -164,7 +164,7 @@ LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:96:1 + --> $DIR/raw-bytes.rs:94:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated) @@ -175,7 +175,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:99:1 + --> $DIR/raw-bytes.rs:97:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated) @@ -186,7 +186,7 @@ LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:102:1 + --> $DIR/raw-bytes.rs:100:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer @@ -197,7 +197,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:104:1 + --> $DIR/raw-bytes.rs:102:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer @@ -208,7 +208,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:106:1 + --> $DIR/raw-bytes.rs:104:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a function pointer @@ -219,7 +219,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:112:1 + --> $DIR/raw-bytes.rs:110:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar @@ -230,7 +230,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:137:1 + --> $DIR/raw-bytes.rs:134:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -241,7 +241,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:139:1 + --> $DIR/raw-bytes.rs:136:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object @@ -252,7 +252,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:141:1 + --> $DIR/raw-bytes.rs:138:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -263,7 +263,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:144:1 + --> $DIR/raw-bytes.rs:141:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .: encountered uninitialized data in `str` @@ -274,9 +274,9 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:146:1 + --> $DIR/raw-bytes.rs:143:1 | -LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; +LL | const MYSTR_NO_INIT: &MyStr = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered uninitialized data in `str` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -285,7 +285,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:148:1 + --> $DIR/raw-bytes.rs:146:1 | LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes @@ -297,7 +297,7 @@ LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _> } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:152:1 + --> $DIR/raw-bytes.rs:150:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) @@ -308,7 +308,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:154:1 + --> $DIR/raw-bytes.rs:152:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object @@ -319,7 +319,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:157:1 + --> $DIR/raw-bytes.rs:155:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) @@ -330,7 +330,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:160:1 + --> $DIR/raw-bytes.rs:158:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x03, but expected a boolean @@ -341,13 +341,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; } note: erroneous constant used - --> $DIR/raw-bytes.rs:160:40 + --> $DIR/raw-bytes.rs:158:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:166:1 + --> $DIR/raw-bytes.rs:163:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered 0x03, but expected a boolean @@ -358,13 +358,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 } note: erroneous constant used - --> $DIR/raw-bytes.rs:166:42 + --> $DIR/raw-bytes.rs:163:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:170:1 + --> $DIR/raw-bytes.rs:167:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean @@ -375,13 +375,13 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran } note: erroneous constant used - --> $DIR/raw-bytes.rs:170:42 + --> $DIR/raw-bytes.rs:167:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:175:1 + --> $DIR/raw-bytes.rs:172:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer @@ -392,7 +392,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:179:1 + --> $DIR/raw-bytes.rs:176:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer @@ -403,7 +403,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:183:1 + --> $DIR/raw-bytes.rs:180:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer @@ -414,9 +414,9 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:186:1 + --> $DIR/raw-bytes.rs:183:1 | -LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; +LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -425,7 +425,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:190:1 + --> $DIR/raw-bytes.rs:188:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..: encountered 0x03, but expected a boolean @@ -436,7 +436,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:194:1 + --> $DIR/raw-bytes.rs:192:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer @@ -447,7 +447,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:196:1 + --> $DIR/raw-bytes.rs:194:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer @@ -458,7 +458,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:201:1 + --> $DIR/raw-bytes.rs:198:1 | LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000000, but expected a valid enum tag @@ -469,7 +469,7 @@ LL | const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchec } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:205:1 + --> $DIR/raw-bytes.rs:202:1 | LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .align.0.: encountered 0x0000000000000003, but expected a valid enum tag @@ -480,7 +480,7 @@ LL | const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unche } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:209:1 + --> $DIR/raw-bytes.rs:205:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type [!; 1] @@ -491,7 +491,7 @@ LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:210:1 + --> $DIR/raw-bytes.rs:206:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -502,7 +502,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:211:1 + --> $DIR/raw-bytes.rs:207:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; | ^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered a value of the never type `!` @@ -513,7 +513,7 @@ LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:215:1 + --> $DIR/raw-bytes.rs:210:1 | LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes @@ -524,7 +524,7 @@ LL | pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) } } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:218:1 + --> $DIR/raw-bytes.rs:213:1 | LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) }; | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes @@ -536,7 +536,7 @@ LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem: } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:221:1 + --> $DIR/raw-bytes.rs:216:1 | LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean @@ -547,7 +547,7 @@ LL | pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:225:1 + --> $DIR/raw-bytes.rs:220:1 | LL | pub static S7: &[u16] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[1]: encountered uninitialized bytes @@ -558,7 +558,7 @@ LL | pub static S7: &[u16] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:232:1 + --> $DIR/raw-bytes.rs:227:1 | LL | pub static R4: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered uninitialized bytes @@ -569,7 +569,7 @@ LL | pub static R4: &[u8] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:237:1 + --> $DIR/raw-bytes.rs:232:1 | LL | pub static R5: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes @@ -581,7 +581,7 @@ LL | pub static R5: &[u8] = unsafe { } error[E0080]: it is undefined behavior to use this value - --> $DIR/raw-bytes.rs:242:1 + --> $DIR/raw-bytes.rs:237:1 | LL | pub static R6: &[bool] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .[0]: encountered 0x11, but expected a boolean diff --git a/tests/ui/consts/const-eval/raw-bytes.rs b/tests/ui/consts/const-eval/raw-bytes.rs index 6c1238c0a063e..7025f4a19dd83 100644 --- a/tests/ui/consts/const-eval/raw-bytes.rs +++ b/tests/ui/consts/const-eval/raw-bytes.rs @@ -6,10 +6,10 @@ #![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)] #![allow(invalid_value)] -use std::mem; use std::alloc::Layout; -use std::ptr::NonNull; +use std::mem; use std::num::{NonZeroU8, NonZeroUsize}; +use std::ptr::NonNull; use std::slice::{from_ptr_range, from_raw_parts}; #[repr(usize)] @@ -50,7 +50,6 @@ const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior - const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value @@ -62,23 +61,22 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; #[rustc_layout_scalar_valid_range_start(10)] #[rustc_layout_scalar_valid_range_end(30)] struct RestrictedRange1(u32); -const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; +const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42_u32 as _) }; //~^ ERROR it is undefined behavior to use this value #[rustc_layout_scalar_valid_range_start(30)] #[rustc_layout_scalar_valid_range_end(10)] struct RestrictedRange2(u32); -const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; +const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20_u32 as _) }; //~^ ERROR it is undefined behavior to use this value const NULL_FAT_PTR: NonNull = unsafe { -//~^ ERROR it is undefined behavior to use this value + //~^ ERROR it is undefined behavior to use this value let x: &dyn Send = &42; let meta = std::ptr::metadata(x); mem::transmute((0_usize, meta)) }; - const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value //~| constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) @@ -112,7 +110,6 @@ enum Bar {} const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR it is undefined behavior to use this value - /// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error /// message. #[repr(transparent)] @@ -143,8 +140,9 @@ const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX) const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; //~^ ERROR it is undefined behavior to use this value -const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; -//~^ ERROR it is undefined behavior to use this value +const MYSTR_NO_INIT: &MyStr = + //~^ ERROR it is undefined behavior to use this value + unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) }; //~^ ERROR: it is undefined behavior to use this value @@ -161,7 +159,6 @@ const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; //~^ ERROR it is undefined behavior to use this value //~| constant - // bad: sized field is not okay const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); //~^ ERROR it is undefined behavior to use this value @@ -183,9 +180,10 @@ const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8 const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; //~^ ERROR it is undefined behavior to use this value //~| expected a vtable -const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; -//~^ ERROR it is undefined behavior to use this value -//~| expected a vtable +const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = + //~^ ERROR it is undefined behavior to use this value + //~| expected a vtable + unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; // bad data *inside* the trait object const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; //~^ ERROR it is undefined behavior to use this value @@ -196,7 +194,6 @@ const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value - // not ok, since alignment needs to be non-zero. const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; //~^ ERROR it is undefined behavior to use this value @@ -205,12 +202,10 @@ const LAYOUT_INVALID_ZERO: Layout = unsafe { Layout::from_size_align_unchecked(0 const LAYOUT_INVALID_THREE: Layout = unsafe { Layout::from_size_align_unchecked(9, 3) }; //~^ ERROR it is undefined behavior to use this value - const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR undefined behavior const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR undefined behavior - // Reading uninitialized data pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) }; //~^ ERROR: it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs index a64b3a74cf6c0..7bbbe9f529f56 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.rs +++ b/tests/ui/consts/const-eval/ub-nonnull.rs @@ -5,8 +5,8 @@ #![allow(invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; -use std::ptr::NonNull; use std::num::{NonZeroU8, NonZeroUsize}; +use std::ptr::NonNull; const NON_NULL: NonNull = unsafe { mem::transmute(1usize) }; const NON_NULL_PTR: NonNull = unsafe { mem::transmute(&1) }; @@ -14,12 +14,14 @@ const NON_NULL_PTR: NonNull = unsafe { mem::transmute(&1) }; const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value -const OUT_OF_BOUNDS_PTR: NonNull = { unsafe { - let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle - // Use address-of-element for pointer arithmetic. This could wrap around to null! - let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed - mem::transmute(out_of_bounds_ptr) -} }; +const OUT_OF_BOUNDS_PTR: NonNull = { + unsafe { + let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + // Use address-of-element for pointer arithmetic. This could wrap around to null! + let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed + mem::transmute(out_of_bounds_ptr) + } +}; const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; //~^ ERROR it is undefined behavior to use this value @@ -40,17 +42,17 @@ const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; #[rustc_layout_scalar_valid_range_start(10)] #[rustc_layout_scalar_valid_range_end(30)] struct RestrictedRange1(u32); -const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; +const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42_u32 as _) }; //~^ ERROR it is undefined behavior to use this value #[rustc_layout_scalar_valid_range_start(30)] #[rustc_layout_scalar_valid_range_end(10)] struct RestrictedRange2(u32); -const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; +const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20_u32 as _) }; //~^ ERROR it is undefined behavior to use this value const NULL_FAT_PTR: NonNull = unsafe { -//~^ ERROR it is undefined behavior to use this value + //~^ ERROR it is undefined behavior to use this value let x: &dyn Send = &42; let meta = std::ptr::metadata(x); mem::transmute((0_usize, meta)) diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 9616487080459..d96d568a6c9b6 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:14:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -10,16 +10,16 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; } error[E0080]: evaluation of constant value failed - --> $DIR/ub-nonnull.rs:20:30 + --> $DIR/ub-nonnull.rs:21:34 | -LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds +LL | let out_of_bounds_ptr = &ptr[255]; + | ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:24:1 + --> $DIR/ub-nonnull.rs:26:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -27,10 +27,10 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:26:1 + --> $DIR/ub-nonnull.rs:28:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -38,16 +38,16 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; } error[E0080]: evaluation of constant value failed - --> $DIR/ub-nonnull.rs:34:36 + --> $DIR/ub-nonnull.rs:36:36 | LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:43:1 + --> $DIR/ub-nonnull.rs:45:1 | -LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30 +LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42_u32 as _) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 42, but expected something in the range 10..=30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -55,10 +55,10 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:49:1 + --> $DIR/ub-nonnull.rs:51:1 | -LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30 +LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20_u32 as _) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 20, but expected something less or equal to 10, or greater or equal to 30 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -66,10 +66,10 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:52:1 + --> $DIR/ub-nonnull.rs:54:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { diff --git a/tests/ui/impl-trait/unsafety-checking-cycle.rs b/tests/ui/impl-trait/unsafety-checking-cycle.rs index 4a5831c5b73df..4957313448772 100644 --- a/tests/ui/impl-trait/unsafety-checking-cycle.rs +++ b/tests/ui/impl-trait/unsafety-checking-cycle.rs @@ -26,7 +26,7 @@ fn not_field(c: bool) -> impl Sized { let x = unsafe { NonZero(not_field(false)) }; &x; } - 5u32 + unsafe { NonZero::(5u32 as _) }.0 } fn main() {} diff --git a/tests/ui/layout/valid_range_oob.rs b/tests/ui/layout/valid_range_oob.rs index 74aa47fe40549..19e465f1ba770 100644 --- a/tests/ui/layout/valid_range_oob.rs +++ b/tests/ui/layout/valid_range_oob.rs @@ -10,6 +10,6 @@ struct Foo(i8); // Need to do in a constant, as runtime codegen // does not compute the layout of `Foo` in check builds. -const FOO: Foo = unsafe { Foo(1) }; +const FOO: Foo = unsafe { Foo(1_i8 as _) }; fn main() {} diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr index 7398f01643f6e..040c90d1a6028 100644 --- a/tests/ui/layout/valid_range_oob.stderr +++ b/tests/ui/layout/valid_range_oob.stderr @@ -1,6 +1,13 @@ error: internal compiler error: unexpected panic query stack during panic: -#0 [layout_of] computing layout of `Foo` -#1 [eval_to_allocation_raw] const-evaluating + checking `FOO` +#0 [layout_of] computing layout of `i8 is ..=257` +#1 [check_mod_deathness] checking deathness of variables in top-level module +end of query stack + +error: internal compiler error: unexpected panic + +query stack during panic: +#0 [layout_of] computing layout of `i8 is ..=257` +#1 [layout_of] computing layout of `Foo` end of query stack diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index 48fd4169da7c9..5d4f0e41f3714 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -332,7 +332,6 @@ LL | let _val: NonNull = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `std::ptr::NonNull` must be non-null - = note: raw pointers must be initialized error: the type `(NonZeroU32, i32)` does not permit zero-initialization --> $DIR/invalid_value.rs:95:39 @@ -355,7 +354,6 @@ LL | let _val: (NonZeroU32, i32) = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `std::num::NonZeroU32` must be non-null - = note: integers must be initialized error: the type `*const dyn Send` does not permit zero-initialization --> $DIR/invalid_value.rs:98:37 @@ -462,7 +460,6 @@ note: because `std::num::NonZeroU32` must be non-null (in this field of the only | LL | Banana(NonZeroU32), | ^^^^^^^^^^ - = note: integers must be initialized error: the type `bool` does not permit being left uninitialized --> $DIR/invalid_value.rs:112:26 @@ -501,11 +498,6 @@ LL | let _val: NonBig = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `NonBig` must be initialized inside its custom valid range -note: integers must be initialized (in this struct field) - --> $DIR/invalid_value.rs:23:26 - | -LL | pub(crate) struct NonBig(u64); - | ^^^ error: the type `Fruit` does not permit being left uninitialized --> $DIR/invalid_value.rs:121:27 @@ -587,11 +579,6 @@ LL | let _val: WrapAroundRange = mem::uninitialized(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `WrapAroundRange` must be initialized inside its custom valid range -note: integers must be initialized (in this struct field) - --> $DIR/invalid_value.rs:49:35 - | -LL | pub(crate) struct WrapAroundRange(u8); - | ^^ error: the type `Result` does not permit being left uninitialized --> $DIR/invalid_value.rs:144:38 @@ -659,7 +646,6 @@ LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: `std::ptr::NonNull` must be non-null - = note: raw pointers must be initialized error: the type `bool` does not permit being left uninitialized --> $DIR/invalid_value.rs:159:26 diff --git a/tests/ui/mir/ssa-analysis-regression-50041.rs b/tests/ui/mir/ssa-analysis-regression-50041.rs index ebc3e2f8c0e31..47b9b6af48aa0 100644 --- a/tests/ui/mir/ssa-analysis-regression-50041.rs +++ b/tests/ui/mir/ssa-analysis-regression-50041.rs @@ -2,9 +2,12 @@ // compile-flags: -Z mir-opt-level=4 #![crate_type = "lib"] -#![feature(lang_items)] +#![feature(lang_items, rustc_attrs)] #![no_std] +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_nonnull_optimization_guaranteed] struct NonNull(*const T); struct Unique(NonNull); @@ -19,7 +22,7 @@ impl Drop for Box { #[lang = "box_free"] #[inline(always)] unsafe fn box_free(ptr: Unique) { - dealloc(ptr.0.0) + dealloc(ptr.0.0 as _) } #[inline(never)] diff --git a/tests/ui/unique/unique-autoderef-index.rs b/tests/ui/unique/unique-autoderef-index.rs index ea6598a7f6b35..430215aca130a 100644 --- a/tests/ui/unique/unique-autoderef-index.rs +++ b/tests/ui/unique/unique-autoderef-index.rs @@ -1,6 +1,31 @@ // run-pass +// compile-flags: -C opt-level=0 + +#![allow(unused_must_use, unused_variables)] +#![feature(rustc_attrs)] + +#[repr(transparent)] +#[rustc_layout_scalar_valid_range_start(1)] +#[rustc_nonnull_optimization_guaranteed] +pub struct Unique { + pointer: *const T, +} + +impl Unique { + pub fn as_ptr(&self) -> *mut T { + self.pointer as *const T as *mut T + } +} + +struct Droppy(Unique); + +impl Drop for Droppy { + fn drop(&mut self) { + self.0.as_ptr(); + } +} pub fn main() { - let i: Box<_> = Box::new(vec![100]); - assert_eq!((*i)[0], 100); + let mut x = 42; + Box::new(Droppy(unsafe { Unique { pointer: &mut x as *const i32 as _ } })); } diff --git a/tests/ui/unique/unique-object-move.rs b/tests/ui/unique/unique-object-move.rs index bb35a9b2d73e2..4c98b6a4e3972 100644 --- a/tests/ui/unique/unique-object-move.rs +++ b/tests/ui/unique/unique-object-move.rs @@ -4,13 +4,15 @@ // pretty-expanded FIXME #23616 -pub trait EventLoop { fn foo(&self) {} } +pub trait EventLoop { + fn foo(&self) {} +} pub struct UvEventLoop { - uvio: isize + uvio: isize, } -impl EventLoop for UvEventLoop { } +impl EventLoop for UvEventLoop {} pub fn main() { let loop_: Box = Box::new(UvEventLoop { uvio: 0 }) as Box; diff --git a/tests/ui/unsafe/ranged_ints.mir.stderr b/tests/ui/unsafe/ranged_ints.mir.stderr index f9ef7834e1e50..f7b732fe5d338 100644 --- a/tests/ui/unsafe/ranged_ints.mir.stderr +++ b/tests/ui/unsafe/ranged_ints.mir.stderr @@ -1,8 +1,8 @@ error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block --> $DIR/ranged_ints.rs:10:14 | -LL | let _x = NonZero(0); - | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr +LL | let _x = NonZero(0 as _); + | ^^^^^^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior diff --git a/tests/ui/unsafe/ranged_ints.rs b/tests/ui/unsafe/ranged_ints.rs index 05efe87ba6e03..7e211ed8d0da1 100644 --- a/tests/ui/unsafe/ranged_ints.rs +++ b/tests/ui/unsafe/ranged_ints.rs @@ -7,5 +7,5 @@ #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); fn main() { - let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr + let _x = NonZero(0 as _); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr } diff --git a/tests/ui/unsafe/ranged_ints.thir.stderr b/tests/ui/unsafe/ranged_ints.thir.stderr index f9ef7834e1e50..f7b732fe5d338 100644 --- a/tests/ui/unsafe/ranged_ints.thir.stderr +++ b/tests/ui/unsafe/ranged_ints.thir.stderr @@ -1,8 +1,8 @@ error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block --> $DIR/ranged_ints.rs:10:14 | -LL | let _x = NonZero(0); - | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr +LL | let _x = NonZero(0 as _); + | ^^^^^^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs index 9a6bb18f92664..4feb45fa4c9c5 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -7,6 +7,6 @@ #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); fn main() { - let mut x = unsafe { NonZero(1) }; + let mut x = unsafe { NonZero(1 as _) }; let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints2_const.rs b/tests/ui/unsafe/ranged_ints2_const.rs index 56f5407bb6ebe..4417621a20d0b 100644 --- a/tests/ui/unsafe/ranged_ints2_const.rs +++ b/tests/ui/unsafe/ranged_ints2_const.rs @@ -10,20 +10,20 @@ fn main() { } const fn foo() -> NonZero { - let mut x = unsafe { NonZero(1) }; + let mut x = unsafe { NonZero(1 as _) }; let y = &mut x.0; //~ ERROR mutable references //~^ ERROR mutation of layout constrained field is unsafe - unsafe { NonZero(1) } + unsafe { NonZero(1_u32 as _) } } const fn bar() -> NonZero { - let mut x = unsafe { NonZero(1) }; + let mut x = unsafe { NonZero(1 as _) }; let y = unsafe { &mut x.0 }; //~ ERROR mutable references - unsafe { NonZero(1) } + unsafe { NonZero(1_u32 as _) } } const fn boo() -> NonZero { - let mut x = unsafe { NonZero(1) }; + let mut x = unsafe { NonZero(1 as _) }; unsafe { let y = &mut x.0; } //~ ERROR mutable references - unsafe { NonZero(1) } + unsafe { NonZero(1_u32 as _) } } diff --git a/tests/ui/unsafe/ranged_ints3.rs b/tests/ui/unsafe/ranged_ints3.rs index 76d4bfe95307d..313e7e6fb566e 100644 --- a/tests/ui/unsafe/ranged_ints3.rs +++ b/tests/ui/unsafe/ranged_ints3.rs @@ -9,6 +9,6 @@ use std::cell::Cell; #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); fn main() { - let mut x = unsafe { NonZero(Cell::new(1)) }; + let mut x = unsafe { NonZero(Cell::new(1) as _) }; let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability } diff --git a/tests/ui/unsafe/ranged_ints3_const.rs b/tests/ui/unsafe/ranged_ints3_const.rs index 637198d360422..42c0f68a2f1c8 100644 --- a/tests/ui/unsafe/ranged_ints3_const.rs +++ b/tests/ui/unsafe/ranged_ints3_const.rs @@ -11,14 +11,14 @@ pub(crate) struct NonZero(pub(crate) T); fn main() {} const fn foo() -> NonZero> { - let mut x = unsafe { NonZero(Cell::new(1)) }; + let mut x = unsafe { NonZero(Cell::new(1) as _) }; let y = &x.0; //~ ERROR the borrowed element may contain interior mutability //~^ ERROR borrow of layout constrained field with interior mutability - unsafe { NonZero(Cell::new(1)) } + unsafe { NonZero(Cell::new(1_u32) as _) } } const fn bar() -> NonZero> { - let mut x = unsafe { NonZero(Cell::new(1)) }; + let mut x = unsafe { NonZero(Cell::new(1) as _) }; let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability - unsafe { NonZero(Cell::new(1)) } + unsafe { NonZero(Cell::new(1_u32) as _) } } diff --git a/tests/ui/unsafe/ranged_ints3_match.rs b/tests/ui/unsafe/ranged_ints3_match.rs index d9fcf0bd665c2..02d14e75c6d21 100644 --- a/tests/ui/unsafe/ranged_ints3_match.rs +++ b/tests/ui/unsafe/ranged_ints3_match.rs @@ -9,13 +9,13 @@ use std::cell::Cell; #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); fn main() { - let mut x = unsafe { NonZero(Cell::new(1)) }; + let mut x = unsafe { NonZero(Cell::new(1) as _) }; match x { NonZero(ref x) => { x } //~^ ERROR borrow of layout constrained field with interior mutability }; - let mut y = unsafe { NonZero(42) }; + let mut y = unsafe { NonZero(42 as _) }; match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze match y { NonZero(ref mut y) => { y } }; //~^ ERROR mutation of layout constrained field diff --git a/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr index 493483d2c4540..0b3d4139f83ba 100644 --- a/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4.mirunsafeck.stderr @@ -1,8 +1,8 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block --> $DIR/ranged_ints4.rs:11:5 | -LL | x.0 = 0; - | ^^^^^^^ mutation of layout constrained field +LL | x.0 = 0 as _; + | ^^^^^^^^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values diff --git a/tests/ui/unsafe/ranged_ints4.rs b/tests/ui/unsafe/ranged_ints4.rs index fe80af454cb8d..ea5aecbc0958d 100644 --- a/tests/ui/unsafe/ranged_ints4.rs +++ b/tests/ui/unsafe/ranged_ints4.rs @@ -7,6 +7,6 @@ #[repr(transparent)] pub(crate) struct NonZero(pub(crate) T); fn main() { - let mut x = unsafe { NonZero(1) }; - x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe + let mut x = unsafe { NonZero(1 as _) }; + x.0 = 0 as _; //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr index 493483d2c4540..0b3d4139f83ba 100644 --- a/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4.thirunsafeck.stderr @@ -1,8 +1,8 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block --> $DIR/ranged_ints4.rs:11:5 | -LL | x.0 = 0; - | ^^^^^^^ mutation of layout constrained field +LL | x.0 = 0 as _; + | ^^^^^^^^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values diff --git a/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr index a06c6f479b8da..35d8bd1a6c67d 100644 --- a/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr @@ -1,8 +1,8 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block --> $DIR/ranged_ints4_const.rs:13:5 | -LL | x.0 = 0; - | ^^^^^^^ mutation of layout constrained field +LL | x.0 = 0_u32 as _; + | ^^^^^^^^^^^^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values diff --git a/tests/ui/unsafe/ranged_ints4_const.rs b/tests/ui/unsafe/ranged_ints4_const.rs index a43c8be71c4fd..d4da414e657e0 100644 --- a/tests/ui/unsafe/ranged_ints4_const.rs +++ b/tests/ui/unsafe/ranged_ints4_const.rs @@ -9,14 +9,14 @@ pub(crate) struct NonZero(pub(crate) T); fn main() {} const fn foo() -> NonZero { - let mut x = unsafe { NonZero(1) }; - x.0 = 0; + let mut x = unsafe { NonZero(1_u32 as _) }; + x.0 = 0_u32 as _; //~^ ERROR mutation of layout constrained field is unsafe x } const fn bar() -> NonZero { - let mut x = unsafe { NonZero(1) }; - unsafe { x.0 = 0 }; // this is UB + let mut x = unsafe { NonZero(1_u32 as _) }; + unsafe { x.0 = 0_u32 as _ }; // this is UB x } diff --git a/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr index a06c6f479b8da..35d8bd1a6c67d 100644 --- a/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr @@ -1,8 +1,8 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block --> $DIR/ranged_ints4_const.rs:13:5 | -LL | x.0 = 0; - | ^^^^^^^ mutation of layout constrained field +LL | x.0 = 0_u32 as _; + | ^^^^^^^^^^^^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values diff --git a/tests/ui/unsafe/ranged_ints_const.mir.stderr b/tests/ui/unsafe/ranged_ints_const.mir.stderr index 33d134c7ce59e..0d41cb47fd65e 100644 --- a/tests/ui/unsafe/ranged_ints_const.mir.stderr +++ b/tests/ui/unsafe/ranged_ints_const.mir.stderr @@ -1,8 +1,8 @@ error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block --> $DIR/ranged_ints_const.rs:11:34 | -LL | const fn foo() -> NonZero { NonZero(0) } - | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr +LL | const fn foo() -> NonZero { NonZero(0_u32 as _) } + | ^^^^^^^^^^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior diff --git a/tests/ui/unsafe/ranged_ints_const.rs b/tests/ui/unsafe/ranged_ints_const.rs index 472b096815075..bd6382cfcbac5 100644 --- a/tests/ui/unsafe/ranged_ints_const.rs +++ b/tests/ui/unsafe/ranged_ints_const.rs @@ -8,7 +8,7 @@ pub(crate) struct NonZero(pub(crate) T); fn main() {} -const fn foo() -> NonZero { NonZero(0) } +const fn foo() -> NonZero { NonZero(0_u32 as _) } //~^ ERROR initializing type with `rustc_layout_scalar_valid_range` attr is unsafe -const fn bar() -> NonZero { unsafe { NonZero(0) } } +const fn bar() -> NonZero { unsafe { NonZero(0_u32 as _) } } diff --git a/tests/ui/unsafe/ranged_ints_const.thir.stderr b/tests/ui/unsafe/ranged_ints_const.thir.stderr index 33d134c7ce59e..0d41cb47fd65e 100644 --- a/tests/ui/unsafe/ranged_ints_const.thir.stderr +++ b/tests/ui/unsafe/ranged_ints_const.thir.stderr @@ -1,8 +1,8 @@ error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block --> $DIR/ranged_ints_const.rs:11:34 | -LL | const fn foo() -> NonZero { NonZero(0) } - | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr +LL | const fn foo() -> NonZero { NonZero(0_u32 as _) } + | ^^^^^^^^^^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr | = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior diff --git a/tests/ui/unsafe/ranged_ints_macro.rs b/tests/ui/unsafe/ranged_ints_macro.rs index 8293d029951fa..f5a90934e2121 100644 --- a/tests/ui/unsafe/ranged_ints_macro.rs +++ b/tests/ui/unsafe/ranged_ints_macro.rs @@ -15,5 +15,5 @@ macro_rules! apply { apply!(1); fn main() { - let _x = unsafe { NonZero(1) }; + let _x = unsafe { NonZero(1 as _) }; } diff --git a/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr index 9abc51424abaf..2bf121582c355 100644 --- a/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-assign.mirunsafeck.stderr @@ -1,11 +1,16 @@ -error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block +error[E0282]: type annotations needed --> $DIR/unsafe-assign.rs:12:5 | -LL | foo.0.0 = 0; - | ^^^^^^^^^^^ mutation of layout constrained field +LL | foo.0.0 = 0_i32; + | ^^^^^^^ cannot infer type + +error[E0609]: no field `0` on type `_ is 1..` + --> $DIR/unsafe-assign.rs:12:11 | - = note: mutating layout constrained fields cannot statically be checked for valid values +LL | foo.0.0 = 0_i32; + | ^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/unsafe/unsafe-assign.rs b/tests/ui/unsafe/unsafe-assign.rs index 15273165b5e13..cdcb35260c1d8 100644 --- a/tests/ui/unsafe/unsafe-assign.rs +++ b/tests/ui/unsafe/unsafe-assign.rs @@ -8,17 +8,18 @@ fn nested_field() { #[rustc_layout_scalar_valid_range_start(1)] struct NonZero(T); - let mut foo = unsafe { NonZero((1,)) }; - foo.0.0 = 0; - //~^ ERROR: mutation of layout constrained field is unsafe + let mut foo = unsafe { NonZero((1_i32,) as _) }; + foo.0.0 = 0_i32; + //~^ ERROR: type annotations needed + //~| ERROR: no field `0` on type `_ is 1..` } fn block() { #[rustc_layout_scalar_valid_range_start(1)] struct NonZero(T); - let mut foo = unsafe { NonZero((1,)) }; - { foo.0 }.0 = 0; + let mut foo = unsafe { NonZero((1_i32,) as _) }; + { foo.0 as (_,) }.0 = 0_i32; // ^ not unsafe because the result of the block expression is a new place } diff --git a/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr index 9abc51424abaf..2bf121582c355 100644 --- a/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-assign.thirunsafeck.stderr @@ -1,11 +1,16 @@ -error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block +error[E0282]: type annotations needed --> $DIR/unsafe-assign.rs:12:5 | -LL | foo.0.0 = 0; - | ^^^^^^^^^^^ mutation of layout constrained field +LL | foo.0.0 = 0_i32; + | ^^^^^^^ cannot infer type + +error[E0609]: no field `0` on type `_ is 1..` + --> $DIR/unsafe-assign.rs:12:11 | - = note: mutating layout constrained fields cannot statically be checked for valid values +LL | foo.0.0 = 0_i32; + | ^ -error: aborting due to previous error +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr index a206722495ac3..1146f5f5347ca 100644 --- a/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-borrow.mirunsafeck.stderr @@ -1,27 +1,19 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:12:13 - | -LL | let a = &mut foo.0.0; - | ^^^^^^^^^^^^ mutation of layout constrained field - | - = note: mutating layout constrained fields cannot statically be checked for valid values - -error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:32:13 + --> $DIR/unsafe-borrow.rs:13:18 | LL | let a = &mut foo.0[2]; - | ^^^^^^^^^^^^^ mutation of layout constrained field + | ^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:51:18 + --> $DIR/unsafe-borrow.rs:23:18 | -LL | NonZero((a,)) => *a = 0, - | ^ mutation of layout constrained field +LL | let a = &mut foo.0[2]; + | ^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/unsafe-borrow.rs b/tests/ui/unsafe/unsafe-borrow.rs index 8dddc70be45c7..877b794d71724 100644 --- a/tests/ui/unsafe/unsafe-borrow.rs +++ b/tests/ui/unsafe/unsafe-borrow.rs @@ -2,25 +2,16 @@ // [thirunsafeck]compile-flags: -Z thir-unsafeck #![feature(rustc_attrs)] -#![allow(unused,dead_code)] - -fn tuple_struct() { - #[rustc_layout_scalar_valid_range_start(1)] - struct NonZero(T); - - let mut foo = unsafe { NonZero((1,)) }; - let a = &mut foo.0.0; - //~^ ERROR: mutation of layout constrained field is unsafe -} +#![allow(unused, dead_code)] fn slice() { #[rustc_layout_scalar_valid_range_start(1)] struct NonZero<'a, T>(&'a mut [T]); let mut nums = [1, 2, 3, 4]; - let mut foo = unsafe { NonZero(&mut nums[..]) }; + let mut foo = unsafe { NonZero(&mut nums[..] as _) }; let a = &mut foo.0[2]; - // ^ not unsafe because there is an implicit dereference here + //~^ ERROR: mutation of layout constrained field is unsafe } fn array() { @@ -28,7 +19,7 @@ fn array() { struct NonZero([T; 4]); let nums = [1, 2, 3, 4]; - let mut foo = unsafe { NonZero(nums) }; + let mut foo = unsafe { NonZero(nums as _) }; let a = &mut foo.0[2]; //~^ ERROR: mutation of layout constrained field is unsafe } @@ -37,20 +28,9 @@ fn block() { #[rustc_layout_scalar_valid_range_start(1)] struct NonZero(T); - let foo = unsafe { NonZero((1,)) }; - &mut { foo.0 }.0; + let foo = unsafe { NonZero((1,) as _) }; + &mut { foo.0 as (i32,) }.0; // ^ not unsafe because the result of the block expression is a new place } -fn mtch() { - #[rustc_layout_scalar_valid_range_start(1)] - struct NonZero(T); - - let mut foo = unsafe { NonZero((1,)) }; - match &mut foo { - NonZero((a,)) => *a = 0, - //~^ ERROR: mutation of layout constrained field is unsafe - } -} - fn main() {} diff --git a/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr index a206722495ac3..1146f5f5347ca 100644 --- a/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr +++ b/tests/ui/unsafe/unsafe-borrow.thirunsafeck.stderr @@ -1,27 +1,19 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:12:13 - | -LL | let a = &mut foo.0.0; - | ^^^^^^^^^^^^ mutation of layout constrained field - | - = note: mutating layout constrained fields cannot statically be checked for valid values - -error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:32:13 + --> $DIR/unsafe-borrow.rs:13:18 | LL | let a = &mut foo.0[2]; - | ^^^^^^^^^^^^^ mutation of layout constrained field + | ^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/unsafe-borrow.rs:51:18 + --> $DIR/unsafe-borrow.rs:23:18 | -LL | NonZero((a,)) => *a = 0, - | ^ mutation of layout constrained field +LL | let a = &mut foo.0[2]; + | ^^^^^ mutation of layout constrained field | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. From ce3e3d49e3d8219ab9ec745453e908f768fb1982 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 26 Jan 2023 09:20:58 +0000 Subject: [PATCH 06/10] Enable matching on pattern types via constants --- compiler/rustc_borrowck/src/type_check/mod.rs | 10 ++++- compiler/rustc_middle/src/mir/syntax.rs | 6 ++- .../src/build/matches/simplify.rs | 4 +- .../rustc_mir_build/src/build/matches/test.rs | 2 +- .../src/thir/pattern/const_to_pat.rs | 2 +- library/core/src/time.rs | 2 + tests/mir-opt/match_pattern_type.rs | 11 ++++++ ...tern_type.system_time_math.built.after.mir | 39 +++++++++++++++++++ 8 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 tests/mir-opt/match_pattern_type.rs create mode 100644 tests/mir-opt/match_pattern_type.system_time_math.built.after.mir diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index e488f757619d8..490ab60ee7fbb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -742,9 +742,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ProjectionElem::OpaqueCast(ty) => { let ty = self.sanitize_type(place, ty); let ty = self.cx.normalize(ty, location); + let compare_ty = match *base.ty.kind() { + ty::Alias(ty::Opaque, _) => base.ty, + ty::Pat(inner, _) => inner, + _ => { + span_mirbug!(self, place, "tried to cast {} to {ty}", base.ty); + base.ty + } + }; self.cx .eq_types( - base.ty, + compare_ty, ty, location.to_locations(), ConstraintCategory::TypeAnnotation, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 3a6e1aa498616..12bc4c73e6d90 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -959,8 +959,10 @@ pub enum ProjectionElem { /// The included Symbol is the name of the variant, used for printing MIR. Downcast(Option, VariantIdx), - /// Like an explicit cast from an opaque type to a concrete type, but without - /// requiring an intermediate variable. + /// Like an explicit cast, but without requiring an intermediate variable. + /// Can cast the following things: + /// * from an opaque type to a concrete type + /// * from a pattern type to its inner type OpaqueCast(T), } diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 18cc83c1a774d..265f964d15c71 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -16,6 +16,7 @@ use crate::build::expr::as_place::PlaceBuilder; use crate::build::matches::{Ascription, Binding, Candidate, MatchPair}; use crate::build::Builder; use rustc_hir::RangeEnd; +use rustc_middle::mir::ProjectionElem; use rustc_middle::thir::{self, *}; use rustc_middle::ty; use rustc_middle::ty::layout::IntegerExt; @@ -174,7 +175,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatKind::PatTy { ref value } => { - candidate.match_pairs.push(MatchPair::new(match_pair.place, value, self)); + let place = match_pair.place.project(ProjectionElem::OpaqueCast(value.ty)); + candidate.match_pairs.push(MatchPair::new(place, value, self)); Ok(()) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 7aa133f9187a0..ef13141a8ca83 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); - debug!(?place, ?place_ty,); + debug!(?place, ?place_ty); let source_info = self.source_info(test.span); match test.kind { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7a4b405d26347..236512fafdcbf 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -229,7 +229,7 @@ impl<'tcx> ConstToPat<'tcx> { } // Recursive helper for `to_pat`; invoke that (instead of calling this directly). - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self), level = "debug", ret)] fn recur( &self, cv: mir::ConstantKind<'tcx>, diff --git a/library/core/src/time.rs b/library/core/src/time.rs index ec0cc1c7e7ea9..7803d541be57a 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -35,6 +35,8 @@ const MICROS_PER_SEC: u64 = 1_000_000; #[rustc_layout_scalar_valid_range_end(999_999_999)] struct Nanoseconds(u32); +impl crate::marker::StructuralPartialEq for Nanoseconds {} + impl PartialEq for Nanoseconds { fn eq(&self, other: &Self) -> bool { self.0 as u32 == other.0 as u32 diff --git a/tests/mir-opt/match_pattern_type.rs b/tests/mir-opt/match_pattern_type.rs new file mode 100644 index 0000000000000..baf6f2c13b1a9 --- /dev/null +++ b/tests/mir-opt/match_pattern_type.rs @@ -0,0 +1,11 @@ +use std::time::Duration; + +// EMIT_MIR match_pattern_type.system_time_math.built.after.mir +fn system_time_math() { + match Duration::ZERO { + Duration::ZERO => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/mir-opt/match_pattern_type.system_time_math.built.after.mir b/tests/mir-opt/match_pattern_type.system_time_math.built.after.mir new file mode 100644 index 0000000000000..64eb3a9a328e3 --- /dev/null +++ b/tests/mir-opt/match_pattern_type.system_time_math.built.after.mir @@ -0,0 +1,39 @@ +// MIR for `system_time_math` after built + +fn system_time_math() -> () { + let mut _0: (); // return place in scope 0 at $DIR/match_pattern_type.rs:+0:23: +0:23 + let mut _1: std::time::Duration; // in scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25 + _1 = const _; // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25 + // mir::Constant + // + span: $DIR/match_pattern_type.rs:5:11: 5:25 + // + literal: Const { ty: Duration, val: Unevaluated(Duration::ZERO, [], None) } + FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/match_pattern_type.rs:+1:11: +1:25 + switchInt((_1.0: u64)) -> [0: bb1, otherwise: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+1:5: +1:25 + } + + bb1: { + switchInt((((_1.1: core::time::Nanoseconds).0: u32 is 0..=999999999) as u32)) -> [0: bb2, otherwise: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+1:5: +1:25 + } + + bb2: { + falseEdge -> [real: bb4, imaginary: bb3]; // scope 0 at $DIR/match_pattern_type.rs:+2:9: +2:23 + } + + bb3: { + _0 = const (); // scope 0 at $DIR/match_pattern_type.rs:+3:14: +3:16 + goto -> bb5; // scope 0 at $DIR/match_pattern_type.rs:+3:14: +3:16 + } + + bb4: { + _0 = const (); // scope 0 at $DIR/match_pattern_type.rs:+2:27: +2:29 + goto -> bb5; // scope 0 at $DIR/match_pattern_type.rs:+2:27: +2:29 + } + + bb5: { + StorageDead(_1); // scope 0 at $DIR/match_pattern_type.rs:+5:1: +5:2 + return; // scope 0 at $DIR/match_pattern_type.rs:+5:2: +5:2 + } +} From 7b9502d4fe384c0fcbbf5dab1fa4ff1cbe7d40b1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 26 Jan 2023 09:24:20 +0000 Subject: [PATCH 07/10] Fixup first commit --- compiler/rustc_trait_selection/src/solve/project_goals.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index b583705ac4369..576fc9f3d3422 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -407,6 +407,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { | ty::Float(..) | ty::Array(..) | ty::RawPtr(..) + | ty::Pat(..) | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(..) From 32d11e6941c2a6ff71b2ef25125069da17077734 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 26 Jan 2023 11:27:26 +0000 Subject: [PATCH 08/10] Handle new cast kinds in clippy and cranelift --- compiler/rustc_codegen_cranelift/src/base.rs | 18 +++++++----------- .../clippy_utils/src/qualify_min_const_fn.rs | 2 ++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 89d955e8bf2e1..3b762bffa0a05 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -610,17 +610,13 @@ fn codegen_stmt<'tcx>( } } Rvalue::Cast( - CastKind::Pointer(PointerCast::UnsafeFnPointer), - ref operand, - to_ty, - ) - | Rvalue::Cast( - CastKind::Pointer(PointerCast::MutToConstPointer), - ref operand, - to_ty, - ) - | Rvalue::Cast( - CastKind::Pointer(PointerCast::ArrayToPointer), + CastKind::StripPattern + | CastKind::Patternize + | CastKind::Pointer( + PointerCast::UnsafeFnPointer + | PointerCast::MutToConstPointer + | PointerCast::ArrayToPointer, + ), ref operand, to_ty, ) => { diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index e5d7da682813c..a014ab6f9fe84 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -133,6 +133,8 @@ fn check_rvalue<'tcx>( | Rvalue::Use(operand) | Rvalue::Cast( CastKind::PointerFromExposedAddress + | CastKind::StripPattern + | CastKind::Patternize | CastKind::IntToInt | CastKind::FloatToInt | CastKind::IntToFloat From e236587a639db0ed0159295b10bb430fdca2a2ec Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 27 Jan 2023 17:07:26 +0000 Subject: [PATCH 09/10] fix stage 2 --- compiler/rustc_ast/src/lib.rs | 1 + compiler/rustc_borrowck/src/lib.rs | 1 + compiler/rustc_data_structures/src/lib.rs | 1 + compiler/rustc_hir/src/lib.rs | 1 + compiler/rustc_hir_analysis/src/lib.rs | 1 + compiler/rustc_hir_typeck/src/lib.rs | 1 + compiler/rustc_index/src/lib.rs | 1 + compiler/rustc_infer/src/lib.rs | 1 + compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_macros/src/newtype.rs | 25 +++++++++++++++++------ compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_mir_build/src/lib.rs | 1 + compiler/rustc_mir_dataflow/src/lib.rs | 1 + compiler/rustc_mir_transform/src/lib.rs | 1 + compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_query_system/src/lib.rs | 1 + compiler/rustc_span/src/lib.rs | 1 + compiler/rustc_target/src/lib.rs | 1 + compiler/rustc_trait_selection/src/lib.rs | 1 + compiler/rustc_type_ir/src/lib.rs | 7 ++++--- 20 files changed, 41 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 9c1dfeb1a6142..733f4f20d0611 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -18,6 +18,7 @@ #![feature(negative_impls)] #![feature(slice_internals)] #![feature(stmt_expr_attributes)] +#![feature(structural_match)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b5a9a86c2215a..4262c56f37417 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -8,6 +8,7 @@ #![feature(once_cell)] #![feature(rustc_attrs)] #![feature(stmt_expr_attributes)] +#![feature(structural_match)] #![feature(trusted_step)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 954e84c303b83..adc6e92ab16d9 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -17,6 +17,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(structural_match)] #![feature(type_alias_impl_trait)] #![feature(new_uninit)] #![feature(once_cell)] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 98d967cc0b86e..bb484089a125a 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -9,6 +9,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] +#![feature(structural_match)] #![feature(variant_count)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index da35210023891..39c7331293ff6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -69,6 +69,7 @@ This API is completely unstable and subject to change. #![feature(never_type)] #![feature(once_cell)] #![feature(slice_partition_dedup)] +#![feature(structural_match)] #![feature(try_blocks)] #![feature(is_some_and)] #![feature(type_alias_impl_trait)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index bb487facc23fd..01ba302416333 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -5,6 +5,7 @@ #![feature(min_specialization)] #![feature(control_flow_enum)] #![feature(drain_filter)] +#![feature(structural_match)] #![allow(rustc::potential_query_instability)] #![recursion_limit = "256"] diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index db2c791525645..50032f60363be 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -9,6 +9,7 @@ new_uninit, step_trait, stmt_expr_attributes, + structural_match, test ) )] diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 4c119a443555e..0c7990b6d2701 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -20,6 +20,7 @@ #![feature(if_let_guard)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(structural_match)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index d6be4da03286f..22f7b6b51075b 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -37,6 +37,7 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(rustc_attrs)] +#![feature(structural_match)] #![recursion_limit = "256"] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 89ea89cf502e5..90534c1d68a42 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -93,7 +93,7 @@ impl Parse for Newtype { } impl ::rustc_serialize::Encodable for #name { fn encode(&self, e: &mut E) { - e.emit_u32(self.private); + e.emit_u32(self.as_u32()); } } } @@ -103,11 +103,16 @@ impl Parse for Newtype { if ord { derive_paths.push(parse_quote!(Ord)); - derive_paths.push(parse_quote!(PartialOrd)); } let step = if ord { quote! { + impl ::std::cmp::PartialOrd for #name { + fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> { + self.as_u32().partial_cmp(&other.as_u32()) + } + } + impl ::std::iter::Step for #name { #[inline] fn steps_between(start: &Self, end: &Self) -> Option { @@ -150,7 +155,7 @@ impl Parse for Newtype { #[inline] fn eq(l: &Option, r: &Option) -> bool { if #max_val < u32::MAX { - l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1) + l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1) } else { match (l, r) { (Some(l), Some(r)) => r == l, @@ -170,13 +175,21 @@ impl Parse for Newtype { Ok(Self(quote! { #(#attrs)* - #[derive(Clone, Copy, PartialEq, Eq, Hash, #(#derive_paths),*)] + #[derive(Clone, Copy, Eq, Hash, #(#derive_paths),*)] #[rustc_layout_scalar_valid_range_end(#max)] #[rustc_pass_by_value] #vis struct #name { private: u32, } + impl ::std::cmp::PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + self.as_u32() == other.as_u32() + } + } + + impl ::std::marker::StructuralPartialEq for #name {} + #(#consts)* impl #name { @@ -224,7 +237,7 @@ impl Parse for Newtype { /// Prefer using `from_u32`. #[inline] #vis const unsafe fn from_u32_unchecked(value: u32) -> Self { - Self { private: value } + Self { private: value as _ } } /// Extracts the value of this index as a `usize`. @@ -236,7 +249,7 @@ impl Parse for Newtype { /// Extracts the value of this index as a `u32`. #[inline] #vis const fn as_u32(self) -> u32 { - self.private + self.private as u32 } /// Extracts the value of this index as a `usize`. diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 7e4063c2ffd78..7d4d94f86aeda 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -45,6 +45,7 @@ #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] +#![feature(structural_match)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] #![feature(trusted_step)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a428180a4fa82..c790a5bd5f0b0 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -10,6 +10,7 @@ #![feature(min_specialization)] #![feature(once_cell)] #![feature(try_blocks)] +#![feature(structural_match)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 7f40cfca32fff..e12177a21dbf8 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -3,6 +3,7 @@ #![feature(exact_size_is_empty)] #![feature(min_specialization)] #![feature(once_cell)] +#![feature(structural_match)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![recursion_limit = "256"] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 4a598862d10f8..f08b3d940f0fc 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -7,6 +7,7 @@ #![feature(never_type)] #![feature(once_cell)] #![feature(option_get_or_insert_default)] +#![feature(structural_match)] #![feature(trusted_step)] #![feature(try_blocks)] #![feature(yeet_expr)] diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 6e621b7eb5eb0..45796f2a91574 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -10,6 +10,7 @@ #![feature(let_chains)] #![feature(map_try_insert)] #![feature(min_specialization)] +#![feature(structural_match)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index f47760e9ae6c8..a198a425dbfc8 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -3,6 +3,7 @@ #![feature(hash_raw_entry)] #![feature(min_specialization)] #![feature(extern_types)] +#![feature(structural_match)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 7e61f2f9f73c0..fbcc6b7d24401 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -19,6 +19,7 @@ #![feature(negative_impls)] #![feature(min_specialization)] #![feature(rustc_attrs)] +#![feature(structural_match)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index dc2cc23ffb1e4..415de5a7baf0f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -15,6 +15,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(step_trait)] +#![feature(structural_match)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 6fa0941036390..ff250eb41ca95 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -20,6 +20,7 @@ #![feature(if_let_guard)] #![feature(never_type)] #![feature(result_option_inspect)] +#![feature(structural_match)] #![feature(type_alias_impl_trait)] #![feature(min_specialization)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index f588fe155fe29..37cc7df1809e1 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,6 +1,7 @@ #![feature(fmt_helpers_for_derive)] #![feature(min_specialization)] #![feature(rustc_attrs)] +#![feature(structural_match)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -818,20 +819,20 @@ impl UniverseIndex { /// name the region `'a`, but that region was not nameable from /// `U` because it was not in scope there. pub fn next_universe(self) -> UniverseIndex { - UniverseIndex::from_u32(self.private.checked_add(1).unwrap()) + UniverseIndex::from_u32(self.as_u32().checked_add(1).unwrap()) } /// Returns `true` if `self` can name a name from `other` -- in other words, /// if the set of names in `self` is a superset of those in /// `other` (`self >= other`). pub fn can_name(self, other: UniverseIndex) -> bool { - self.private >= other.private + self.as_u32() >= other.as_u32() } /// Returns `true` if `self` cannot name some names from `other` -- in other /// words, if the set of names in `self` is a strict subset of /// those in `other` (`self < other`). pub fn cannot_name(self, other: UniverseIndex) -> bool { - self.private < other.private + self.as_u32() < other.as_u32() } } From a1c0a3e4c93dde3ae9a352338fcacfe5286ac281 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 27 Jan 2023 18:05:03 +0000 Subject: [PATCH 10/10] x fmt --- compiler/rustc_trait_selection/src/traits/project.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 02aa0f08a3a96..dbdde98f8f38d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1597,7 +1597,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::Str | ty::Array(..) | ty::Pat(..) - | ty::Slice(_) + | ty::Slice(_) | ty::RawPtr(..) | ty::Ref(..) | ty::FnDef(..)