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 8 pull requests #66121

Merged
merged 22 commits into from
Nov 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6067126
Improved MaybeUninit::get_{ref,mut} documentation
danielhenrymantilla Oct 29, 2019
539de43
Allow specifying key "llvm-abiname" in target specification
archshift Oct 30, 2019
2ebf5e6
Fix doctests
danielhenrymantilla Oct 30, 2019
d9087cb
Added a panic-on-uninhabited guard on get_ref and get_mut
danielhenrymantilla Oct 30, 2019
8971972
De-querify `trivial_dropck_outlives`.
nnethercote Nov 1, 2019
ecaa964
`Span` cannot represent `span.hi < span.lo`
petrochenkov Nov 1, 2019
981e11e
Don't double-count `simd_shuffle` promotion candidates
ecstatic-morse Nov 2, 2019
9138d3b
when Miri tests are not passing, do not add Miri component
RalfJung Nov 3, 2019
a675fd6
don't fail manifest creation if the toolstate file is missing or mal-…
RalfJung Nov 3, 2019
2cf7c29
avoid using nightly features
RalfJung Nov 4, 2019
224378c
more correct error msg
RalfJung Nov 4, 2019
1c78af7
clean highlightSourceLines code
GuillaumeGomez Nov 4, 2019
5083ade
Implemented the home_dir for VxWorks
Oct 30, 2019
67f2200
Minor style improvements
danielhenrymantilla Nov 3, 2019
54c57a2
Rollup merge of #65948 - danielhenrymantilla:doc/maybe_uninit_ref_mut…
pietroalbini Nov 5, 2019
26449f8
Rollup merge of #65953 - keystone-enclave:llvm_abiname, r=alexcrichton
pietroalbini Nov 5, 2019
b5bcb28
Rollup merge of #66012 - nnethercote:dequery-trivial_dropck_outlives,…
pietroalbini Nov 5, 2019
6ad9f56
Rollup merge of #66025 - petrochenkov:lohi, r=eddyb
pietroalbini Nov 5, 2019
80404bf
Rollup merge of #66047 - ecstatic-morse:issue-66016, r=eddyb
pietroalbini Nov 5, 2019
50035e8
Rollup merge of #66053 - RalfJung:miri-toolstate, r=pietroalbini
pietroalbini Nov 5, 2019
63e5ed3
Rollup merge of #66082 - GuillaumeGomez:cleanup-highlightsourcelines,…
pietroalbini Nov 5, 2019
135b784
Rollup merge of #66091 - Wind-River:master_xyz, r=cramertj
pietroalbini Nov 5, 2019
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ name = "build-manifest"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"toml",
]

Expand Down
167 changes: 159 additions & 8 deletions src/libcore/mem/maybe_uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,32 +509,183 @@ impl<T> MaybeUninit<T> {
self.as_ptr().read()
}

/// Gets a reference to the contained value.
/// Gets a shared reference to the contained value.
///
/// This can be useful when we want to access a `MaybeUninit` that has been
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
/// of `.assume_init()`).
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
/// Calling this when the content is not yet fully initialized causes undefined
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
/// is in an initialized state.
///
/// # Examples
///
/// ### Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
/// // Initialize `x`:
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
/// // create a shared reference to it:
/// let x: &Vec<u32> = unsafe {
/// // Safety: `x` has been initialized.
/// x.get_ref()
/// };
/// assert_eq!(x, &vec![1, 2, 3]);
/// ```
///
/// ### *Incorrect* usages of this method:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let x = MaybeUninit::<Vec<u32>>::uninit();
/// let x_vec: &Vec<u32> = unsafe { x.get_ref() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{cell::Cell, mem::MaybeUninit};
///
/// let b = MaybeUninit::<Cell<bool>>::uninit();
/// // Initialize the `MaybeUninit` using `Cell::set`:
/// unsafe {
/// b.get_ref().set(true);
/// // ^^^^^^^^^^^
/// // Reference to an uninitialized `Cell<bool>`: UB!
/// }
/// ```
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_ref(&self) -> &T {
intrinsics::panic_if_uninhabited::<T>();
&*self.value
}

