Skip to content

Commit 1423bec

Browse files
committed
Auto merge of #66121 - pietroalbini:rollup-8zrwe7l, r=pietroalbini
Rollup of 8 pull requests Successful merges: - #65948 (Improve MaybeUninit::get_{ref,mut} documentation) - #65953 (Allow specifying LLVM's MCTargetOptions::ABIName in target specification files) - #66012 (De-querify `trivial_dropck_outlives`.) - #66025 (`Span` cannot represent `span.hi < span.lo`) - #66047 (Don't double-count `simd_shuffle` promotion candidates) - #66053 (when Miri tests are not passing, do not add Miri component) - #66082 (clean highlightSourceLines code) - #66091 (Implemented the home_dir for VxWorks) Failed merges: r? @ghost
2 parents 3a1b3b3 + 135b784 commit 1423bec

File tree

21 files changed

+267
-102
lines changed

21 files changed

+267
-102
lines changed

Diff for: Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ name = "build-manifest"
208208
version = "0.1.0"
209209
dependencies = [
210210
"serde",
211+
"serde_json",
211212
"toml",
212213
]
213214

Diff for: src/libcore/mem/maybe_uninit.rs

+159-8
Original file line numberDiff line numberDiff line change
@@ -509,32 +509,183 @@ impl<T> MaybeUninit<T> {
509509
self.as_ptr().read()
510510
}
511511

512-
/// Gets a reference to the contained value.
512+
/// Gets a shared reference to the contained value.
513+
///
514+
/// This can be useful when we want to access a `MaybeUninit` that has been
515+
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
516+
/// of `.assume_init()`).
513517
///
514518
/// # Safety
515519
///
516-
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
517-
/// state. Calling this when the content is not yet fully initialized causes undefined
518-
/// behavior.
520+
/// Calling this when the content is not yet fully initialized causes undefined
521+
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
522+
/// is in an initialized state.
523+
///
524+
/// # Examples
525+
///
526+
/// ### Correct usage of this method:
527+
///
528+
/// ```rust
529+
/// #![feature(maybe_uninit_ref)]
530+
/// use std::mem::MaybeUninit;
531+
///
532+
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
533+
/// // Initialize `x`:
534+
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
535+
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
536+
/// // create a shared reference to it:
537+
/// let x: &Vec<u32> = unsafe {
538+
/// // Safety: `x` has been initialized.
539+
/// x.get_ref()
540+
/// };
541+
/// assert_eq!(x, &vec![1, 2, 3]);
542+
/// ```
543+
///
544+
/// ### *Incorrect* usages of this method:
545+
///
546+
/// ```rust,no_run
547+
/// #![feature(maybe_uninit_ref)]
548+
/// use std::mem::MaybeUninit;
549+
///
550+
/// let x = MaybeUninit::<Vec<u32>>::uninit();
551+
/// let x_vec: &Vec<u32> = unsafe { x.get_ref() };
552+
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
553+
/// ```
554+
///
555+
/// ```rust,no_run
556+
/// #![feature(maybe_uninit_ref)]
557+
/// use std::{cell::Cell, mem::MaybeUninit};
558+
///
559+
/// let b = MaybeUninit::<Cell<bool>>::uninit();
560+
/// // Initialize the `MaybeUninit` using `Cell::set`:
561+
/// unsafe {
562+
/// b.get_ref().set(true);
563+
/// // ^^^^^^^^^^^
564+
/// // Reference to an uninitialized `Cell<bool>`: UB!
565+
/// }
566+
/// ```
519567
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
520568
#[inline(always)]
521569
pub unsafe fn get_ref(&self) -> &T {
570+
intrinsics::panic_if_uninhabited::<T>();
522571
&*self.value
523572
}
524573

