Skip to content
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

Rollup of 4 pull requests #90899

Closed
wants to merge 10 commits into from
92 changes: 50 additions & 42 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,36 @@ pub struct GccLinker<'a> {
}

impl<'a> GccLinker<'a> {
/// Argument that must be passed *directly* to the linker
/// Passes an argument directly to the linker.
///
/// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
fn linker_arg<S>(&mut self, arg: S) -> &mut Self
where
S: AsRef<OsStr>,
{
if !self.is_ld {
let mut os = OsString::from("-Wl,");
os.push(arg.as_ref());
self.cmd.arg(os);
/// When the linker is not ld-like such as when using a compiler as a linker, the argument is
/// prepended by `-Wl,`.
fn linker_arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
self.linker_args(&[arg]);
self
}

/// Passes a series of arguments directly to the linker.
///
/// When the linker is ld-like, the arguments are simply appended to the command. When the
/// linker is not ld-like such as when using a compiler as a linker, the arguments are joined by
/// commas to form an argument that is then prepended with `-Wl`. In this situation, only a
/// single argument is appended to the command to ensure that the order of the arguments is
/// preserved by the compiler.
fn linker_args(&mut self, args: &[impl AsRef<OsStr>]) -> &mut Self {
if self.is_ld {
args.into_iter().for_each(|a| {
self.cmd.arg(a);
});
} else {
self.cmd.arg(arg);
if !args.is_empty() {
let mut s = OsString::from("-Wl");
for a in args {
s.push(",");
s.push(a);
}
self.cmd.arg(s);
}
}
self
}
Expand Down Expand Up @@ -289,25 +306,29 @@ impl<'a> GccLinker<'a> {
if let Some(path) = &self.sess.opts.debugging_opts.profile_sample_use {
self.linker_arg(&format!("-plugin-opt=sample-profile={}", path.display()));
};
self.linker_arg(&format!("-plugin-opt={}", opt_level));
self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu));
self.linker_args(&[
&format!("-plugin-opt={}", opt_level),
&format!("-plugin-opt=mcpu={}", self.target_cpu),
]);
}

fn build_dylib(&mut self, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.is_like_osx {
self.cmd.arg("-dynamiclib");
if !self.is_ld {
self.cmd.arg("-dynamiclib");
}

self.linker_arg("-dylib");

// Note that the `osx_rpath_install_name` option here is a hack
// purely to support rustbuild right now, we should get a more
// principled solution at some point to force the compiler to pass
// the right `-Wl,-install_name` with an `@rpath` in it.
if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
self.linker_arg("-install_name");
let mut v = OsString::from("@rpath/");
v.push(out_filename.file_name().unwrap());
self.linker_arg(&v);
let mut rpath = OsString::from("@rpath/");
rpath.push(out_filename.file_name().unwrap());
self.linker_args(&[OsString::from("-install_name"), rpath]);
}
} else {
self.cmd.arg("-shared");
Expand Down Expand Up @@ -381,8 +402,7 @@ impl<'a> Linker for GccLinker<'a> {
self.build_dylib(out_filename);
}
LinkOutputKind::WasiReactorExe => {
self.linker_arg("--entry");
self.linker_arg("_initialize");
self.linker_args(&["--entry", "_initialize"]);
}
}
// VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
Expand Down Expand Up @@ -454,8 +474,7 @@ impl<'a> Linker for GccLinker<'a> {
self.cmd.arg(path);
}
fn full_relro(&mut self) {
self.linker_arg("-zrelro");
self.linker_arg("-znow");
self.linker_args(&["-zrelro", "-znow"]);
}
fn partial_relro(&mut self) {
self.linker_arg("-zrelro");
Expand Down Expand Up @@ -639,7 +658,6 @@ impl<'a> Linker for GccLinker<'a> {
}

let is_windows = self.sess.target.is_like_windows;
let mut arg = OsString::new();
let path = tmpdir.join(if is_windows { "list.def" } else { "list" });

debug!("EXPORTED SYMBOLS:");
Expand Down Expand Up @@ -691,27 +709,18 @@ impl<'a> Linker for GccLinker<'a> {
}

if self.sess.target.is_like_osx {
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-exported_symbols_list,");
self.linker_args(&[OsString::from("-exported_symbols_list"), path.into()]);
} else if self.sess.target.is_like_solaris {
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-M,");
self.linker_args(&[OsString::from("-M"), path.into()]);
} else {
if !self.is_ld {
arg.push("-Wl,")
}
// Both LD and LLD accept export list in *.def file form, there are no flags required
if !is_windows {
arg.push("--version-script=")
if is_windows {
self.linker_arg(path);
} else {
let mut arg = OsString::from("--version-script=");
arg.push(path);
self.linker_arg(arg);
}
}

arg.push(&path);
self.cmd.arg(arg);
}

fn subsystem(&mut self, subsystem: &str) {
Expand Down Expand Up @@ -769,8 +778,7 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_arg("--as-needed");
} else if self.sess.target.is_like_solaris {
// -z ignore is the Solaris equivalent to the GNU ld --as-needed option
self.linker_arg("-z");
self.linker_arg("ignore");
self.linker_args(&["-z", "ignore"]);
}
}
}
Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1057,20 +1057,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(dest_ptr) => dest_ptr,
};