/// Gets a mutable reference to the contained value.
/// Gets a mutable (unique) reference to the contained value.
///
/// This can be useful when we want to access a `MaybeUninit` that has been
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
/// of `.assume_init()`).
///
/// # Safety
///
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
/// state. Calling this when the content is not yet fully initialized causes undefined
/// behavior.
/// Calling this when the content is not yet fully initialized causes undefined
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
/// is in an initialized state. For instance, `.get_mut()` cannot be used to
/// initialize a `MaybeUninit`.
///
/// # Examples
///
/// ### Correct usage of this method:
///
/// ```rust
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] }
/// # #[cfg(FALSE)]
/// extern "C" {
/// /// Initializes *all* the bytes of the input buffer.
/// fn initialize_buffer(buf: *mut [u8; 2048]);
/// }
///
/// let mut buf = MaybeUninit::<[u8; 2048]>::uninit();
///
/// // Initialize `buf`:
/// unsafe { initialize_buffer(buf.as_mut_ptr()); }
/// // Now we know that `buf` has been initialized, so we could `.assume_init()` it.
/// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes.
/// // To assert our buffer has been initialized without copying it, we upgrade
/// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`:
/// let buf: &mut [u8; 2048] = unsafe {
/// // Safety: `buf` has been initialized.
/// buf.get_mut()
/// };
///
/// // Now we can use `buf` as a normal slice:
/// buf.sort_unstable();
/// assert!(
/// buf.chunks(2).all(|chunk| chunk[0] <= chunk[1]),
/// "buffer is sorted",
/// );
/// ```
///
/// ### *Incorrect* usages of this method:
///
/// You cannot use `.get_mut()` to initialize a value:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::mem::MaybeUninit;
///
/// let mut b = MaybeUninit::<bool>::uninit();
/// unsafe {
/// *b.get_mut() = true;
/// // We have created a (mutable) reference to an uninitialized `bool`!
/// // This is undefined behavior.
/// }
/// ```
///
/// For instance, you cannot [`Read`] into an uninitialized buffer:
///
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{io, mem::MaybeUninit};
///
/// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
/// {
/// let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
/// reader.read_exact(unsafe { buffer.get_mut() })?;
/// // ^^^^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// Ok(unsafe { buffer.assume_init() })
/// }
/// ```
///
/// Nor can you use direct field access to do field-by-field gradual initialization:
///
/// ```rust,no_run
/// #![feature(maybe_uninit_ref)]
/// use std::{mem::MaybeUninit, ptr};
///
/// struct Foo {
/// a: u32,
/// b: u8,
/// }
///
/// let foo: Foo = unsafe {
/// let mut foo = MaybeUninit::<Foo>::uninit();
/// ptr::write(&mut foo.get_mut().a as *mut u32, 1337);
/// // ^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// ptr::write(&mut foo.get_mut().b as *mut u8, 42);
/// // ^^^^^^^^^^^^^
/// // (mutable) reference to uninitialized memory!
/// // This is undefined behavior.
/// foo.assume_init()
/// };
/// ```
// FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
// a final decision about the rules before stabilization.
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
#[inline(always)]
pub unsafe fn get_mut(&mut self) -> &mut T {
intrinsics::panic_if_uninhabited::<T>();
&mut *self.value
}

Expand Down
5 changes: 0 additions & 5 deletions src/librustc/ich/hcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span {
// position that belongs to it, as opposed to hashing the first
// position past it.
let span = self.data();

if span.hi < span.lo {
return std_hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
}

let (file_lo, line_lo, col_lo) = match hcx.source_map()
.byte_pos_to_line_and_col(span.lo) {
Some(pos) => pos,
Expand Down
6 changes: 0 additions & 6 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,6 @@ rustc_queries! {
cycle_delay_bug
}

query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool {
anon
no_force
desc { "checking if `{:?}` has trivial dropck", ty }
}

query adt_dtorck_constraint(
_: DefId
) -> Result<DtorckConstraint<'tcx>, NoSolution> {}
Expand Down
16 changes: 4 additions & 12 deletions src/librustc/traits/query/dropck_outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::iter::FromIterator;
use syntax::source_map::Span;
use crate::ty::subst::GenericArg;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::query::Providers;

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

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

// (T1..Tn) and closures have same properties as T1..Tn --
// check if *any* of those are trivial.
ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())),
ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())),
ty::Closure(def_id, ref substs) => substs
.as_closure()
.upvar_tys(def_id, tcx)
.all(|t| tcx.trivial_dropck_outlives(t)),
.all(|t| trivial_dropck_outlives(tcx, t)),

