diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c9a8adec31ae8..1275197470fd9 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2513,6 +2513,9 @@ pub enum TyPatKind { /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). Range(Option>, Option>, Spanned), + /// A `!null` pattern for raw pointers. + NotNull, + Or(ThinVec>), /// Placeholder for a pattern that wasn't syntactically well formed in some way. diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 08726ee6b4115..e3bef18565614 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -507,7 +507,7 @@ pub fn walk_ty_pat(vis: &mut T, ty: &mut TyPat) { visit_opt(end, |c| vis.visit_anon_const(c)); } TyPatKind::Or(variants) => visit_thin_vec(variants, |p| vis.visit_ty_pat(p)), - TyPatKind::Err(_) => {} + TyPatKind::NotNull | TyPatKind::Err(_) => {} } vis.visit_span(span); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1f7c97380dc27..b85c345e36bb9 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1043,7 +1043,7 @@ pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Res visit_opt!(visitor, visit_anon_const, end); } TyPatKind::Or(variants) => walk_list!(visitor, visit_ty_pat, variants), - TyPatKind::Err(_) => {} + TyPatKind::NotNull | TyPatKind::Err(_) => {} } V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 58dea472f1d3b..bff1bc01de1f0 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -143,7 +143,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // return inner to be processed in next loop PatKind::Paren(inner) => pattern = inner, - PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), + PatKind::MacCall(_) => { + panic!("{pattern:#?} shouldn't exist here") + } PatKind::Err(guar) => break hir::PatKind::Err(*guar), } }; @@ -464,6 +466,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) }), ), + TyPatKind::NotNull => hir::TyPatKind::NotNull, TyPatKind::Or(variants) => { hir::TyPatKind::Or(self.arena.alloc_from_iter( variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 0990c9b27eb09..0b9b119f42cff 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1218,6 +1218,7 @@ impl<'a> State<'a> { self.print_expr_anon_const(end, &[]); } } + rustc_ast::TyPatKind::NotNull => self.word("!null"), rustc_ast::TyPatKind::Or(variants) => { let mut first = true; for pat in variants { diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 3529e5525fcd2..5d0ee8097455a 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -28,17 +28,23 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P let ty = parser.parse_ty()?; parser.expect_keyword(exp!(Is))?; - let pat = pat_to_ty_pat( - cx, - parser - .parse_pat_no_top_guard( - None, - RecoverComma::No, - RecoverColon::No, - CommaRecoveryMode::EitherTupleOrPipe, - )? - .into_inner(), - ); + let start = parser.token.span; + let pat = if parser.eat(exp!(Bang)) { + parser.expect_keyword(exp!(Null))?; + ty_pat(TyPatKind::NotNull, start.to(parser.token.span)) + } else { + pat_to_ty_pat( + cx, + parser + .parse_pat_no_top_guard( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + )? + .into_inner(), + ) + }; if parser.token != token::Eof { parser.unexpected()?; diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index f8bbb21492015..328a7ec94ce38 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -148,6 +148,11 @@ pub(crate) fn coerce_unsized_into<'tcx>( dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout())); }; match (&src_ty.kind(), &dst_ty.kind()) { + (ty::Pat(a, _), ty::Pat(b, _)) => { + let src = src.cast_pat_ty_to_base(fx.layout_of(*a)); + let dst = dst.place_transmute_type(fx, *b); + return coerce_unsized_into(fx, src, dst); + } (&ty::Ref(..), &ty::Ref(..)) | (&ty::Ref(..), &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => coerce_ptr(), diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index cbfb215a892a4..4c7ea1d88f3e8 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -379,6 +379,14 @@ impl<'tcx> CValue<'tcx> { assert_eq!(self.layout().backend_repr, layout.backend_repr); CValue(self.0, layout) } + + pub(crate) fn cast_pat_ty_to_base(self, layout: TyAndLayout<'tcx>) -> Self { + let ty::Pat(base, _) = *self.layout().ty.kind() else { + panic!("not a pattern type: {:#?}", self.layout()) + }; + assert_eq!(layout.ty, base); + CValue(self.0, layout) + } } /// A place where you can write a value to or read a value from diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 7f3e486ca310d..c7578c58add89 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -459,7 +459,18 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), }, ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), - _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), + ty::Pat(base, _) => return type_di_node(cx, base), + // FIXME(unsafe_binders): impl debug info + ty::UnsafeBinder(_) => unimplemented!(), + ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Infer(_) + | ty::Placeholder(_) + | ty::CoroutineWitness(..) + | ty::Error(_) => { + 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 f7863fe4ae264..6a4187463651a 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -230,6 +230,7 @@ pub(crate) fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> (Bx::Value, Bx::Value) { debug!("unsize_ptr: {:?} => {:?}", src_ty, dst_ty); match (src_ty.kind(), dst_ty.kind()) { + (&ty::Pat(a, _), &ty::Pat(b, _)) => unsize_ptr(bx, src, a, b, old_info), (&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _)) | (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => { assert_eq!(bx.cx().type_is_sized(a), old_info.is_none()); diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 789baea073463..ba9222cb1173d 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -86,6 +86,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (_, field) = layout.non_1zst_field(self).unwrap(); self.unfold_transparent(field, may_unfold) } + ty::Pat(base, _) => self.layout_of(*base).expect( + "if the layout of a pattern type could be computed, so can the layout of its base", + ), // Not a transparent type, no further unfolding. _ => layout, } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 643a5805019ff..2e90712e2df26 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -473,6 +473,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); match (src.layout.ty.kind(), cast_ty.ty.kind()) { + (&ty::Pat(_, s_pat), &ty::Pat(cast_ty, c_pat)) if s_pat == c_pat => { + let src = self.project_field(src, 0)?; + let dest = self.project_field(dest, 0)?; + let cast_ty = self.layout_of(cast_ty)?; + self.unsize_into(&src, cast_ty, &dest) + } (&ty::Ref(_, s, _), &ty::Ref(_, c, _) | &ty::RawPtr(c, _)) | (&ty::RawPtr(s, _), &ty::RawPtr(c, _)) => self.unsize_into_ptr(src, dest, s, c), (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 7d76d925ef23e..0998c4151187a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1245,9 +1245,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // When you extend this match, make sure to also add tests to // tests/ui/type/pattern_types/validity.rs(( match **pat { - // Range patterns are precisely reflected into `valid_range` and thus + // Range and non-null patterns are precisely reflected into `valid_range` and thus // handled fully by `visit_scalar` (called below). ty::PatternKind::Range { .. } => {}, + ty::PatternKind::NotNull => {}, // FIXME(pattern_types): check that the value is covered by one of the variants. // For now, we rely on layout computation setting the scalar's `valid_range` to diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 3647c109a6ed4..1299ff184f93c 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -156,7 +156,12 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { ); // ... that contains a `NonNull`... (gladly, only a single field here) assert_eq!(nonnull_ptr.layout().fields.count(), 1); - let raw_ptr = self.ecx().project_field(&nonnull_ptr, 0)?; // the actual raw ptr + let pat_ty = self.ecx().project_field(&nonnull_ptr, 0)?; // `*mut T is !null` + let base = match *pat_ty.layout().ty.kind() { + ty::Pat(base, _) => self.ecx().layout_of(base)?, + _ => unreachable!(), + }; + let raw_ptr = pat_ty.transmute(base, self.ecx())?; // The actual raw pointer // ... whose only field finally is a raw ptr we can dereference. self.visit_box(ty, &raw_ptr)?; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 433d5f9882937..d014a07d4fcb0 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1824,6 +1824,9 @@ pub enum TyPatKind<'hir> { /// A range pattern (e.g., `1..=2` or `1..2`). Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>), + /// A pattern that excludes null pointers + NotNull, + /// A list of patterns where only one needs to be satisfied Or(&'hir [TyPat<'hir>]), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bebac3a4b7820..d507eeaf8697d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -725,7 +725,7 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) try_visit!(visitor.visit_const_arg_unambig(upper_bound)); } TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns), - TyPatKind::Err(_) => (), + TyPatKind::NotNull | TyPatKind::Err(_) => (), } V::Result::output() } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a3a0e276f74cd..8e39a50399bee 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -99,6 +99,8 @@ hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applica hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout +hir_analysis_coerce_same_pat_kind = only pattern types with the same pattern can be coerced between each other + hir_analysis_coerce_unsized_field_validity = for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}` .label = `{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b92d1d7104f0a..0f891d76a6d43 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -249,6 +249,18 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent) // even if they do not carry that attribute. match (source.kind(), target.kind()) { + (&ty::Pat(_, pat_a), &ty::Pat(_, pat_b)) => { + if pat_a != pat_b { + return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind { + span, + trait_name, + pat_a: pat_a.to_string(), + pat_b: pat_b.to_string(), + })); + } + Ok(()) + } + (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b)) if r_a == *r_b && mutbl_a == *mutbl_b => { @@ -414,6 +426,18 @@ pub(crate) fn coerce_unsized_info<'tcx>( (mt_a.ty, mt_b.ty, unsize_trait, None, span) }; let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) { + (&ty::Pat(ty_a, pat_a), &ty::Pat(ty_b, pat_b)) => { + if pat_a != pat_b { + return Err(tcx.dcx().emit_err(errors::CoerceSamePatKind { + span, + trait_name, + pat_a: pat_a.to_string(), + pat_b: pat_b.to_string(), + })); + } + (ty_a, ty_b, coerce_unsized_trait, None, span) + } + (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; @@ -713,13 +737,16 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err let impl_span = tcx.def_span(checker.impl_def_id); let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty(); - let is_permitted_primitive = match *self_ty.kind() { - ty::Adt(def, _) => def.is_box(), - ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true, - _ => false, - }; + fn is_permitted_primitive(self_ty: Ty<'_>) -> bool { + match *self_ty.kind() { + ty::Adt(def, _) => def.is_box(), + ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true, + ty::Pat(base, _) => is_permitted_primitive(base), + _ => false, + } + } - if is_permitted_primitive + if is_permitted_primitive(self_ty) && let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty)) && layout.layout.is_pointer_like(&tcx.data_layout) { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c75fef9f716d6..6660ed4181084 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -206,12 +206,8 @@ pub(crate) fn orphan_check_impl( (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) } - ty::Pat(..) => ( - LocalImpl::Disallow { problematic_kind: "pattern type" }, - NonlocalImpl::DisallowOther, - ), - ty::Bool + | ty::Pat(..) | ty::Char | ty::Int(..) | ty::Uint(..) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 152714b340731..641b340d7a3b0 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1280,6 +1280,16 @@ pub(crate) struct CoerceUnsizedNonStruct { pub trait_name: &'static str, } +#[derive(Diagnostic)] +#[diag(hir_analysis_coerce_same_pat_kind)] +pub(crate) struct CoerceSamePatKind { + #[primary_span] + pub span: Span, + pub trait_name: &'static str, + pub pat_a: String, + pub pat_b: String, +} + #[derive(Diagnostic)] #[diag(hir_analysis_coerce_unsized_may, code = E0377)] pub(crate) struct CoerceSameStruct { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2a37a8bdbd47d..0a4cc04a74ec9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2651,6 +2651,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .span_delayed_bug(ty_span, "invalid base type for range pattern")), } } + hir::TyPatKind::NotNull => Ok(ty::PatternKind::NotNull), hir::TyPatKind::Or(patterns) => { self.tcx() .mk_patterns_from_iter(patterns.iter().map(|pat| { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 960ec7f66ab15..09da0e2ec6511 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -340,6 +340,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_const(current, start, variance); self.add_constraints_from_const(current, end, variance); } + ty::PatternKind::NotNull => {} ty::PatternKind::Or(patterns) => { for pat in patterns { self.add_constraints_from_pat(current, variance, pat) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b23b3125c59a3..ed2529362d098 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1869,6 +1869,10 @@ impl<'a> State<'a> { self.word("..="); self.print_const_arg(end); } + TyPatKind::NotNull => { + self.word_space("not"); + self.word("null"); + } TyPatKind::Or(patterns) => { self.popen(); let mut first = true; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fec23354c9122..e276354296154 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -910,6 +910,7 @@ fn pat_ty_is_known_nonnull<'tcx>( // to ensure we aren't wrapping over zero. start > 0 && end >= start } + ty::PatternKind::NotNull => true, ty::PatternKind::Or(patterns) => { patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) } @@ -1071,7 +1072,9 @@ fn get_nullable_type_from_pat<'tcx>( pat: ty::Pattern<'tcx>, ) -> Option> { match *pat { - ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, base), + ty::PatternKind::NotNull | ty::PatternKind::Range { .. } => { + get_nullable_type(tcx, typing_env, base) + } ty::PatternKind::Or(patterns) => { let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?; for &pat in &patterns[1..] { diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index aa2ee756bc502..2025802a217ff 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -159,6 +159,9 @@ pub enum SelectionCandidate<'tcx> { /// types generated for a fn pointer type (e.g., `fn(int) -> int`) FnPointerCandidate, + /// Builtin impl of the `PointerLike` trait. + PointerLikeCandidate, + TraitAliasCandidate, /// Matching `dyn Trait` with a supertrait of `Trait`. The index is the diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index c2ae6b06192a9..e7005a5b9666e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -822,11 +822,21 @@ where | ty::FnDef(..) | ty::CoroutineWitness(..) | ty::Foreign(..) - | ty::Pat(_, _) | ty::Dynamic(_, _, ty::Dyn) => { bug!("TyAndLayout::field({:?}): not applicable", this) } + // May contain wide pointers + ty::Pat(base, pat) => match *pat { + ty::PatternKind::NotNull => { + assert_eq!(i, 0); + TyMaybeWithLayout::Ty(base) + } + ty::PatternKind::Range { .. } | ty::PatternKind::Or(_) => { + bug!("TyAndLayout::field({this:?}): only applicable to !null patterns") + } + }, + ty::UnsafeBinder(bound_ty) => { let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into()); field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i) diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 5af9b17dd7777..335e5c0647435 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -30,6 +30,7 @@ impl<'tcx> Flags for Pattern<'tcx> { } flags } + ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(), } } @@ -45,6 +46,7 @@ impl<'tcx> Flags for Pattern<'tcx> { } idx } + ty::PatternKind::NotNull => rustc_type_ir::INNERMOST, } } } @@ -91,6 +93,7 @@ impl<'tcx> IrPrint> for TyCtxt<'tcx> { write!(f, "..={end}") } + PatternKind::NotNull => write!(f, "!null"), PatternKind::Or(patterns) => { write!(f, "(")?; let mut first = true; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index dc1d60f3d43c1..a4d7423818ea2 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -59,6 +59,7 @@ impl<'tcx> Relate> for ty::Pattern<'tcx> { let end = relation.relate(end_a, end_b)?; Ok(tcx.mk_pat(ty::PatternKind::Range { start, end })) } + (ty::PatternKind::NotNull, ty::PatternKind::NotNull) => Ok(a), (&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => { if a.len() != b.len() { return Err(TypeError::Mismatch); @@ -67,7 +68,10 @@ impl<'tcx> Relate> for ty::Pattern<'tcx> { let patterns = tcx.mk_patterns_from_iter(v)?; Ok(tcx.mk_pat(ty::PatternKind::Or(patterns))) } - (ty::PatternKind::Range { .. } | ty::PatternKind::Or(_), _) => Err(TypeError::Mismatch), + ( + ty::PatternKind::NotNull | ty::PatternKind::Range { .. } | ty::PatternKind::Or(_), + _, + ) => Err(TypeError::Mismatch), } } } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index 5c344a806880c..c187503f2f2d8 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::span_bug; -use rustc_middle::ty::{Ty, TyCtxt}; +use rustc_middle::ty::{PatternKind, Ty, TyCtxt}; use crate::patch::MirPatch; @@ -17,13 +17,14 @@ fn build_ptr_tys<'tcx>( pointee: Ty<'tcx>, unique_did: DefId, nonnull_did: DefId, -) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) { +) -> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) { let args = tcx.mk_args(&[pointee.into()]); let unique_ty = tcx.type_of(unique_did).instantiate(tcx, args); let nonnull_ty = tcx.type_of(nonnull_did).instantiate(tcx, args); let ptr_ty = Ty::new_imm_ptr(tcx, pointee); + let pat_ty = Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull)); - (unique_ty, nonnull_ty, ptr_ty) + (unique_ty, nonnull_ty, pat_ty, ptr_ty) } /// Constructs the projection needed to access a Box's pointer @@ -63,7 +64,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> { { let source_info = self.local_decls[place.local].source_info; - let (unique_ty, nonnull_ty, ptr_ty) = + let (unique_ty, nonnull_ty, _pat_ty, ptr_ty) = build_ptr_tys(tcx, boxed_ty, self.unique_did, self.nonnull_did); let ptr_local = self.patch.new_temp(ptr_ty, source_info.span); @@ -130,10 +131,11 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { let new_projections = new_projections.get_or_insert_with(|| base.projection.to_vec()); - let (unique_ty, nonnull_ty, ptr_ty) = + let (unique_ty, nonnull_ty, pat_ty, ptr_ty) = build_ptr_tys(tcx, boxed_ty, unique_did, nonnull_did); new_projections.extend_from_slice(&build_projection(unique_ty, nonnull_ty)); + new_projections.push(PlaceElem::Field(FieldIdx::ZERO, pat_ty)); // While we can't project into `NonNull<_>` in a basic block // due to MCP#807, this is debug info where it's fine. new_projections.push(PlaceElem::Field(FieldIdx::ZERO, ptr_ty)); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index c8aa7588d03ab..eb9570e53b011 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -707,6 +707,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; check_equal(self, location, *f_ty); } + // Debug info is allowed to project into pattern types + ty::Pat(base, _) => check_equal(self, location, *base), ty::Adt(adt_def, args) => { // see if self.tcx.is_lang_item(adt_def.did(), LangItem::DynMetadata) { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1ee977a5457e2..a8b583b7e71b5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1067,6 +1067,7 @@ fn find_tails_for_unsizing<'tcx>( debug_assert!(!target_ty.has_param(), "{target_ty} should be fully monomorphic"); match (source_ty.kind(), target_ty.kind()) { + (&ty::Pat(source, _), &ty::Pat(target, _)) => find_tails_for_unsizing(tcx, source, target), ( &ty::Ref(_, source_pointee, _), &ty::Ref(_, target_pointee, _) | &ty::RawPtr(target_pointee, _), diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index b91548196a305..1d7ff549f1b09 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -139,6 +139,7 @@ pub enum TokenType { SymNomem, SymNoreturn, SymNostack, + SymNull, SymOptions, SymOut, SymPreservesFlags, @@ -273,6 +274,7 @@ impl TokenType { SymNomem, SymNoreturn, SymNostack, + SymNull, SymOptions, SymOut, SymPreservesFlags, @@ -348,6 +350,7 @@ impl TokenType { TokenType::SymNomem => Some(sym::nomem), TokenType::SymNoreturn => Some(sym::noreturn), TokenType::SymNostack => Some(sym::nostack), + TokenType::SymNull => Some(sym::null), TokenType::SymOptions => Some(sym::options), TokenType::SymOut => Some(sym::out), TokenType::SymPreservesFlags => Some(sym::preserves_flags), @@ -562,6 +565,7 @@ macro_rules! exp { (Nomem) => { exp!(@sym, nomem, SymNomem) }; (Noreturn) => { exp!(@sym, noreturn, SymNoreturn) }; (Nostack) => { exp!(@sym, nostack, SymNostack) }; + (Null) => { exp!(@sym, null, SymNull) }; (Options) => { exp!(@sym, options, SymOptions) }; (Out) => { exp!(@sym, out, SymOut) }; (PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2a4be5fc3b16e..e5793b16de2ca 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -986,7 +986,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r self.visit_ty_pat(pat) } } - TyPatKind::Err(_) => {} + TyPatKind::NotNull | TyPatKind::Err(_) => {} } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index b0c9dba78a659..213c15258359f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -412,6 +412,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { end: Some(end.stable(tables)), include_end: true, }, + ty::PatternKind::NotNull => todo!(), ty::PatternKind::Or(_) => todo!(), } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4e842a8f93a8f..8ab1e240635ba 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1487,6 +1487,7 @@ symbols! { not, notable_trait, note, + null, object_safe_for_dispatch, of, off, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 49a5e20d7cf8b..fe1055b80db7f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -267,6 +267,9 @@ impl<'tcx> SymbolMangler<'tcx> { Ty::new_array_with_const_len(self.tcx, self.tcx.types.unit, ct).print(self)?; } } + ty::PatternKind::NotNull => { + self.tcx.types.unit.print(self)?; + } ty::PatternKind::Or(patterns) => { for pat in patterns { self.print_pat(pat)?; 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 97ecf9702e620..da50f7a641b50 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -138,6 +138,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut candidates, ); } + Some(LangItem::PointerLike) => { + self.assemble_pointer_like_candidates(obligation, &mut candidates); + } Some(LangItem::AsyncFn | LangItem::AsyncFnMut | LangItem::AsyncFnOnce) => { self.assemble_async_closure_candidates(obligation, &mut candidates); } @@ -501,6 +504,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn assemble_pointer_like_candidates( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + match obligation.self_ty().skip_binder().kind() { + ty::Pat(..) => candidates.vec.push(PointerLikeCandidate), + _ => {} + } + } + fn assemble_async_fn_kind_helper_candidates( &mut self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index c9169127e0b90..25bb240489946 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -117,6 +117,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, data) } + PointerLikeCandidate => { + let data = self.confirm_pointer_like_candidate(obligation); + ImplSource::Builtin(BuiltinImplSource::Misc, data) + } + TraitAliasCandidate => { let data = self.confirm_trait_alias_candidate(obligation); ImplSource::Builtin(BuiltinImplSource::Misc, data) @@ -665,6 +670,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(nested) } + fn confirm_pointer_like_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + ) -> PredicateObligations<'tcx> { + debug!(?obligation, "confirm_fn_pointer_candidate"); + let placeholder_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); + let self_ty = self.infcx.shallow_resolve(placeholder_predicate.self_ty()); + let ty::Pat(base, _) = *self_ty.kind() else { bug!() }; + let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived); + + self.collect_predicates_for_types( + obligation.param_env, + cause, + obligation.recursion_depth + 1, + placeholder_predicate.def_id(), + vec![base], + ) + } + fn confirm_trait_alias_candidate( &mut self, obligation: &PolyTraitObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3a2f9e8ca179f..d2bc2ff201109 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1983,6 +1983,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitUpcastingUnsizeCandidate(_) | BuiltinObjectCandidate | BuiltinUnsizeCandidate + | PointerLikeCandidate | BikeshedGuaranteedNoDropCandidate => false, // Non-global param candidates have already been handled, global // where-bounds get ignored. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 3018dad8e0916..0c39d180064a9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -696,6 +696,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { check(start); check(end); } + ty::PatternKind::NotNull => {} ty::PatternKind::Or(patterns) => { for pat in patterns { self.add_wf_preds_for_pat_ty(base_ty, pat) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 9774263e4c951..4cec941b4afec 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -213,9 +213,7 @@ fn layout_of_uncached<'tcx>( let mut layout = LayoutData::clone(&layout.0); match *pat { ty::PatternKind::Range { start, end } => { - if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = - &mut layout.backend_repr - { + if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr { scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; @@ -263,6 +261,29 @@ fn layout_of_uncached<'tcx>( bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") } } + ty::PatternKind::NotNull => { + if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = + &mut layout.backend_repr + { + scalar.valid_range_mut().start = 1; + let niche = Niche { + offset: Size::ZERO, + value: scalar.primitive(), + valid_range: scalar.valid_range(cx), + }; + + layout.largest_niche = Some(niche); + layout.fields = FieldsShape::Arbitrary { + offsets: [Size::ZERO].into_iter().collect(), + memory_index: [0].into_iter().collect(), + } + } else { + bug!( + "pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}" + ) + } + } + ty::PatternKind::Or(variants) => match *variants[0] { ty::PatternKind::Range { .. } => { if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr { @@ -279,7 +300,7 @@ fn layout_of_uncached<'tcx>( .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?, )), - ty::PatternKind::Or(_) => { + ty::PatternKind::NotNull | ty::PatternKind::Or(_) => { unreachable!("mixed or patterns are not allowed") } }) @@ -344,6 +365,7 @@ fn layout_of_uncached<'tcx>( ) } } + ty::PatternKind::NotNull => bug!("or patterns can't contain `!null` patterns"), ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"), }, } diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs index 7e56565917c67..8237254f8c44d 100644 --- a/compiler/rustc_type_ir/src/pattern.rs +++ b/compiler/rustc_type_ir/src/pattern.rs @@ -14,4 +14,5 @@ use crate::Interner; pub enum PatternKind { Range { start: I::Const, end: I::Const }, Or(I::PatList), + NotNull, } diff --git a/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs index 737550eb73e99..d1d707b896f0f 100644 --- a/compiler/rustc_type_ir/src/walk.rs +++ b/compiler/rustc_type_ir/src/walk.rs @@ -178,5 +178,6 @@ fn push_ty_pat(stack: &mut TypeWalkerStack, pat: I::Pat) { push_ty_pat::(stack, pat) } } + ty::PatternKind::NotNull => {} } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f2a5c40bada0b..7f0e8d9412c76 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -168,6 +168,8 @@ #![feature(never_type)] #![feature(no_core)] #![feature(optimize_attribute)] +#![feature(pattern_type_macro)] +#![feature(pattern_types)] #![feature(prelude_import)] #![feature(repr_simd)] #![feature(rustc_allow_const_fn_unstable)] diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs index 47ff4254e533b..4d23d3d28b1e4 100644 --- a/library/core/src/num/niche_types.rs +++ b/library/core/src/num/niche_types.rs @@ -5,60 +5,48 @@ )] use crate::cmp::Ordering; -use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::marker::StructuralPartialEq; +use crate::{fmt, pattern_type}; macro_rules! define_valid_range_type { ($( $(#[$m:meta])* - $vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal); + $vis:vis struct $name:ident($int:ident is $pat:pat); )+) => {$( - #[derive(Clone, Copy, Eq)] + #[derive(Clone, Copy)] #[repr(transparent)] - #[rustc_layout_scalar_valid_range_start($low)] - #[rustc_layout_scalar_valid_range_end($high)] $(#[$m])* - $vis struct $name($int); - - const _: () = { - // With the `valid_range` attributes, it's always specified as unsigned - assert!(<$uint>::MIN == 0); - let ulow: $uint = $low; - let uhigh: $uint = $high; - assert!(ulow <= uhigh); - - assert!(size_of::<$int>() == size_of::<$uint>()); - }; - + $vis struct $name(pattern_type!($int is $pat)); impl $name { #[inline] pub const fn new(val: $int) -> Option { - if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) { - // SAFETY: just checked the inclusive range - Some(unsafe { $name(val) }) + #[allow(non_contiguous_range_endpoints)] + if let $pat = val { + // SAFETY: just checked that the value matches the pattern + Some(unsafe { $name(crate::mem::transmute(val)) }) } else { None } } /// Constructs an instance of this type from the underlying integer - /// primitive without checking whether its zero. + /// primitive without checking whether its valid. /// /// # Safety - /// Immediate language UB if `val == 0`, as it violates the validity + /// Immediate language UB if `val` is not in the range of the pattern type, + /// as it violates the validity /// invariant of this type. #[inline] pub const unsafe fn new_unchecked(val: $int) -> Self { - // SAFETY: Caller promised that `val` is non-zero. - unsafe { $name(val) } + // SAFETY: Caller promised that `val` is in the valid range. + unsafe { $name(crate::mem::transmute(val)) } } #[inline] pub const fn as_inner(self) -> $int { - // SAFETY: This is a transparent wrapper, so unwrapping it is sound - // (Not using `.0` due to MCP#807.) - unsafe { crate::mem::transmute(self) } + // SAFETY: pattern types are always legal values of their base type + unsafe { crate::mem::transmute(self.0) } } } @@ -67,6 +55,8 @@ macro_rules! define_valid_range_type { // by . impl StructuralPartialEq for $name {} + impl Eq for $name {} + impl PartialEq for $name { #[inline] fn eq(&self, other: &Self) -> bool { @@ -104,7 +94,7 @@ macro_rules! define_valid_range_type { } define_valid_range_type! { - pub struct Nanoseconds(u32 as u32 in 0..=999_999_999); + pub struct Nanoseconds(u32 is 0..=999_999_999); } impl Nanoseconds { @@ -119,45 +109,30 @@ impl Default for Nanoseconds { } } -define_valid_range_type! { - pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff); - pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff); - pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); - - pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff); - pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff); - pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff); - pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff); - pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff); -} - -#[cfg(target_pointer_width = "16")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff); -} -#[cfg(target_pointer_width = "32")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff); -} -#[cfg(target_pointer_width = "64")] -define_valid_range_type! { - pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff); - pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff); - pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff); -} +const HALF_USIZE: usize = usize::MAX >> 1; define_valid_range_type! { - pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe); - pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe); - - pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe); - pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe); + pub struct NonZeroU8Inner(u8 is 1..); + pub struct NonZeroU16Inner(u16 is 1..); + pub struct NonZeroU32Inner(u32 is 1..); + pub struct NonZeroU64Inner(u64 is 1..); + pub struct NonZeroU128Inner(u128 is 1..); + + pub struct NonZeroI8Inner(i8 is ..0 | 1..); + pub struct NonZeroI16Inner(i16 is ..0 | 1..); + pub struct NonZeroI32Inner(i32 is ..0 | 1..); + pub struct NonZeroI64Inner(i64 is ..0 | 1..); + pub struct NonZeroI128Inner(i128 is ..0 | 1..); + + pub struct UsizeNoHighBit(usize is 0..=HALF_USIZE); + pub struct NonZeroUsizeInner(usize is 1..); + pub struct NonZeroIsizeInner(isize is ..0 | 1..); + + pub struct U32NotAllOnes(u32 is 0..u32::MAX); + pub struct I32NotAllOnes(i32 is ..-1 | 0..); + + pub struct U64NotAllOnes(u64 is 0..u64::MAX); + pub struct I64NotAllOnes(i64 is ..-1 | 0..); } pub trait NotAllOnesHelper { diff --git a/library/core/src/pat.rs b/library/core/src/pat.rs index 91d015b1bc53f..233cca7f17e39 100644 --- a/library/core/src/pat.rs +++ b/library/core/src/pat.rs @@ -1,5 +1,8 @@ //! Helper module for exporting the `pattern_type` macro +use crate::marker::{Freeze, Unsize}; +use crate::ops::{CoerceUnsized, DispatchFromDyn}; + /// Creates a pattern type. /// ```ignore (cannot test this from within core yet) /// type Positive = std::pat::pattern_type!(i32 is 1..); @@ -74,3 +77,16 @@ impl const RangePattern for char { } } } + +impl CoerceUnsized for pattern_type!(*const T is !null) where + T: Unsize +{ +} + +impl, U> DispatchFromDyn for pattern_type!(T is !null) {} + +impl Unpin for pattern_type!(*const T is !null) {} + +unsafe impl Freeze for pattern_type!(*const T is !null) {} + +unsafe impl Freeze for pattern_type!(*mut T is !null) {} diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 91b8d1bf9a707..854fa4cd0a684 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1,6 +1,6 @@ use crate::cmp::Ordering; use crate::marker::Unsize; -use crate::mem::{MaybeUninit, SizedTypeProperties}; +use crate::mem::{MaybeUninit, SizedTypeProperties, transmute}; use crate::num::NonZero; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::PinCoerceUnsized; @@ -64,13 +64,10 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; /// [null pointer optimization]: crate::option#representation #[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] -#[rustc_layout_scalar_valid_range_start(1)] #[rustc_nonnull_optimization_guaranteed] #[rustc_diagnostic_item = "NonNull"] pub struct NonNull { - // Remember to use `.as_ptr()` instead of `.pointer`, as field projecting to - // this is banned by . - pointer: *const T, + pointer: crate::pattern_type!(*const T is !null), } /// `NonNull` pointers are not `Send` because the data they reference may be aliased. @@ -93,9 +90,9 @@ impl NonNull { #[must_use] #[inline] pub const fn without_provenance(addr: NonZero) -> Self { - let pointer = crate::ptr::without_provenance(addr.get()); + let pointer: *const T = crate::ptr::without_provenance(addr.get()); // SAFETY: we know `addr` is non-zero. - unsafe { NonNull { pointer } } + unsafe { NonNull { pointer: transmute(pointer) } } } /// Creates a new `NonNull` that is dangling, but well-aligned. @@ -225,7 +222,7 @@ impl NonNull { "NonNull::new_unchecked requires that the pointer is non-null", (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() ); - NonNull { pointer: ptr as _ } + NonNull { pointer: transmute(ptr) } } } @@ -268,7 +265,7 @@ impl NonNull { #[inline] pub const fn from_ref(r: &T) -> Self { // SAFETY: A reference cannot be null. - unsafe { NonNull { pointer: r as *const T } } + unsafe { NonNull { pointer: transmute(r as *const T) } } } /// Converts a mutable reference to a `NonNull` pointer. @@ -277,7 +274,7 @@ impl NonNull { #[inline] pub const fn from_mut(r: &mut T) -> Self { // SAFETY: A mutable reference cannot be null. - unsafe { NonNull { pointer: r as *mut T } } + unsafe { NonNull { pointer: transmute(r as *mut T) } } } /// Performs the same functionality as [`std::ptr::from_raw_parts`], except that a @@ -488,7 +485,7 @@ impl NonNull { #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null - unsafe { NonNull { pointer: self.as_ptr() as *mut U } } + unsafe { NonNull { pointer: transmute(self.as_ptr() as *mut U) } } } /// Try to cast to a pointer of another type by checking aligment. @@ -567,7 +564,7 @@ impl NonNull { // Additionally safety contract of `offset` guarantees that the resulting pointer is // pointing to an allocation, there can't be an allocation at null, thus it's safe to // construct `NonNull`. - unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } } + unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } } } /// Calculates the offset from a pointer in bytes. @@ -591,7 +588,7 @@ impl NonNull { // Additionally safety contract of `offset` guarantees that the resulting pointer is // pointing to an allocation, there can't be an allocation at null, thus it's safe to // construct `NonNull`. - unsafe { NonNull { pointer: self.as_ptr().byte_offset(count) } } + unsafe { NonNull { pointer: transmute(self.as_ptr().byte_offset(count)) } } } /// Adds an offset to a pointer (convenience for `.offset(count as isize)`). @@ -643,7 +640,7 @@ impl NonNull { // Additionally safety contract of `offset` guarantees that the resulting pointer is // pointing to an allocation, there can't be an allocation at null, thus it's safe to // construct `NonNull`. - unsafe { NonNull { pointer: intrinsics::offset(self.as_ptr(), count) } } + unsafe { NonNull { pointer: transmute(intrinsics::offset(self.as_ptr(), count)) } } } /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`). @@ -667,7 +664,7 @@ impl NonNull { // Additionally safety contract of `add` guarantees that the resulting pointer is pointing // to an allocation, there can't be an allocation at null, thus it's safe to construct // `NonNull`. - unsafe { NonNull { pointer: self.as_ptr().byte_add(count) } } + unsafe { NonNull { pointer: transmute(self.as_ptr().byte_add(count)) } } } /// Subtracts an offset from a pointer (convenience for @@ -749,7 +746,7 @@ impl NonNull { // Additionally safety contract of `sub` guarantees that the resulting pointer is pointing // to an allocation, there can't be an allocation at null, thus it's safe to construct // `NonNull`. - unsafe { NonNull { pointer: self.as_ptr().byte_sub(count) } } + unsafe { NonNull { pointer: transmute(self.as_ptr().byte_sub(count)) } } } /// Calculates the distance between two pointers within the same allocation. The returned value is in diff --git a/library/std/src/os/unix/io/tests.rs b/library/std/src/os/unix/io/tests.rs index fc147730578ac..ce5e7aac5a99d 100644 --- a/library/std/src/os/unix/io/tests.rs +++ b/library/std/src/os/unix/io/tests.rs @@ -2,8 +2,7 @@ use crate::os::unix::io::RawFd; #[test] fn test_raw_fd_layout() { - // `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start` - // and `rustc_layout_scalar_valid_range_end`, with values that depend on + // `OwnedFd` and `BorrowedFd` use pattern types, with ranges that depend on // the bit width of `RawFd`. If this ever changes, those values will need // to be updated. assert_eq!(size_of::(), 4); diff --git a/library/std/src/os/wasi/io/tests.rs b/library/std/src/os/wasi/io/tests.rs index c5c6a19a6c885..d18b9fe10cab0 100644 --- a/library/std/src/os/wasi/io/tests.rs +++ b/library/std/src/os/wasi/io/tests.rs @@ -2,8 +2,7 @@ use crate::os::wasi::io::RawFd; #[test] fn test_raw_fd_layout() { - // `OwnedFd` and `BorrowedFd` use `rustc_layout_scalar_valid_range_start` - // and `rustc_layout_scalar_valid_range_end`, with values that depend on + // `OwnedFd` and `BorrowedFd` use pattern types with ranges that depend on // the bit width of `RawFd`. If this ever changes, those values will need // to be updated. assert_eq!(size_of::(), 4); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 26323af312288..81b4946595029 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -242,6 +242,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> loop { ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); return match *ty.kind() { + ty::Pat(base, _) => { + ty = base; + continue; + }, ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ReducedTy::TypeErasure { raw_ptr_only: false } }, diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index c37231d093129..49b818e0760f2 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1122,7 +1122,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty_pat(variant); } }, - TyPatKind::Err(_) => {}, + TyPatKind::NotNull | TyPatKind::Err(_) => {}, } } diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr index a0b7cc7a521d4..c3b614dae5260 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_callee_ret.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> tests/fail/validity/cast_fn_ptr_invalid_callee_ret.rs:LL:CC | LL | f(); - | ^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 + | ^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr index 6af0e72b9c43f..06ed64ac76f1f 100644 --- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr +++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error: Undefined Behavior: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs:LL:CC | LL | Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/pass/pattern-types.rs b/src/tools/miri/tests/pass/pattern-types.rs new file mode 100644 index 0000000000000..b0c35cd1ff4b3 --- /dev/null +++ b/src/tools/miri/tests/pass/pattern-types.rs @@ -0,0 +1,17 @@ +#![feature(pattern_types, pattern_type_macro)] +#![allow(dead_code)] + +use std::mem::transmute; + +pub struct NonNull { + pointer: std::pat::pattern_type!(*const T is !null), +} + +trait Trait {} +impl Trait for () {} + +fn main() { + unsafe { + let _: NonNull = NonNull { pointer: transmute(&mut () as *mut dyn Trait) }; + } +} diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 7ec1032dcb421..6b98a67506a80 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1106,7 +1106,7 @@ impl Rewrite for ast::TyPat { } Ok(s) } - ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), + ast::TyPatKind::NotNull | ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), } } } diff --git a/tests/codegen/loads.rs b/tests/codegen/loads.rs index 88d67642b7250..e19af7a3c2bc1 100644 --- a/tests/codegen/loads.rs +++ b/tests/codegen/loads.rs @@ -58,7 +58,7 @@ pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 { // CHECK-LABEL: @load_box #[no_mangle] pub fn load_box<'a>(x: Box>) -> Box { - // CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}} + // CHECK: load ptr, ptr %{{.*}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}} *x } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff index b698d8f373575..f4d395335870a 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.32bit.diff @@ -13,8 +13,8 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); -+ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); ++ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute); unreachable; } } diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff index b698d8f373575..f4d395335870a 100644 --- a/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff +++ b/tests/mir-opt/const_prop/transmute.unreachable_box.GVN.64bit.diff @@ -13,8 +13,8 @@ StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); - _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); -+ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); -+ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} }} as *const Never (Transmute); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); ++ _2 = const std::ptr::NonNull:: {{ pointer: {0x1 as *const Never} is !null }} as *const Never (Transmute); unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index 2c89670dcf7d7..4fc66f1bf7200 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,19 +45,19 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); + _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _7 = const {0x1 as *const [bool; 0]} is !null; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 8fecfe224cc69..c9b9d2fb8bc96 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,19 +45,19 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); + _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _7 = const {0x1 as *const [bool; 0]} is !null; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index 976ea252c2f89..9b455a71afa24 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,19 +45,19 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); + _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _7 = const {0x1 as *const [bool; 0]} is !null; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 6c59f5e3e2e86..fb9e46fa2c517 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -45,19 +45,19 @@ StorageLive(_4); StorageLive(_5); StorageLive(_6); - _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); + _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); - _7 = const {0x1 as *const [bool; 0]}; - _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; + _7 = const {0x1 as *const [bool; 0]} is !null; + _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; + _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; + _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); + _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index 1f9cf6d6aca83..c8548a9f9a4b6 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -46,25 +46,25 @@ StorageLive(_5); StorageLive(_6); - _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); ++ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; +- _7 = copy _6 as (*const [bool; 0]) is !null (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: move _7 }; ++ _7 = const {0x1 as *const [bool; 0]} is !null; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(copy _3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; ++ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index a8760285fac11..5417d6555fc76 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -46,25 +46,25 @@ StorageLive(_5); StorageLive(_6); - _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); ++ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; +- _7 = copy _6 as (*const [bool; 0]) is !null (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: move _7 }; ++ _7 = const {0x1 as *const [bool; 0]} is !null; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(copy _3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; ++ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index c398ae70a1a3e..e046cc38ea331 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -46,25 +46,25 @@ StorageLive(_5); StorageLive(_6); - _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); ++ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; +- _7 = copy _6 as (*const [bool; 0]) is !null (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: move _7 }; ++ _7 = const {0x1 as *const [bool; 0]} is !null; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(copy _3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; ++ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index 02934c02587d2..91cb8622b45ea 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -21,7 +21,7 @@ scope 8 (inlined std::ptr::Alignment::as_nonzero) { } scope 9 (inlined NonNull::<[bool; 0]>::without_provenance) { - let _7: *const [bool; 0]; + let mut _7: (*const [bool; 0]) is !null; scope 10 { } scope 11 (inlined NonZero::::get) { @@ -46,25 +46,25 @@ StorageLive(_5); StorageLive(_6); - _6 = const std::ptr::Alignment::of::<[bool; 0]>::{constant#0} as std::num::NonZero (Transmute); -+ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); ++ _6 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); StorageLive(_7); -- _7 = copy _6 as *const [bool; 0] (Transmute); -- _5 = NonNull::<[bool; 0]> { pointer: copy _7 }; -+ _7 = const {0x1 as *const [bool; 0]}; -+ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}; +- _7 = copy _6 as (*const [bool; 0]) is !null (Transmute); +- _5 = NonNull::<[bool; 0]> { pointer: move _7 }; ++ _7 = const {0x1 as *const [bool; 0]} is !null; ++ _5 = const NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}; StorageDead(_7); StorageDead(_6); - _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; -+ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} }}, _marker: PhantomData::<[bool; 0]> }}; ++ _4 = const Unique::<[bool; 0]> {{ pointer: NonNull::<[bool; 0]> {{ pointer: {0x1 as *const [bool; 0]} is !null }}, _marker: PhantomData::<[bool; 0]> }}; StorageDead(_5); - _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize, Implicit)); -+ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}; ++ _3 = const Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC0, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}; StorageDead(_4); - _2 = Box::<[bool]>(copy _3, const std::alloc::Global); -+ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); ++ _2 = const Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC1, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global); StorageDead(_3); - _1 = A { foo: move _2 }; -+ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; ++ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: (*const [bool]) is !null }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff index fa6c2e29e072e..802d6daa1a27d 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.32bit.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -+ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); unreachable; } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff index fa6c2e29e072e..802d6daa1a27d 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_box.DataflowConstProp.64bit.diff @@ -12,7 +12,7 @@ bb0: { StorageLive(_1); - _1 = const 1_usize as std::boxed::Box (Transmute); -+ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData:: }}, std::alloc::Global); ++ _1 = const Box::(Unique:: {{ pointer: NonNull:: {{ pointer: {0x1 as *const Never} is !null }}, _marker: PhantomData:: }}, std::alloc::Global); _2 = copy ((_1.0: std::ptr::Unique).0: std::ptr::NonNull) as *const Never (Transmute); unreachable; } diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 25ffff619e60b..16a3dffcce07d 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -10,7 +10,7 @@ let mut _8: *const [()]; let mut _9: std::boxed::Box<()>; let mut _10: *const (); - let mut _23: usize; + let mut _25: usize; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -47,7 +47,9 @@ scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _22: *mut [u8]; + let mut _22: (*const u8) is !null; + let mut _23: *mut u8; + let mut _24: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -105,8 +107,14 @@ bb4: { _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); - _22 = copy _17 as *mut [u8] (Transmute); - _13 = copy _22 as *mut u8 (PtrToPtr); + StorageLive(_23); + StorageLive(_24); + _24 = copy _17 as *mut [u8] (Transmute); + _23 = move _24 as *mut u8 (PtrToPtr); + StorageDead(_24); + _22 = move _23 as (*const u8) is !null (Transmute); + StorageDead(_23); + _13 = copy _22 as *mut u8 (Transmute); StorageDead(_22); StorageDead(_15); StorageDead(_17); @@ -129,11 +137,11 @@ StorageLive(_6); - _6 = copy _4; + _6 = copy _10; - StorageLive(_23); - _23 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _23); + StorageLive(_25); + _25 = const 1_usize; +- _5 = *const [()] from (copy _6, copy _25); + _5 = *const [()] from (copy _10, const 1_usize); - StorageDead(_23); + StorageDead(_25); StorageDead(_6); StorageLive(_7); StorageLive(_8); diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 839b53e3b0b3b..592734e01e5a0 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -10,7 +10,7 @@ let mut _8: *const [()]; let mut _9: std::boxed::Box<()>; let mut _10: *const (); - let mut _23: usize; + let mut _25: usize; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -47,7 +47,9 @@ scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::) { - let mut _22: *mut [u8]; + let mut _22: (*const u8) is !null; + let mut _23: *mut u8; + let mut _24: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -105,8 +107,14 @@ bb4: { _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); - _22 = copy _17 as *mut [u8] (Transmute); - _13 = copy _22 as *mut u8 (PtrToPtr); + StorageLive(_23); + StorageLive(_24); + _24 = copy _17 as *mut [u8] (Transmute); + _23 = move _24 as *mut u8 (PtrToPtr); + StorageDead(_24); + _22 = move _23 as (*const u8) is !null (Transmute); + StorageDead(_23); + _13 = copy _22 as *mut u8 (Transmute); StorageDead(_22); StorageDead(_15); StorageDead(_17); @@ -129,11 +137,11 @@ StorageLive(_6); - _6 = copy _4; + _6 = copy _10; - StorageLive(_23); - _23 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _23); + StorageLive(_25); + _25 = const 1_usize; +- _5 = *const [()] from (copy _6, copy _25); + _5 = *const [()] from (copy _10, const 1_usize); - StorageDead(_23); + StorageDead(_25); StorageDead(_6); StorageLive(_7); StorageLive(_8); diff --git a/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff index 279c1a1990dc8..6075d7895eeb3 100644 --- a/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff +++ b/tests/mir-opt/elaborate_box_deref_in_debuginfo.pointee.ElaborateBoxDerefs.diff @@ -3,7 +3,7 @@ fn pointee(_1: Box) -> () { - debug foo => (*_1); -+ debug foo => (*(((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: *const i32)); ++ debug foo => (*((((_1.0: std::ptr::Unique).0: std::ptr::NonNull).0: (*const i32) is !null).0: *const i32)); let mut _0: (); bb0: { diff --git a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff index f56af33ea603f..55fea9aef9101 100644 --- a/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff +++ b/tests/mir-opt/gvn_ptr_eq_with_constant.main.GVN.diff @@ -12,6 +12,7 @@ scope 5 (inlined std::ptr::Alignment::as_nonzero) { } scope 6 (inlined NonNull::::without_provenance) { + let mut _4: (*const u8) is !null; scope 7 { } scope 8 (inlined NonZero::::get) { @@ -29,9 +30,9 @@ } } scope 12 (inlined Foo::::cmp_ptr) { - let mut _4: *const u8; - let mut _5: *mut u8; - let mut _6: *const u8; + let mut _5: *const u8; + let mut _6: *mut u8; + let mut _7: *const u8; scope 13 (inlined std::ptr::eq::) { } } @@ -39,26 +40,29 @@ bb0: { StorageLive(_1); StorageLive(_2); + StorageLive(_4); StorageLive(_3); - _3 = const std::ptr::Alignment::of::::{constant#0} as std::num::NonZero (Transmute); -- _2 = copy _3 as *mut u8 (Transmute); -+ _3 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize)); -+ _2 = const {0x1 as *mut u8}; +- _4 = copy _3 as (*const u8) is !null (Transmute); ++ _3 = const NonZero::(core::num::niche_types::NonZeroUsizeInner(1_usize is 1..)); ++ _4 = const {0x1 as *const u8} is !null; StorageDead(_3); - StorageLive(_4); +- _2 = copy _4 as *mut u8 (Transmute); ++ _2 = const {0x1 as *const u8} is !null as *mut u8 (Transmute); + StorageDead(_4); StorageLive(_5); -- _5 = copy _2; -- _4 = copy _2 as *const u8 (PtrToPtr); -+ _5 = const {0x1 as *mut u8}; -+ _4 = const {0x1 as *const u8}; - StorageDead(_5); StorageLive(_6); -- _6 = const Foo::::SENTINEL as *const u8 (PtrToPtr); -- _1 = Eq(copy _4, copy _6); -+ _6 = const {0x1 as *const u8}; -+ _1 = const true; + _6 = copy _2; +- _5 = copy _2 as *const u8 (PtrToPtr); ++ _5 = const {0x1 as *const u8} is !null as *const u8 (Transmute); StorageDead(_6); - StorageDead(_4); + StorageLive(_7); +- _7 = const Foo::::SENTINEL as *const u8 (PtrToPtr); +- _1 = Eq(copy _5, copy _7); ++ _7 = const {0x1 as *const u8}; ++ _1 = Eq(copy _5, const {0x1 as *const u8}); + StorageDead(_7); + StorageDead(_5); StorageDead(_2); StorageDead(_1); _0 = const (); diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index f6c111a2228a9..e75984b98fbe4 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -19,9 +19,10 @@ + scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { + scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { + scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { -+ let mut _11: std::ptr::NonNull; ++ let mut _12: std::ptr::NonNull; + scope 7 (inlined Unique::::cast::) { + scope 8 (inlined NonNull::::cast::) { ++ let mut _11: (*const A) is !null; + scope 9 (inlined NonNull::::as_ptr) { + } + } @@ -39,15 +40,15 @@ + } + } + scope 14 (inlined drop_in_place::<[A]> - shim(Some([A]))) { -+ let mut _12: usize; -+ let mut _13: *mut A; -+ let mut _14: bool; ++ let mut _13: usize; ++ let mut _14: *mut A; ++ let mut _15: bool; + } + } + } + scope 15 (inlined drop_in_place::> - shim(Some(Option))) { -+ let mut _15: isize; + let mut _16: isize; ++ let mut _17: isize; + } bb0: { @@ -62,16 +63,19 @@ + StorageLive(_8); + StorageLive(_9); + StorageLive(_11); -+ _11 = copy (((((*_6).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); ++ StorageLive(_12); ++ _12 = copy (((((*_6).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _11 = copy _12 as (*const A) is !null (Transmute); ++ StorageDead(_12); + _9 = copy _11 as *mut A (Transmute); + StorageDead(_11); + _10 = copy ((*_6).1: usize); + _8 = *mut [A] from (copy _9, copy _10); + StorageDead(_9); -+ StorageLive(_12); + StorageLive(_13); + StorageLive(_14); -+ _12 = const 0_usize; ++ StorageLive(_15); ++ _13 = const 0_usize; + goto -> bb4; } @@ -83,35 +87,35 @@ StorageLive(_5); _5 = copy _2; - _0 = drop_in_place::>(move _5) -> [return: bb2, unwind unreachable]; -+ StorageLive(_15); + StorageLive(_16); -+ _15 = discriminant((*_5)); -+ switchInt(move _15) -> [0: bb5, otherwise: bb6]; ++ StorageLive(_17); ++ _16 = discriminant((*_5)); ++ switchInt(move _16) -> [0: bb5, otherwise: bb6]; } bb2: { ++ StorageDead(_15); + StorageDead(_14); + StorageDead(_13); -+ StorageDead(_12); + StorageDead(_8); + StorageDead(_10); + drop(((*_4).0: alloc::raw_vec::RawVec)) -> [return: bb1, unwind unreachable]; + } + + bb3: { -+ _13 = &raw mut (*_8)[_12]; -+ _12 = Add(move _12, const 1_usize); -+ drop((*_13)) -> [return: bb4, unwind unreachable]; ++ _14 = &raw mut (*_8)[_13]; ++ _13 = Add(move _13, const 1_usize); ++ drop((*_14)) -> [return: bb4, unwind unreachable]; + } + + bb4: { -+ _14 = Eq(copy _12, copy _10); -+ switchInt(move _14) -> [0: bb3, otherwise: bb2]; ++ _15 = Eq(copy _13, copy _10); ++ switchInt(move _15) -> [0: bb3, otherwise: bb2]; + } + + bb5: { ++ StorageDead(_17); + StorageDead(_16); -+ StorageDead(_15); StorageDead(_5); return; + } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir index 30eafe8594b3f..068af3fd7ce64 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-abort.mir @@ -7,8 +7,8 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { debug self => _1; scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _3: *const u8; - let mut _4: usize; + let mut _4: *const u8; + let mut _5: usize; scope 3 (inlined Vec::::as_ptr) { debug self => _1; scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { @@ -17,6 +17,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _2: std::ptr::NonNull; scope 7 (inlined Unique::::cast::) { scope 8 (inlined NonNull::::cast::) { + let mut _3: (*const u8) is !null; scope 9 (inlined NonNull::::as_ptr) { } } @@ -30,9 +31,9 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 12 (inlined #[track_caller] std::slice::from_raw_parts::<'_, u8>) { - debug data => _3; - debug len => _4; - let _5: *const [u8]; + debug data => _4; + debug len => _5; + let _6: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -42,10 +43,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 16 (inlined align_of::) { } scope 17 (inlined slice_from_raw_parts::) { - debug data => _3; - debug len => _4; + debug data => _4; + debug len => _5; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _3; + debug data_pointer => _4; } } } @@ -53,19 +54,22 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } bb0: { - StorageLive(_2); StorageLive(_3); - _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = copy _2 as *const u8 (Transmute); StorageLive(_4); - _4 = copy ((*_1).1: usize); + StorageLive(_2); + _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _3 = copy _2 as (*const u8) is !null (Transmute); + StorageDead(_2); + _4 = copy _3 as *const u8 (Transmute); StorageLive(_5); - _5 = *const [u8] from (copy _3, copy _4); - _0 = &(*_5); + _5 = copy ((*_1).1: usize); + StorageLive(_6); + _6 = *const [u8] from (copy _4, copy _5); + _0 = &(*_6); + StorageDead(_6); StorageDead(_5); StorageDead(_4); StorageDead(_3); - StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir index 30eafe8594b3f..068af3fd7ce64 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.PreCodegen.after.panic-unwind.mir @@ -7,8 +7,8 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { debug self => _1; scope 2 (inlined Vec::::as_slice) { debug self => _1; - let mut _3: *const u8; - let mut _4: usize; + let mut _4: *const u8; + let mut _5: usize; scope 3 (inlined Vec::::as_ptr) { debug self => _1; scope 4 (inlined alloc::raw_vec::RawVec::::ptr) { @@ -17,6 +17,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { let mut _2: std::ptr::NonNull; scope 7 (inlined Unique::::cast::) { scope 8 (inlined NonNull::::cast::) { + let mut _3: (*const u8) is !null; scope 9 (inlined NonNull::::as_ptr) { } } @@ -30,9 +31,9 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } } scope 12 (inlined #[track_caller] std::slice::from_raw_parts::<'_, u8>) { - debug data => _3; - debug len => _4; - let _5: *const [u8]; + debug data => _4; + debug len => _5; + let _6: *const [u8]; scope 13 (inlined core::ub_checks::check_language_ub) { scope 14 (inlined core::ub_checks::check_language_ub::runtime) { } @@ -42,10 +43,10 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 16 (inlined align_of::) { } scope 17 (inlined slice_from_raw_parts::) { - debug data => _3; - debug len => _4; + debug data => _4; + debug len => _5; scope 18 (inlined std::ptr::from_raw_parts::<[u8], u8>) { - debug data_pointer => _3; + debug data_pointer => _4; } } } @@ -53,19 +54,22 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { } bb0: { - StorageLive(_2); StorageLive(_3); - _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); - _3 = copy _2 as *const u8 (Transmute); StorageLive(_4); - _4 = copy ((*_1).1: usize); + StorageLive(_2); + _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _3 = copy _2 as (*const u8) is !null (Transmute); + StorageDead(_2); + _4 = copy _3 as *const u8 (Transmute); StorageLive(_5); - _5 = *const [u8] from (copy _3, copy _4); - _0 = &(*_5); + _5 = copy ((*_1).1: usize); + StorageLive(_6); + _6 = *const [u8] from (copy _4, copy _5); + _0 = &(*_6); + StorageDead(_6); StorageDead(_5); StorageDead(_4); StorageDead(_3); - StorageDead(_2); return; } } diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr index 36183e2892101..c09fe36a3df9c 100644 --- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr @@ -53,7 +53,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran 78 00 00 00 ff ff ff ff │ x....... } -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:58:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; 00 00 00 00 │ .... } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:61:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; 00 │ . } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:63:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; @@ -108,7 +108,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; 14 00 00 00 │ .... } -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:78:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr index c53326534fdc5..55a55ddb57092 100644 --- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr +++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr @@ -53,7 +53,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran 78 00 00 00 ff ff ff ff │ x....... } -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:58:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; @@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; 00 00 00 00 00 00 00 00 │ ........ } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:61:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; 00 │ . } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:63:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; @@ -108,7 +108,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; 14 00 00 00 │ .... } -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/raw-bytes.rs:78:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 0a02dbb16bff8..cc8f3dadfdea4 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -1,4 +1,4 @@ -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:16:1 | LL | const NULL_PTR: NonNull = unsafe { mem::transmute(0usize) }; @@ -15,7 +15,7 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer LL | let out_of_bounds_ptr = &ptr[255]; | ^^^^^^^^^ evaluation of constant value failed here -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:26:1 | LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; @@ -26,7 +26,7 @@ LL | const NULL_U8: NonZero = unsafe { mem::transmute(0u8) }; HEX_DUMP } -error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:28:1 | LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; @@ -65,7 +65,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; HEX_DUMP } -error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1 +error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1 --> $DIR/ub-nonnull.rs:53:1 | LL | const NULL_FAT_PTR: NonNull = unsafe { diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr index cc6a2a1c8e532..63df1e5d11d68 100644 --- a/tests/ui/lint/invalid_value.stderr +++ b/tests/ui/lint/invalid_value.stderr @@ -314,7 +314,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 `(NonZero, i32)` does not permit zero-initialization --> $DIR/invalid_value.rs:94:41 @@ -333,7 +332,6 @@ LL | let _val: (NonZero, i32) = mem::uninitialized(); | = note: `std::num::NonZero` must be non-null = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null - = note: integers must be initialized error: the type `*const dyn Send` does not permit zero-initialization --> $DIR/invalid_value.rs:97:37 @@ -430,7 +428,6 @@ note: because `std::num::NonZero` must be non-null (in this field of the on LL | Banana(NonZero), | ^^^^^^^^^^^^ = note: because `core::num::niche_types::NonZeroU32Inner` must be non-null - = note: integers must be initialized error: the type `bool` does not permit being left uninitialized --> $DIR/invalid_value.rs:111:26 @@ -625,7 +622,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:158:26 diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs index 549b0d11dd187..7e2b4cb996f27 100644 --- a/tests/ui/type/pattern_types/bad_pat.rs +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -10,4 +10,15 @@ type Positive2 = pattern_type!(i32 is 0..=); type Wild = pattern_type!(() is _); //~^ ERROR: pattern not supported in pattern types +// FIXME: confusing diagnostic because `not` can be a binding +type NonNull = pattern_type!(*const () is not null); +//~^ ERROR: expected one of `@` or `|`, found `null` +//~| ERROR: pattern not supported in pattern types + +type NonNull2 = pattern_type!(*const () is !nil); +//~^ ERROR: expected `null`, found `nil` + +// FIXME: reject with a type mismatch +type Mismatch2 = pattern_type!(() is !null); + fn main() {} diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index d2a5a20bf89b6..e72279542280c 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -30,6 +30,24 @@ error: pattern not supported in pattern types LL | type Wild = pattern_type!(() is _); | ^ -error: aborting due to 3 previous errors +error: pattern not supported in pattern types + --> $DIR/bad_pat.rs:14:43 + | +LL | type NonNull = pattern_type!(*const () is not null); + | ^^^ + +error: expected one of `@` or `|`, found `null` + --> $DIR/bad_pat.rs:14:47 + | +LL | type NonNull = pattern_type!(*const () is not null); + | ^^^^ expected one of `@` or `|` + +error: expected `null`, found `nil` + --> $DIR/bad_pat.rs:18:45 + | +LL | type NonNull2 = pattern_type!(*const () is !nil); + | ^^^ expected `null` + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0586`. diff --git a/tests/ui/type/pattern_types/non_null.rs b/tests/ui/type/pattern_types/non_null.rs new file mode 100644 index 0000000000000..6a36ab9324170 --- /dev/null +++ b/tests/ui/type/pattern_types/non_null.rs @@ -0,0 +1,20 @@ +//! Show that pattern-types non-null is the same as libstd's + +//@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED" + +#![feature(pattern_type_macro, pattern_types, rustc_attrs)] + +use std::pat::pattern_type; + +#[rustc_layout(debug)] +type NonNull = pattern_type!(*const T is !null); //~ ERROR layout_of + +#[rustc_layout(debug)] +type Test = Option>; //~ ERROR layout_of + +#[rustc_layout(debug)] +type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of + +const _: () = assert!(size_of::>() == size_of::>>()); + +fn main() {} diff --git a/tests/ui/type/pattern_types/non_null.stderr b/tests/ui/type/pattern_types/non_null.stderr new file mode 100644 index 0000000000000..b779a2485192f --- /dev/null +++ b/tests/ui/type/pattern_types/non_null.stderr @@ -0,0 +1,223 @@ +error: layout_of((*const T) is !null) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: Align(8 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + ), + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + } + --> $DIR/non_null.rs:10:1 + | +LL | type NonNull = pattern_type!(*const T is !null); + | ^^^^^^^^^^^^^^^ + +error: layout_of(Option<(*const ()) is !null>) = Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: Align(8 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: (..=0) | (1..), + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: None, + uninhabited: false, + variants: Multiple { + tag: Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: (..=0) | (1..), + }, + tag_encoding: Niche { + untagged_variant: 1, + niche_variants: 0..=0, + niche_start: 0, + }, + tag_field: 0, + variants: [ + Layout { + size: Size(0 bytes), + align: AbiAndPrefAlign { + abi: Align(1 bytes), + pref: Align(8 bytes), + }, + backend_repr: Memory { + sized: true, + }, + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + largest_niche: None, + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(1 bytes), + randomization_seed: $SEED, + }, + Layout { + size: Size(8 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: Align(8 bytes), + }, + backend_repr: Scalar( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + ), + uninhabited: false, + variants: Single { + index: 1, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + }, + ], + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + } + --> $DIR/non_null.rs:13:1 + | +LL | type Test = Option>; + | ^^^^^^^^^ + +error: layout_of((*const [u8]) is !null) = Layout { + size: Size(16 bytes), + align: AbiAndPrefAlign { + abi: Align(8 bytes), + pref: Align(8 bytes), + }, + backend_repr: ScalarPair( + Initialized { + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + Initialized { + value: Int( + I64, + false, + ), + valid_range: 0..=18446744073709551615, + }, + ), + fields: Arbitrary { + offsets: [ + Size(0 bytes), + ], + memory_index: [ + 0, + ], + }, + largest_niche: Some( + Niche { + offset: Size(0 bytes), + value: Pointer( + AddressSpace( + 0, + ), + ), + valid_range: 1..=18446744073709551615, + }, + ), + uninhabited: false, + variants: Single { + index: 0, + }, + max_repr_align: None, + unadjusted_abi_align: Align(8 bytes), + randomization_seed: $SEED, + } + --> $DIR/non_null.rs:16:1 + | +LL | type Wide = pattern_type!(*const [u8] is !null); + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/type/pattern_types/unsize.rs b/tests/ui/type/pattern_types/unsize.rs new file mode 100644 index 0000000000000..1020dd8c21544 --- /dev/null +++ b/tests/ui/type/pattern_types/unsize.rs @@ -0,0 +1,18 @@ +//! Show that pattern-types with pointer base types can be part of unsizing coercions + +//@ check-pass + +#![feature(pattern_type_macro, pattern_types)] + +use std::pat::pattern_type; + +type NonNull = pattern_type!(*const T is !null); + +trait Trait {} +impl Trait for u32 {} +impl Trait for i32 {} + +fn main() { + let x: NonNull = unsafe { std::mem::transmute(std::ptr::dangling::()) }; + let x: NonNull = x; +}