525-
/// Gets a mutable reference to the contained value.
574+
/// Gets a mutable (unique) reference to the contained value.
575+
///
576+
/// This can be useful when we want to access a `MaybeUninit` that has been
577+
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
578+
/// of `.assume_init()`).
526579
///
527580
/// # Safety
528581
///
529-
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
530-
/// state. Calling this when the content is not yet fully initialized causes undefined
531-
/// behavior.
582+
/// Calling this when the content is not yet fully initialized causes undefined
583+
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
584+
/// is in an initialized state. For instance, `.get_mut()` cannot be used to
585+
/// initialize a `MaybeUninit`.
586+
///
587+
/// # Examples
588+
///
589+
/// ### Correct usage of this method:
590+
///
591+
/// ```rust
592+
/// #![feature(maybe_uninit_ref)]
593+
/// use std::mem::MaybeUninit;
594+
///
595+
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] }
596+
/// # #[cfg(FALSE)]
597+
/// extern "C" {
598+
/// /// Initializes *all* the bytes of the input buffer.
599+
/// fn initialize_buffer(buf: *mut [u8; 2048]);
600+
/// }
601+
///
602+
/// let mut buf = MaybeUninit::<[u8; 2048]>::uninit();
603+
///
604+
/// // Initialize `buf`:
605+
/// unsafe { initialize_buffer(buf.as_mut_ptr()); }
606+
/// // Now we know that `buf` has been initialized, so we could `.assume_init()` it.
607+
/// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes.
608+
/// // To assert our buffer has been initialized without copying it, we upgrade
609+
/// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`:
610+
/// let buf: &mut [u8; 2048] = unsafe {
611+
/// // Safety: `buf` has been initialized.
612+
/// buf.get_mut()
613+
/// };
614+
///
615+
/// // Now we can use `buf` as a normal slice:
616+
/// buf.sort_unstable();
617+
/// assert!(
618+
/// buf.chunks(2).all(|chunk| chunk[0] <= chunk[1]),
619+
/// "buffer is sorted",
620+
/// );
621+
/// ```
622+
///
623+
/// ### *Incorrect* usages of this method:
624+
///
625+
/// You cannot use `.get_mut()` to initialize a value:
626+
///
627+
/// ```rust,no_run
628+
/// #![feature(maybe_uninit_ref)]
629+
/// use std::mem::MaybeUninit;
630+
///
631+
/// let mut b = MaybeUninit::<bool>::uninit();
632+
/// unsafe {
633+
/// *b.get_mut() = true;
634+
/// // We have created a (mutable) reference to an uninitialized `bool`!
635+
/// // This is undefined behavior.
636+
/// }
637+
/// ```
638+
///
639+
/// For instance, you cannot [`Read`] into an uninitialized buffer:
640+
///
641+
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
642+
///
643+
/// ```rust,no_run
644+
/// #![feature(maybe_uninit_ref)]
645+
/// use std::{io, mem::MaybeUninit};
646+
///
647+
/// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
648+
/// {
649+
/// let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
650+
/// reader.read_exact(unsafe { buffer.get_mut() })?;
651+
/// // ^^^^^^^^^^^^^^^^
652+
/// // (mutable) reference to uninitialized memory!
653+
/// // This is undefined behavior.
654+
/// Ok(unsafe { buffer.assume_init() })
655+
/// }
656+
/// ```
657+
///
658+
/// Nor can you use direct field access to do field-by-field gradual initialization:
659+
///
660+
/// ```rust,no_run
661+
/// #![feature(maybe_uninit_ref)]
662+
/// use std::{mem::MaybeUninit, ptr};
663+
///
664+
/// struct Foo {
665+
/// a: u32,
666+
/// b: u8,
667+
/// }
668+
///
669+
/// let foo: Foo = unsafe {
670+
/// let mut foo = MaybeUninit::<Foo>::uninit();
671+
/// ptr::write(&mut foo.get_mut().a as *mut u32, 1337);
672+
/// // ^^^^^^^^^^^^^
673+
/// // (mutable) reference to uninitialized memory!
674+
/// // This is undefined behavior.
675+
/// ptr::write(&mut foo.get_mut().b as *mut u8, 42);
676+
/// // ^^^^^^^^^^^^^
677+
/// // (mutable) reference to uninitialized memory!
678+
/// // This is undefined behavior.
679+
/// foo.assume_init()
680+
/// };
681+
/// ```
532682
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
533683
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
534684
// a final decision about the rules before stabilization.
535685
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
536686
#[inline(always)]
537687
pub unsafe fn get_mut(&mut self) -> &mut T {
688+
intrinsics::panic_if_uninhabited::<T>();
538689
&mut *self.value
539690
}
540691