// This checks relocation edges on the src, which needs to happen before
// `prepare_relocation_copy`.
let src_bytes = src_alloc
.get_bytes_with_uninit_and_ptr(&tcx, src_range)
.map_err(|e| e.to_interp_error(src_alloc_id))?
.as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation
// first copy the relocations to a temporary buffer, because
// `get_bytes_mut` will clear the relocations, which is correct,
// since we don't want to keep any relocations at the target.
// (`get_bytes_with_uninit_and_ptr` below checks that there are no
// relocations overlapping the edges; those would not be handled correctly).
let relocations =
src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies);
// Prepare a copy of the initialization mask.
let compressed = src_alloc.compress_uninit_range(src_range);
// This checks relocation edges on the src.
let src_bytes = src_alloc
.get_bytes_with_uninit_and_ptr(&tcx, src_range)
.map_err(|e| e.to_interp_error(src_alloc_id))?
.as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation

// Destination alloc preparations and access hooks.
let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?;
Expand Down
24 changes: 23 additions & 1 deletion compiler/rustc_index/src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,32 +118,54 @@ macro_rules! newtype_index {
}

impl $type {
/// Maximum value the index can take, as a `u32`.
$v const MAX_AS_U32: u32 = $max;

/// Maximum value the index can take.
$v const MAX: Self = Self::from_u32($max);

/// Creates a new index from a given `usize`.
///
/// # Panics
///
/// Will panic if `value` exceeds `MAX`.
#[inline]
$v const fn from_usize(value: usize) -> Self {
assert!(value <= ($max as usize));
// SAFETY: We just checked that `value <= max`.
unsafe {
Self::from_u32_unchecked(value as u32)
}
}

/// Creates a new index from a given `u32`.
///
/// # Panics
///
/// Will panic if `value` exceeds `MAX`.
#[inline]
$v const fn from_u32(value: u32) -> Self {
assert!(value <= $max);
// SAFETY: We just checked that `value <= max`.
unsafe {
Self::from_u32_unchecked(value)
}
}

/// Creates a new index from a given `u32`.
///
/// # Safety
///
/// The provided value must be less than or equal to the maximum value for the newtype.
/// Providing a value outside this range is undefined due to layout restrictions.
///
/// Prefer using `from_u32`.
#[inline]
$v const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self { private: value }
}

/// Extracts the value of this index as an integer.
/// Extracts the value of this index as a `usize`.
#[inline]
$v const fn index(self) -> usize {
self.as_usize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,36 +706,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}