ty::Adt(def, _) => {
if Some(def.did) == tcx.lang_items().manually_drop() {
Expand Down Expand Up @@ -244,10 +243,3 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
}
}

crate fn provide(p: &mut Providers<'_>) {
*p = Providers {
trivial_dropck_outlives,
..*p
};
}
4 changes: 2 additions & 2 deletions src/librustc/traits/query/type_op/outlives.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse};
use crate::traits::query::dropck_outlives::DropckOutlivesResult;
use crate::traits::query::dropck_outlives::{DropckOutlivesResult, trivial_dropck_outlives};
use crate::traits::query::Fallible;
use crate::ty::{ParamEnvAnd, Ty, TyCtxt};

Expand All @@ -21,7 +21,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
if tcx.trivial_dropck_outlives(key.value.dropped_ty) {
if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
Some(DropckOutlivesResult::default())
} else {
None
Expand Down
1 change: 0 additions & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3407,7 +3407,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
layout::provide(providers);
util::provide(providers);
constness::provide(providers);
crate::traits::query::dropck_outlives::provide(providers);
*providers = ty::query::Providers {
asyncness,
associated_item,
Expand Down
5 changes: 0 additions & 5 deletions src/librustc/ty/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,11 +796,6 @@ where
}

let span_data = span.data();

if span_data.hi < span_data.lo {
return TAG_INVALID_SPAN.encode(self);
}

let (file_lo, line_lo, col_lo) = match self.source_map
.byte_pos_to_line_and_col(span_data.lo) {
Some(pos) => pos,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea
let cpu = SmallCStr::new(llvm_util::target_cpu(sess));
let features = features.join(",");
let features = CString::new(features).unwrap();
let abi = SmallCStr::new(&sess.target.target.options.llvm_abiname);
let is_pie_binary = !find_features && is_pie_binary(sess);
let trap_unreachable = sess.target.target.options.trap_unreachable;
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
Expand All @@ -170,7 +171,7 @@ pub fn target_machine_factory(sess: &Session, optlvl: config::OptLevel, find_fea
Arc::new(move || {
let tm = unsafe {
llvm::LLVMRustCreateTargetMachine(
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), abi.as_ptr(),
code_model,
reloc_model,
opt_level,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1684,6 +1684,7 @@ extern "C" {
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char,
Features: *const c_char,
Abi: *const c_char,
Model: CodeModel,
Reloc: RelocMode,
Level: CodeGenOptLevel,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
bb: location.block,
index: 2,
});

return; // Don't double count `simd_shuffle` candidates
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,10 @@ pub struct TargetOptions {
pub merge_functions: MergeFunctions,

/// Use platform dependent mcount function
pub target_mcount: String
pub target_mcount: String,

/// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
pub llvm_abiname: String,
}

impl Default for TargetOptions {
Expand Down Expand Up @@ -880,6 +883,7 @@ impl Default for TargetOptions {
override_export_symbols: None,
merge_functions: MergeFunctions::Aliases,
target_mcount: "mcount".to_string(),
llvm_abiname: "".to_string(),
}
}
}
Expand Down Expand Up @@ -1196,6 +1200,7 @@ impl Target {
key!(override_export_symbols, opt_list);
key!(merge_functions, MergeFunctions)?;
key!(target_mcount);
key!(llvm_abiname);

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

if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_traits/dropck_outlives.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::{Canonical, QueryResponse};
use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
use rustc::traits::query::dropck_outlives::trivial_dropck_outlives;
use rustc::traits::query::{CanonicalTyGoal, NoSolution};
use rustc::traits::{TraitEngine, Normalized, ObligationCause, TraitEngineExt};
use rustc::ty::query::Providers;
Expand Down Expand Up @@ -172,7 +173,7 @@ fn dtorck_constraint_for_ty<'tcx>(
return Ok(());
}

if tcx.trivial_dropck_outlives(ty) {
if trivial_dropck_outlives(tcx, ty) {
return Ok(());
}

Expand Down
Loading