diff --git a/Cargo.lock b/Cargo.lock index 46480aeb4476d..873f5da053787 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -208,6 +208,7 @@ name = "build-manifest" version = "0.1.0" dependencies = [ "serde", + "serde_json", "toml", ] diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 792ce9dfad419..51ba260589f62 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -509,32 +509,183 @@ impl MaybeUninit { 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` 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` 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::>::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 = 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::>::uninit(); + /// let x_vec: &Vec = 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::>::uninit(); + /// // Initialize the `MaybeUninit` using `Cell::set`: + /// unsafe { + /// b.get_ref().set(true); + /// // ^^^^^^^^^^^ + /// // Reference to an uninitialized `Cell`: UB! + /// } + /// ``` #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { + intrinsics::panic_if_uninhabited::(); &*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` 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` 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::::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::::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::(); &mut *self.value } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 957dab39414f0..a5b131520c243 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -309,11 +309,6 @@ impl<'a> HashStable> 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, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 86ed2419e048b..12ae2c3201547 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -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, NoSolution> {} diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index e84c91daf293f..eaf5971e4592f 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -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 @@ -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![], @@ -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() { @@ -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 - }; -} diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs index 86a32d68fc09e..81c3857cbf8d8 100644 --- a/src/librustc/traits/query/type_op/outlives.rs +++ b/src/librustc/traits/query/type_op/outlives.rs @@ -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}; @@ -21,7 +21,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if tcx.trivial_dropck_outlives(key.value.dropped_ty) { + if trivial_dropck_outlives(tcx, key.value.dropped_ty) { Some(DropckOutlivesResult::default()) } else { None diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 60028f2488a33..1b1cc423fd457 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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, diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 21a7cf00b283f..4dabea01c9e46 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -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, diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 52f3a1cbb5c30..fa14ce7b03c8c 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -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; @@ -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, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 72b0a7d640a48..4dad6ff793c9e 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -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, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 83f3aafc55cb1..f5e49e3283406 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -199,6 +199,8 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { bb: location.block, index: 2, }); + + return; // Don't double count `simd_shuffle` candidates } } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 6033d52c44112..e51772220b73f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -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 { @@ -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(), } } } @@ -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()) { @@ -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() diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index c1316f415a559..d77ec3010f4b7 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -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; @@ -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(()); } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index de19ca3ed333a..53e16978ff12b 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -163,59 +163,71 @@ function getSearchElement() { var main = document.getElementById("main"); - function highlightSourceLines(ev) { - // If we're in mobile mode, we should add the sidebar in any case. + function onHashChange(ev) { + // If we're in mobile mode, we should hide the sidebar in any case. hideSidebar(); - var elem; - var search = getSearchElement(); - var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); + var match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { - from = parseInt(match[1], 10); - to = from; - if (typeof match[2] !== "undefined") { - to = parseInt(match[2], 10); - } - if (to < from) { - var tmp = to; - to = from; - from = tmp; - } - elem = document.getElementById(from); - if (!elem) { - return; - } - if (ev === null) { - var x = document.getElementById(from); - if (x) { - x.scrollIntoView(); - } - } - onEachLazy(document.getElementsByClassName("line-numbers"), function(e) { - onEachLazy(e.getElementsByTagName("span"), function(i_e) { - removeClass(i_e, "line-highlighted"); - }); - }); - for (i = from; i <= to; ++i) { - elem = document.getElementById(i); - if (!elem) { - break; - } - addClass(elem, "line-highlighted"); - } - } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { + return highlightSourceLines(match, ev); + } + var search = getSearchElement(); + if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { addClass(search, "hidden"); removeClass(main, "hidden"); var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1); if (browserSupportsHistoryApi()) { history.replaceState(hash, "", "?search=#" + hash); } - elem = document.getElementById(hash); + var elem = document.getElementById(hash); if (elem) { elem.scrollIntoView(); } } } + function highlightSourceLines(match, ev) { + if (typeof match === "undefined") { + // If we're in mobile mode, we should hide the sidebar in any case. + hideSidebar(); + match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); + } + if (!match) { + return; + } + var from = parseInt(match[1], 10); + var to = from; + if (typeof match[2] !== "undefined") { + to = parseInt(match[2], 10); + } + if (to < from) { + var tmp = to; + to = from; + from = tmp; + } + var elem = document.getElementById(from); + if (!elem) { + return; + } + if (!ev) { + var x = document.getElementById(from); + if (x) { + x.scrollIntoView(); + } + } + onEachLazy(document.getElementsByClassName("line-numbers"), function(e) { + onEachLazy(e.getElementsByTagName("span"), function(i_e) { + removeClass(i_e, "line-highlighted"); + }); + }); + for (var i = from; i <= to; ++i) { + elem = document.getElementById(i); + if (!elem) { + break; + } + addClass(elem, "line-highlighted"); + } + } + function expandSection(id) { var elem = document.getElementById(id); if (elem && isHidden(elem)) { @@ -234,8 +246,8 @@ function getSearchElement() { } } - highlightSourceLines(null); - window.onhashchange = highlightSourceLines; + highlightSourceLines(); + window.onhashchange = onHashChange; // Gets the human-readable string for the virtual-key code of the // given KeyboardEvent, ev. @@ -358,7 +370,7 @@ function getSearchElement() { var set_fragment = function(name) { if (browserSupportsHistoryApi()) { history.replaceState(null, null, "#" + name); - highlightSourceLines(null); + highlightSourceLines(); } else { location.replace("#" + name); } diff --git a/src/libstd/sys/vxworks/os.rs b/src/libstd/sys/vxworks/os.rs index f4798da1876cf..baa6c425d2e7f 100644 --- a/src/libstd/sys/vxworks/os.rs +++ b/src/libstd/sys/vxworks/os.rs @@ -287,7 +287,8 @@ pub fn temp_dir() -> PathBuf { } pub fn home_dir() -> Option { - None + crate::env::var_os("HOME").or_else(|| None + ).map(PathBuf::from) } pub fn exit(code: i32) -> ! { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 48cf117f65ae6..e2a7ea28b9b59 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -68,7 +68,7 @@ impl<'a> StringReader<'a> { let end = sess.source_map().lookup_byte_offset(span.hi()); // Make the range zero-length if the span is invalid. - if span.lo() > span.hi() || begin.sf.start_pos != end.sf.start_pos { + if begin.sf.start_pos != end.sf.start_pos { span = span.shrink_to_lo(); } diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index d7760e0cf9ee4..d9f618602a40b 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -498,10 +498,6 @@ impl SourceMap { pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { debug!("span_to_lines(sp={:?})", sp); - if sp.lo() > sp.hi() { - return Err(SpanLinesError::IllFormedSpan(sp)); - } - let lo = self.lookup_char_pos(sp.lo()); debug!("span_to_lines: lo={:?}", lo); let hi = self.lookup_char_pos(sp.hi()); @@ -549,10 +545,6 @@ impl SourceMap { fn span_to_source(&self, sp: Span, extract_source: F) -> Result where F: Fn(&str, usize, usize) -> Result { - if sp.lo() > sp.hi() { - return Err(SpanSnippetError::IllFormedSpan(sp)); - } - let local_begin = self.lookup_byte_offset(sp.lo()); let local_end = self.lookup_byte_offset(sp.hi()); @@ -762,14 +754,14 @@ impl SourceMap { /// Finds the width of a character, either before or after the provided span. fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 { - // Disregard malformed spans and assume a one-byte wide character. - if sp.lo() >= sp.hi() { - debug!("find_width_of_character_at_span: early return malformed span"); + let sp = sp.data(); + if sp.lo == sp.hi { + debug!("find_width_of_character_at_span: early return empty span"); return 1; } - let local_begin = self.lookup_byte_offset(sp.lo()); - let local_end = self.lookup_byte_offset(sp.hi()); + let local_begin = self.lookup_byte_offset(sp.lo); + let local_end = self.lookup_byte_offset(sp.hi); debug!("find_width_of_character_at_span: local_begin=`{:?}`, local_end=`{:?}`", local_begin, local_end); diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9034f8c1afd1b..dc29b189639ce 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -1512,7 +1512,6 @@ pub type FileLinesResult = Result; #[derive(Clone, PartialEq, Eq, Debug)] pub enum SpanLinesError { - IllFormedSpan(Span), DistinctSources(DistinctSources), } diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 0cda3465dc093..5b3900ab49611 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -343,7 +343,7 @@ extern "C" const char* LLVMRustGetHostCPUName(size_t *len) { extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( const char *TripleStr, const char *CPU, const char *Feature, - LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, + const char *ABIStr, LLVMRustCodeModel RustCM, LLVMRustRelocMode RustReloc, LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat, bool PositionIndependentExecutable, bool FunctionSections, bool DataSections, @@ -374,6 +374,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( Options.FunctionSections = FunctionSections; Options.MCOptions.AsmVerbose = AsmComments; Options.MCOptions.PreserveAsmComments = AsmComments; + Options.MCOptions.ABIName = ABIStr; if (TrapUnreachable) { // Tell LLVM to codegen `unreachable` into an explicit trap instruction. diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index c364479d8db13..0bbbabd29989e 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" [dependencies] toml = "0.5" serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index fca57eec79fc6..d92924085e7c7 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -11,10 +11,11 @@ use serde::Serialize; use std::collections::BTreeMap; use std::env; -use std::fs; +use std::fs::{self, File}; use std::io::{self, Read, Write}; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; +use std::collections::HashMap; static HOSTS: &[&str] = &[ "aarch64-unknown-linux-gnu", @@ -366,6 +367,7 @@ impl Builder { self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu"); self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu"); + self.check_toolstate(); self.digest_and_sign(); let manifest = self.build_manifest(); self.write_channel_files(&self.rust_release, &manifest); @@ -375,6 +377,25 @@ impl Builder { } } + /// If a tool does not pass its tests, don't ship it. + /// Right now, we do this only for Miri. + fn check_toolstate(&mut self) { + let toolstates: Option> = + File::open(self.input.join("toolstates-linux.json")).ok() + .and_then(|f| serde_json::from_reader(&f).ok()); + let toolstates = toolstates.unwrap_or_else(|| { + println!("WARNING: `toolstates-linux.json` missing/malformed; \ + assuming all tools failed"); + HashMap::default() // Use empty map if anything went wrong. + }); + // Mark some tools as missing based on toolstate. + if toolstates.get("miri").map(|s| &*s as &str) != Some("test-pass") { + println!("Miri tests are not passing, removing component"); + self.miri_version = None; + self.miri_git_commit_hash = None; + } + } + /// Hash all files, compute their signatures, and collect the hashes in `self.digests`. fn digest_and_sign(&mut self) { for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {