Skip to content

Commit

Permalink
Auto merge of #109413 - compiler-errors:pointer-like-abi, r=cjgillot
Browse files Browse the repository at this point in the history
Enforce that `PointerLike` requires a pointer-like ABI

At least temporarily, let's ban coercing things that are pointer-sized and pointer-aligned but *not* `Abi::Scalar(..)` into `dyn*`. See: #104694 (comment)

This can be lifted in the future if we decie that we *want* to be able to coerce something `repr(C)` into a `dyn*`, but we'll have to figure out what to do with Miri and codegen...

r? compiler
  • Loading branch information
bors committed Apr 9, 2023
2 parents f8ed97e + 920c51c commit 0030465
Show file tree
Hide file tree
Showing 14 changed files with 41 additions and 25 deletions.
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

0 comments on commit 0030465

Please sign in to comment.