Skip to content

Enforce that PointerLike requires a pointer-like ABI #109413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
3 changes: 1 addition & 2 deletions compiler/rustc_trait_selection/src/solve/trait_goals.rs
Original file line number Diff line number Diff line change
@@ -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)
Original file line number Diff line number Diff line change
@@ -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,25 +942,24 @@ 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() {
candidates.ambiguous = true;
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 });
}
2 changes: 1 addition & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
@@ -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 {}
13 changes: 11 additions & 2 deletions tests/ui/dyn-star/align.normal.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
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)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/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`.
6 changes: 3 additions & 3 deletions tests/ui/dyn-star/align.over_aligned.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
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)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/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
3 changes: 1 addition & 2 deletions tests/ui/dyn-star/align.rs
Original file line number Diff line number Diff line change
@@ -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
}
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ fn dyn_debug(_: (dyn* Debug + '_)) {

fn polymorphic<T: Debug + ?Sized>(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() {}
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/check-size-at-cast.rs
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/check-size-at-cast.stderr
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/upcast.stderr
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ LL | #![feature(dyn_star, trait_upcasting)]
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/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;
2 changes: 1 addition & 1 deletion tests/ui/traits/new-solver/pointer-like.rs
Original file line number Diff line number Diff line change
@@ -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);
}
2 changes: 1 addition & 1 deletion tests/ui/traits/new-solver/pointer-like.stderr
Original file line number Diff line number Diff line change
@@ -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);