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
Show file tree
Hide file tree
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
Expand Up @@ -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)]
Expand Down
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
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 });
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
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
Expand Down
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
Expand All @@ -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
Expand Up @@ -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);
Expand Down
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
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/dyn-star/upcast.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/traits/new-solver/pointer-like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down