let param_env = obligation.param_env;
let trait_ref = poly_trait_ref.skip_binder();

let found_ty = trait_ref.self_ty();
let found_ty_str = found_ty.to_string();
let imm_borrowed_found_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, found_ty);
let imm_substs = self.tcx.mk_substs_trait(imm_borrowed_found_ty, &[]);
let mut_borrowed_found_ty = self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, found_ty);
let mut_substs = self.tcx.mk_substs_trait(mut_borrowed_found_ty, &[]);

// Try to apply the original trait binding obligation by borrowing.
let mut try_borrowing = |new_imm_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
new_mut_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
blacklist: &[DefId]|
-> bool {
if blacklist.contains(&expected_trait_ref.def_id()) {
if blacklist.contains(&old_ref.def_id()) {
return false;
}

let imm_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
ObligationCause::dummy(),
param_env,
new_imm_trait_ref.without_const().to_predicate(self.tcx),
));

let mut_result = self.predicate_must_hold_modulo_regions(&Obligation::new(
ObligationCause::dummy(),
param_env,
new_mut_trait_ref.without_const().to_predicate(self.tcx),
));
let orig_ty = old_ref.self_ty().skip_binder();
let mk_result = |new_ty| {
let new_ref = old_ref.rebind(ty::TraitRef::new(
old_ref.def_id(),
self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]),
));
self.predicate_must_hold_modulo_regions(&Obligation::new(
ObligationCause::dummy(),
param_env,
new_ref.without_const().to_predicate(self.tcx),
))
};
let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty));
let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty));

if imm_result || mut_result {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
Expand All @@ -747,8 +740,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {

let msg = format!(
"the trait bound `{}: {}` is not satisfied",
found_ty_str,
expected_trait_ref.print_only_trait_path(),
orig_ty.to_string(),
old_ref.print_only_trait_path(),
);
if has_custom_message {
err.note(&msg);
Expand All @@ -764,7 +757,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span,
&format!(
"expected an implementor of trait `{}`",
expected_trait_ref.print_only_trait_path(),
old_ref.print_only_trait_path(),
),
);

Expand Down Expand Up @@ -807,21 +800,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
};

if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
let expected_trait_ref = obligation.parent_trait_ref;
let new_imm_trait_ref = poly_trait_ref
.rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs));
let new_mut_trait_ref = poly_trait_ref
.rebind(ty::TraitRef::new(obligation.parent_trait_ref.def_id(), mut_substs));
return try_borrowing(new_imm_trait_ref, new_mut_trait_ref, expected_trait_ref, &[]);
try_borrowing(obligation.parent_trait_ref, &[])
} else if let ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ItemObligation(_) = &*code
{
return try_borrowing(
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, imm_substs)),
poly_trait_ref.rebind(ty::TraitRef::new(trait_ref.def_id, mut_substs)),
*poly_trait_ref,
&never_suggest_borrow[..],
);
try_borrowing(*poly_trait_ref, &never_suggest_borrow[..])
} else {
false
}
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/consts/issue-miri-1910.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// error-pattern unable to turn pointer into raw bytes
#![feature(const_ptr_read)]
#![feature(const_ptr_offset)]

const C: () = unsafe {
let foo = Some(&42 as *const i32);
let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3;
(&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
};

fn main() {
}
26 changes: 26 additions & 0 deletions src/test/ui/consts/issue-miri-1910.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
error: any use of this value will cause an error
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| unable to turn pointer into raw bytes
| inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
| inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
| inside `C` at $DIR/issue-miri-1910.rs:8:5
|
::: $DIR/issue-miri-1910.rs:5:1
|
LL | / const C: () = unsafe {
LL | | let foo = Some(&42 as *const i32);
LL | | let one_and_a_half_pointers = std::mem::size_of::<*const i32>()/2*3;
LL | | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
LL | | };
| |__-
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

error: aborting due to previous error

Loading