Diff for: src/librustc/ich/hcx.rs

-5
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
309309
// position that belongs to it, as opposed to hashing the first
310310
// position past it.
311311
let span = self.data();
312-
313-
if span.hi < span.lo {
314-
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
315-
}
316-
317312
let (file_lo, line_lo, col_lo) = match hcx.source_map()
318313
.byte_pos_to_line_and_col(span.lo) {
319314
Some(pos) => pos,

Diff for: src/librustc/query/mod.rs

-6
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,6 @@ rustc_queries! {
228228
cycle_delay_bug
229229
}
230230

231-
query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool {
232-
anon
233-
no_force
234-
desc { "checking if `{:?}` has trivial dropck", ty }
235-
}
236-
237231
query adt_dtorck_constraint(
238232
_: DefId
239233
) -> Result<DtorckConstraint<'tcx>, NoSolution> {}

Diff for: src/librustc/traits/query/dropck_outlives.rs

+4-12
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use std::iter::FromIterator;
55
use syntax::source_map::Span;
66
use crate::ty::subst::GenericArg;
77
use crate::ty::{self, Ty, TyCtxt};
8-
use crate::ty::query::Providers;
98

109
impl<'cx, 'tcx> At<'cx, 'tcx> {
1110
/// Given a type `ty` of some value being dropped, computes a set
@@ -34,7 +33,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> {
3433
// Quick check: there are a number of cases that we know do not require
3534
// any destructor.
3635
let tcx = self.infcx.tcx;
37-
if tcx.trivial_dropck_outlives(ty) {
36+
if trivial_dropck_outlives(tcx, ty) {
3837
return InferOk {
3938
value: vec![],
4039
obligations: vec![],
@@ -208,15 +207,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
208207
| ty::Error => true,
209208

210209
// [T; N] and [T] have same properties as T.
211-
ty::Array(ty, _) | ty::Slice(ty) => tcx.trivial_dropck_outlives(ty),
210+
ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty),
212211

213212
// (T1..Tn) and closures have same properties as T1..Tn --
214213
// check if *any* of those are trivial.
215-
ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())),
214+
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
216215
ty::Closure(def_id, ref substs) => substs
217216
.as_closure()
218217
.upvar_tys(def_id, tcx)
219-
.all(|t| tcx.trivial_dropck_outlives(t)),
218+
.all(|t| trivial_dropck_outlives(tcx, t)),
220219

221220
ty::Adt(def, _) => {
222221
if Some(def.did) == tcx.lang_items().manually_drop() {
@@ -244,10 +243,3 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
244243
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
245244
}
246245
}
247-
248-
crate fn provide(p: &mut Providers<'_>) {
249-
*p = Providers {
250-
trivial_dropck_outlives,
251-
..*p
252-
};
253-
}

Diff for: src/librustc/traits/query/type_op/outlives.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
2-
use crate::traits::query::dropck_outlives::DropckOutlivesResult;
2+
use crate::traits::query::dropck_outlives::{DropckOutlivesResult, trivial_dropck_outlives};
33
use crate::traits::query::Fallible;
44
use crate::ty::{ParamEnvAnd, Ty, TyCtxt};
55

@@ -21,7 +21,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
2121
tcx: TyCtxt<'tcx>,
2222
key: &ParamEnvAnd<'tcx, Self>,
2323
) -> Option<Self::QueryResponse> {
24-
if tcx.trivial_dropck_outlives(key.value.dropped_ty) {
24+
if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
2525
Some(DropckOutlivesResult::default())
2626
} else {
2727
None

Diff for: src/librustc/ty/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3407,7 +3407,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
34073407
layout::provide(providers);
34083408
util::provide(providers);
34093409
constness::provide(providers);
3410-
crate::traits::query::dropck_outlives::provide(providers);
34113410
*providers = ty::query::Providers {
34123411
asyncness,
34133412
associated_item,

Diff for: src/librustc/ty/query/on_disk_cache.rs

-5
Original file line numberDiff line numberDiff line change
@@ -796,11 +796,6 @@ where
796796
}
797797

798798
let span_data = span.data();
799-
800-
if span_data.hi < span_data.lo {
801-
return TAG_INVALID_SPAN.encode(self);
802-
}
803-
804799
let (file_lo, line_lo, col_lo) = match self.source_map
805800
.byte_pos_to_line_and_col(span_data.lo) {
806801
Some(pos) => pos,

Diff for: src/librustc_codegen_llvm/back/write.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea
161161
let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
162162
let features = features.join(",");
163163
let features = CString::new(features).unwrap();
164+
let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
164165
let is_pie_binary = !find_features && is_pie_binary(sess);
165166
let trap_unreachable = sess.target.target.options.trap_unreachable;
166167
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
@@ -170,7 +171,7 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea
170171
Arc::new(move || {
171172
let tm = unsafe {
172173
llvm::LLVMRustCreateTargetMachine(
173-
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
174+
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), abi.as_ptr(),
174175
code_model,
175176
reloc_model,
176177
opt_level,

Diff for: src/librustc_codegen_llvm/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1684,6 +1684,7 @@ extern "C" {
16841684
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
16851685
CPU: *const c_char,
16861686
Features: *const c_char,
1687+
Abi: *const c_char,
16871688
Model: CodeModel,
16881689
Reloc: RelocMode,
16891690
Level: CodeGenOptLevel,

Diff for: src/librustc_mir/transform/promote_consts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
199199
bb: location.block,
200200
index: 2,
201201
});
202+
203+
return; // Don't double count `simd_shuffle` candidates
202204
}
203205
}
204206

Diff for: src/librustc_target/spec/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,10 @@ pub struct TargetOptions {
793793
pub merge_functions: MergeFunctions,
794794

795795
/// Use platform dependent mcount function
796-
pub target_mcount: String
796+
pub target_mcount: String,
797+
798+
/// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
799+
pub llvm_abiname: String,
797800
}
798801

799802
impl Default for TargetOptions {
@@ -880,6 +883,7 @@ impl Default for TargetOptions {
880883
override_export_symbols: None,
881884
merge_functions: MergeFunctions::Aliases,
882885
target_mcount: "mcount".to_string(),
886+
llvm_abiname: "".to_string(),
883887
}
884888
}
885889
}
@@ -1196,6 +1200,7 @@ impl Target {
11961200
key!(override_export_symbols, opt_list);
11971201
key!(merge_functions, MergeFunctions)?;
11981202
key!(target_mcount);
1203+
key!(llvm_abiname);
11991204

12001205
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
12011206
for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1414,6 +1419,7 @@ impl ToJson for Target {
14141419
target_option_val!(override_export_symbols);
14151420
target_option_val!(merge_functions);
14161421
target_option_val!(target_mcount);
1422+
target_option_val!(llvm_abiname);
14171423

14181424
if default.abi_blacklist != self.options.abi_blacklist {
14191425
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()

Diff for: src/librustc_traits/dropck_outlives.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc::hir::def_id::DefId;
22
use rustc::infer::canonical::{Canonical, QueryResponse};
33
use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
4+
use rustc::traits::query::dropck_outlives::trivial_dropck_outlives;
45
use rustc::traits::query::{CanonicalTyGoal, NoSolution};
56
use rustc::traits::{TraitEngine, Normalized, ObligationCause, TraitEngineExt};
67
use rustc::ty::query::Providers;
@@ -172,7 +173,7 @@ fn dtorck_constraint_for_ty<'tcx>(
172173
return Ok(());
173174
}
174175

175-
if tcx.trivial_dropck_outlives(ty) {
176+
if trivial_dropck_outlives(tcx, ty) {
176177
return Ok(());
177178
}
178179

0 commit comments

Comments
 (0)