From 920c51c5265833b1a587ad9206e271f49564e2cc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Mar 2023 20:53:43 +0000 Subject: [PATCH] Enforce that PointerLike requires a pointer-like ABI --- compiler/rustc_abi/src/lib.rs | 10 ++++++++++ .../src/solve/trait_goals.rs | 3 +-- .../src/traits/select/candidate_assembly.rs | 15 +++++++-------- library/core/src/marker.rs | 2 +- tests/ui/dyn-star/align.normal.stderr | 13 +++++++++++-- tests/ui/dyn-star/align.over_aligned.stderr | 6 +++--- tests/ui/dyn-star/align.rs | 3 +-- .../check-size-at-cast-polymorphic-bad.rs | 2 +- .../check-size-at-cast-polymorphic-bad.stderr | 2 +- tests/ui/dyn-star/check-size-at-cast.rs | 2 +- tests/ui/dyn-star/check-size-at-cast.stderr | 2 +- tests/ui/dyn-star/upcast.stderr | 2 +- tests/ui/traits/new-solver/pointer-like.rs | 2 +- tests/ui/traits/new-solver/pointer-like.stderr | 2 +- 14 files changed, 41 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index da91776ef67..76765c8a0aa 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1522,6 +1522,16 @@ impl<'a> Layout<'a> { pub fn size(self) -> Size { self.0.0.size } + + /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. + /// + /// Currently, that means that the type is pointer-sized, pointer-aligned, + /// and has a scalar ABI. + pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool { + self.size() == data_layout.pointer_size + && self.align().abi == data_layout.pointer_align.abi + && matches!(self.abi(), Abi::Scalar(..)) + } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index ce3db83d33d..a2203473ca9 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -221,8 +221,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let self_ty = tcx.erase_regions(goal.predicate.self_ty()); if let Ok(layout) = tcx.layout_of(goal.param_env.and(self_ty)) - && layout.layout.size() == tcx.data_layout.pointer_size - && layout.layout.align().abi == tcx.data_layout.pointer_align.abi + && layout.layout.is_pointer_like(&tcx.data_layout) { // FIXME: We could make this faster by making a no-constraints response ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) 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 090312338e0..a794d20d683 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -97,7 +97,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.tuple_trait() == Some(def_id) { self.assemble_candidate_for_tuple(obligation, &mut candidates); } else if lang_items.pointer_like() == Some(def_id) { - self.assemble_candidate_for_ptr_sized(obligation, &mut candidates); + self.assemble_candidate_for_pointer_like(obligation, &mut candidates); } else if lang_items.fn_ptr_trait() == Some(def_id) { self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates); } else { @@ -942,15 +942,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - fn assemble_candidate_for_ptr_sized( + fn assemble_candidate_for_pointer_like( &mut self, obligation: &TraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { // The regions of a type don't affect the size of the type - let self_ty = self - .tcx() - .erase_regions(self.tcx().erase_late_bound_regions(obligation.predicate.self_ty())); + let tcx = self.tcx(); + let self_ty = + tcx.erase_regions(tcx.erase_late_bound_regions(obligation.predicate.self_ty())); // But if there are inference variables, we have to wait until it's resolved. if self_ty.has_non_region_infer() { @@ -958,9 +958,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return; } - if let Ok(layout) = self.tcx().layout_of(obligation.param_env.and(self_ty)) - && layout.layout.size() == self.tcx().data_layout.pointer_size - && layout.layout.align().abi == self.tcx().data_layout.pointer_align.abi + if let Ok(layout) = tcx.layout_of(obligation.param_env.and(self_ty)) + && layout.layout.is_pointer_like(&tcx.data_layout) { candidates.vec.push(BuiltinCandidate { has_nested: false }); } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 74e9c55396d..62064f1aa6c 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -879,7 +879,7 @@ pub trait Tuple {} #[unstable(feature = "pointer_like_trait", issue = "none")] #[lang = "pointer_like"] #[rustc_on_unimplemented( - message = "`{Self}` needs to have the same alignment and size as a pointer", + message = "`{Self}` needs to have the same ABI as a pointer", label = "`{Self}` needs to be a pointer-like type" )] pub trait PointerLike {} diff --git a/tests/ui/dyn-star/align.normal.stderr b/tests/ui/dyn-star/align.normal.stderr index 53c2cbeac32..42fa4fd6f00 100644 --- a/tests/ui/dyn-star/align.normal.stderr +++ b/tests/ui/dyn-star/align.normal.stderr @@ -1,5 +1,5 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/align.rs:4:12 + --> $DIR/align.rs:3:12 | LL | #![feature(dyn_star)] | ^^^^^^^^ @@ -7,5 +7,14 @@ LL | #![feature(dyn_star)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer + --> $DIR/align.rs:14:13 + | +LL | let x = AlignedUsize(12) as dyn* Debug; + | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type + | + = help: the trait `PointerLike` is not implemented for `AlignedUsize` +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/dyn-star/align.over_aligned.stderr b/tests/ui/dyn-star/align.over_aligned.stderr index 0365d87a6f8..42fa4fd6f00 100644 --- a/tests/ui/dyn-star/align.over_aligned.stderr +++ b/tests/ui/dyn-star/align.over_aligned.stderr @@ -1,5 +1,5 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/align.rs:4:12 + --> $DIR/align.rs:3:12 | LL | #![feature(dyn_star)] | ^^^^^^^^ @@ -7,8 +7,8 @@ LL | #![feature(dyn_star)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `AlignedUsize` needs to have the same alignment and size as a pointer - --> $DIR/align.rs:15:13 +error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer + --> $DIR/align.rs:14:13 | LL | let x = AlignedUsize(12) as dyn* Debug; | ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type diff --git a/tests/ui/dyn-star/align.rs b/tests/ui/dyn-star/align.rs index 6679997a940..79cbaba0c78 100644 --- a/tests/ui/dyn-star/align.rs +++ b/tests/ui/dyn-star/align.rs @@ -1,5 +1,4 @@ // revisions: normal over_aligned -//[normal] check-pass #![feature(dyn_star)] //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes @@ -13,5 +12,5 @@ struct AlignedUsize(usize); fn main() { let x = AlignedUsize(12) as dyn* Debug; - //[over_aligned]~^ ERROR `AlignedUsize` needs to have the same alignment and size as a pointer + //~^ ERROR `AlignedUsize` needs to have the same ABI as a pointer } diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs index 85749aa7b00..913c2faacbd 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs @@ -9,7 +9,7 @@ fn dyn_debug(_: (dyn* Debug + '_)) { fn polymorphic(t: &T) { dyn_debug(t); - //~^ ERROR `&T` needs to have the same alignment and size as a pointer + //~^ ERROR `&T` needs to have the same ABI as a pointer } fn main() {} diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr index 350630f7941..8726fae79a0 100644 --- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr +++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.stderr @@ -1,4 +1,4 @@ -error[E0277]: `&T` needs to have the same alignment and size as a pointer +error[E0277]: `&T` needs to have the same ABI as a pointer --> $DIR/check-size-at-cast-polymorphic-bad.rs:11:15 | LL | dyn_debug(t); diff --git a/tests/ui/dyn-star/check-size-at-cast.rs b/tests/ui/dyn-star/check-size-at-cast.rs index 17bc4f303bf..e15e090b529 100644 --- a/tests/ui/dyn-star/check-size-at-cast.rs +++ b/tests/ui/dyn-star/check-size-at-cast.rs @@ -5,6 +5,6 @@ use std::fmt::Debug; fn main() { let i = [1, 2, 3, 4] as dyn* Debug; - //~^ ERROR `[i32; 4]` needs to have the same alignment and size as a pointer + //~^ ERROR `[i32; 4]` needs to have the same ABI as a pointer dbg!(i); } diff --git a/tests/ui/dyn-star/check-size-at-cast.stderr b/tests/ui/dyn-star/check-size-at-cast.stderr index 19700b40644..e60b5c56ff0 100644 --- a/tests/ui/dyn-star/check-size-at-cast.stderr +++ b/tests/ui/dyn-star/check-size-at-cast.stderr @@ -1,4 +1,4 @@ -error[E0277]: `[i32; 4]` needs to have the same alignment and size as a pointer +error[E0277]: `[i32; 4]` needs to have the same ABI as a pointer --> $DIR/check-size-at-cast.rs:7:13 | LL | let i = [1, 2, 3, 4] as dyn* Debug; diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr index e60144fea74..8b34c7f8b71 100644 --- a/tests/ui/dyn-star/upcast.stderr +++ b/tests/ui/dyn-star/upcast.stderr @@ -7,7 +7,7 @@ LL | #![feature(dyn_star, trait_upcasting)] = note: see issue #102425 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `dyn* Foo` needs to have the same alignment and size as a pointer +error[E0277]: `dyn* Foo` needs to have the same ABI as a pointer --> $DIR/upcast.rs:30:23 | LL | let w: dyn* Bar = w; diff --git a/tests/ui/traits/new-solver/pointer-like.rs b/tests/ui/traits/new-solver/pointer-like.rs index 3745a075e6a..98630176976 100644 --- a/tests/ui/traits/new-solver/pointer-like.rs +++ b/tests/ui/traits/new-solver/pointer-like.rs @@ -9,6 +9,6 @@ fn require_(_: impl PointerLike) {} fn main() { require_(1usize); require_(1u16); - //~^ ERROR `u16` needs to have the same alignment and size as a pointer + //~^ ERROR `u16` needs to have the same ABI as a pointer require_(&1i16); } diff --git a/tests/ui/traits/new-solver/pointer-like.stderr b/tests/ui/traits/new-solver/pointer-like.stderr index f695e64187d..215a81cc265 100644 --- a/tests/ui/traits/new-solver/pointer-like.stderr +++ b/tests/ui/traits/new-solver/pointer-like.stderr @@ -1,4 +1,4 @@ -error[E0277]: `u16` needs to have the same alignment and size as a pointer +error[E0277]: `u16` needs to have the same ABI as a pointer --> $DIR/pointer-like.rs:11:14 | LL | require_(1u16);