diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 39d7ea922bced..7ea2bb126a641 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -810,6 +810,7 @@ impl Build { !target.contains("emscripten") && !target.contains("wasm32") && !target.contains("nvptx") && + !target.contains("fortanix") && !target.contains("fuchsia") { Some(self.cc(target)) } else { diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0104507f7020f..d952bf7ab9e25 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -710,14 +710,25 @@ impl DepGraph { return None } None => { - if !tcx.sess.has_errors() { + if !tcx.sess.has_errors_or_delayed_span_bugs() { bug!("try_mark_previous_green() - Forcing the DepNode \ should have set its color") } else { - // If the query we just forced has resulted - // in some kind of compilation error, we - // don't expect that the corresponding - // dep-node color has been updated. + // If the query we just forced has resulted in + // some kind of compilation error, we cannot rely on + // the dep-node color having been properly updated. + // This means that the query system has reached an + // invalid state. We let the compiler continue (by + // returning `None`) so it can emit error messages + // and wind down, but rely on the fact that this + // invalid state will not be persisted to the + // incremental compilation cache because of + // compilation errors being present. + debug!("try_mark_previous_green({:?}) - END - \ + dependency {:?} resulted in compilation error", + dep_node, + dep_dep_node); + return None } } } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index a05ba9c78e0d2..ada29c350ad04 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -22,7 +22,7 @@ use rustc_fs_util::{path_to_c_string, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use errors::{Handler, FatalError}; -use std::ffi::{CString, CStr}; +use std::ffi::CString; use std::fs; use std::io::{self, Write}; use std::path::{Path, PathBuf}; @@ -833,8 +833,8 @@ fn create_msvc_imps( }) .filter_map(|val| { // Exclude some symbols that we know are not Rust symbols. - let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); - if ignored(name.to_bytes()) { + let name = llvm::get_value_name(val); + if ignored(name) { None } else { Some((val, name)) @@ -842,7 +842,7 @@ fn create_msvc_imps( }) .map(move |(val, name)| { let mut imp_name = prefix.as_bytes().to_vec(); - imp_name.extend(name.to_bytes()); + imp_name.extend(name); let imp_name = CString::new(imp_name).unwrap(); (imp_name, val) }) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 541b3d9476b33..297aff93a9d28 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -21,7 +21,7 @@ use rustc::ty::layout::{self, Size, Align, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; -use std::ffi::{CStr, CString}; +use std::ffi::CStr; pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); @@ -392,16 +392,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { } else { // If we created the global with the wrong type, // correct the type. - let empty_string = const_cstr!(""); - let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g)); - let name_string = CString::new(name_str_ref.to_bytes()).unwrap(); - llvm::LLVMSetValueName(g, empty_string.as_ptr()); + let name = llvm::get_value_name(g).to_vec(); + llvm::set_value_name(g, b""); let linkage = llvm::LLVMRustGetLinkage(g); let visibility = llvm::LLVMRustGetVisibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( - self.llmod, name_string.as_ptr(), val_llty); + self.llmod, name.as_ptr().cast(), name.len(), val_llty); llvm::LLVMRustSetLinkage(new_g, linkage); llvm::LLVMRustSetVisibility(new_g, visibility); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index c2359a2fe6d94..a3782ecd92dcd 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -32,7 +32,7 @@ use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope, use libc::c_uint; use std::cell::RefCell; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use smallvec::SmallVec; use syntax_pos::{self, BytePos, Span, Pos}; @@ -255,23 +255,11 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } - let old_name = unsafe { - CStr::from_ptr(llvm::LLVMGetValueName(value)) - }; - match old_name.to_str() { - Ok("") => {} - Ok(_) => { - // Avoid replacing the name if it already exists. - // While we could combine the names somehow, it'd - // get noisy quick, and the usefulness is dubious. - return; - } - Err(_) => return, - } - - let cname = SmallCStr::new(name); - unsafe { - llvm::LLVMSetValueName(value, cname.as_ptr()); + // Avoid replacing the name if it already exists. + // While we could combine the names somehow, it'd + // get noisy quick, and the usefulness is dubious. + if llvm::get_value_name(value).is_empty() { + llvm::set_value_name(value, name.as_bytes()); } } } diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 8b6fedc87db96..fa9fc46536801 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -76,9 +76,8 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> { name: &str, ty: &'ll Type ) -> &'ll Value { debug!("declare_global(name={:?})", name); - let namebuf = SmallCStr::new(name); unsafe { - llvm::LLVMRustGetOrInsertGlobal(self.llmod, namebuf.as_ptr(), ty) + llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 5362d180d1b78..5da3275e28e8b 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -701,8 +701,8 @@ extern "C" { // Operations on all values pub fn LLVMTypeOf(Val: &Value) -> &Type; - pub fn LLVMGetValueName(Val: &Value) -> *const c_char; - pub fn LLVMSetValueName(Val: &Value, Name: *const c_char); + pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char; + pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); @@ -774,7 +774,8 @@ extern "C" { pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; - pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value; + pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, NameLen: size_t, + T: &'a Type) -> &'a Value; pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value; pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; @@ -1811,7 +1812,7 @@ extern "C" { pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); - pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char); + pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); pub fn LLVMRustUnsetComdat(V: &Value); pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index 57815933af02b..d2d4187623981 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -115,7 +115,8 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { // For more details on COMDAT sections see e.g., http://www.airs.com/blog/archives/52 pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { unsafe { - LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); + let name = get_value_name(val); + LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); } } @@ -217,6 +218,23 @@ pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { } } +/// Safe wrapper for `LLVMGetValueName2` into a byte slice +pub fn get_value_name(value: &'a Value) -> &'a [u8] { + unsafe { + let mut len = 0; + let data = LLVMGetValueName2(value, &mut len); + std::slice::from_raw_parts(data.cast(), len) + } +} + +/// Safe wrapper for `LLVMSetValueName2` from a byte slice +pub fn set_value_name(value: &Value, name: &[u8]) { + unsafe { + let data = name.as_ptr().cast(); + LLVMSetValueName2(value, data, name.len()); + } +} + pub fn build_string(f: impl FnOnce(&RustString)) -> Result { let sr = RustString { bytes: RefCell::new(Vec::new()), diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 6dccf329c9f64..ce703f2433506 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -261,7 +261,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.ret.layout.abi.is_uninhabited() { // Functions with uninhabited return values are marked `noreturn`, // so we should make sure that we never actually do. + // We play it safe by using a well-defined `abort`, but we could go for immediate UB + // if that turns out to be helpful. bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. bx.unreachable(); return; } @@ -825,6 +829,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::TerminatorKind::Abort => { bx.abort(); + // `abort` does not terminate the block, so we still need to generate + // an `unreachable` terminator after it. bx.unreachable(); } diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 310b8aeb4db09..a6dec81274915 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -475,9 +475,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }, } // Allow RalfJ to sleep soundly knowing that even refactorings that remove - // the above error (or silence it under some conditions) will not cause UB + // the above error (or silence it under some conditions) will not cause UB. bx.abort(); - // We've errored, so we don't have to produce working code. + // We still have to return an operand but it doesn't matter, + // this code is unreachable. let ty = self.monomorphize(&constant.literal.ty); let layout = bx.cx().layout_of(ty); bx.load_operand(PlaceRef::new_sized( diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index e2507394ce681..e60b8861faf85 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -333,6 +333,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { variant_index: VariantIdx ) { if self.layout.for_variant(bx.cx(), variant_index).abi.is_uninhabited() { + // We play it safe by using a well-defined `abort`, but we could go for immediate UB + // if that turns out to be helpful. + bx.abort(); return; } match self.layout.variants { @@ -488,10 +491,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }, Err(_) => { // This is unreachable as long as runtime - // and compile-time agree on values + // and compile-time agree perfectly. // With floats that won't always be true, - // so we generate an abort. + // so we generate a (safe) abort. bx.abort(); + // We still have to return a place but it doesn't matter, + // this code is unreachable. let llval = bx.cx().const_undef( bx.cx().type_ptr_to(bx.cx().backend_type(layout)) ); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 6103d42c5dbcb..d1fbb949fb164 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -22,7 +22,7 @@ use std::mem; use syntax::{self, ast}; /// Represent the result of a query. -/// This result can be stolen with the `take` method and returned with the `give` method. +/// This result can be stolen with the `take` method and generated with the `compute` method. pub struct Query { result: RefCell>>, } @@ -37,7 +37,7 @@ impl Query { } /// Takes ownership of the query result. Further attempts to take or peek the query - /// result will panic unless it is returned by calling the `give` method. + /// result will panic unless it is generated by calling the `compute` method. pub fn take(&self) -> T { self.result .borrow_mut() diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 3a7ec9f038aa5..a44d4014b42ee 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -202,7 +202,7 @@ fn write_graph_label<'tcx, W: Write>( } for var_debug_info in &body.var_debug_info { - write!(w, r#"debug {} => {};
"#, + write!(w, r#"debug {} => {};
"#, var_debug_info.name, escape(&var_debug_info.place))?; } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 078948cc63bd2..fb2cce3683132 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -209,6 +209,9 @@ impl ops::Not for Cfg { impl ops::BitAndAssign for Cfg { fn bitand_assign(&mut self, other: Cfg) { + if *self == other { + return; + } match (self, other) { (&mut Cfg::False, _) | (_, Cfg::True) => {}, (s, Cfg::False) => *s = Cfg::False, @@ -238,6 +241,9 @@ impl ops::BitAnd for Cfg { impl ops::BitOrAssign for Cfg { fn bitor_assign(&mut self, other: Cfg) { + if *self == other { + return; + } match (self, other) { (&mut Cfg::True, _) | (_, Cfg::False) => {}, (s, Cfg::True) => *s = Cfg::True, diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index e5cf022f0444e..a109e38e1e3bc 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2339,8 +2339,10 @@ mod tests { let filename = &tmpdir.join("file_that_does_not_exist.txt"); let result = File::open(filename); - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "vxworks")))] error!(result, "No such file or directory"); + #[cfg(target_os = "vxworks")] + error!(result, "no such file or directory"); #[cfg(windows)] error!(result, 2); // ERROR_FILE_NOT_FOUND } @@ -2352,8 +2354,10 @@ mod tests { let result = fs::remove_file(filename); - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "vxworks")))] error!(result, "No such file or directory"); + #[cfg(target_os = "vxworks")] + error!(result, "no such file or directory"); #[cfg(windows)] error!(result, 2); // ERROR_FILE_NOT_FOUND } @@ -2553,7 +2557,10 @@ mod tests { check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777))); let metadata1 = check!(fs::metadata(filename)); + #[cfg(all(unix, not(target_os = "vxworks")))] assert_eq!(mask & metadata1.permissions().mode(), 0o1777); + #[cfg(target_os = "vxworks")] + assert_eq!(mask & metadata1.permissions().mode(), 0o0777); } #[test] diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 20c1c5cd1b8ad..a1a33bade0d7c 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -987,7 +987,6 @@ impl<'a> IoSliceMut<'a> { /// #![feature(io_slice_advance)] /// /// use std::io::IoSliceMut; - /// use std::mem; /// use std::ops::Deref; /// /// let mut buf1 = [1; 8]; @@ -1000,7 +999,7 @@ impl<'a> IoSliceMut<'a> { /// ][..]; /// /// // Mark 10 bytes as read. - /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10); + /// bufs = IoSliceMut::advance(bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); /// ``` @@ -1090,20 +1089,19 @@ impl<'a> IoSlice<'a> { /// #![feature(io_slice_advance)] /// /// use std::io::IoSlice; - /// use std::mem; /// use std::ops::Deref; /// - /// let mut buf1 = [1; 8]; - /// let mut buf2 = [2; 16]; - /// let mut buf3 = [3; 8]; + /// let buf1 = [1; 8]; + /// let buf2 = [2; 16]; + /// let buf3 = [3; 8]; /// let mut bufs = &mut [ - /// IoSlice::new(&mut buf1), - /// IoSlice::new(&mut buf2), - /// IoSlice::new(&mut buf3), + /// IoSlice::new(&buf1), + /// IoSlice::new(&buf2), + /// IoSlice::new(&buf3), /// ][..]; /// /// // Mark 10 bytes as written. - /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10); + /// bufs = IoSlice::advance(bufs, 10); /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); #[unstable(feature = "io_slice_advance", issue = "62726")] @@ -2415,7 +2413,6 @@ mod tests { use crate::cmp; use crate::io::prelude::*; use crate::io::{self, IoSlice, IoSliceMut}; - use crate::mem; use crate::ops::Deref; #[test] @@ -2731,26 +2728,26 @@ mod tests { ][..]; // Only in a single buffer.. - bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 1); + bufs = IoSliceMut::advance(bufs, 1); assert_eq!(bufs[0].deref(), [1; 7].as_ref()); assert_eq!(bufs[1].deref(), [2; 16].as_ref()); assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // Removing a buffer, leaving others as is. - bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 7); + bufs = IoSliceMut::advance(bufs, 7); assert_eq!(bufs[0].deref(), [2; 16].as_ref()); assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // Removing a buffer and removing from the next buffer. - bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 18); + bufs = IoSliceMut::advance(bufs, 18); assert_eq!(bufs[0].deref(), [3; 6].as_ref()); } #[test] fn io_slice_mut_advance_empty_slice() { - let mut empty_bufs = &mut [][..]; + let empty_bufs = &mut [][..]; // Shouldn't panic. - IoSliceMut::advance(&mut empty_bufs, 1); + IoSliceMut::advance(empty_bufs, 1); } #[test] @@ -2759,48 +2756,48 @@ mod tests { let mut bufs = &mut [IoSliceMut::new(&mut buf1)][..]; // Going beyond the total length should be ok. - bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 9); + bufs = IoSliceMut::advance(bufs, 9); assert!(bufs.is_empty()); } #[test] fn io_slice_advance() { - let mut buf1 = [1; 8]; - let mut buf2 = [2; 16]; - let mut buf3 = [3; 8]; + let buf1 = [1; 8]; + let buf2 = [2; 16]; + let buf3 = [3; 8]; let mut bufs = - &mut [IoSlice::new(&mut buf1), IoSlice::new(&mut buf2), IoSlice::new(&mut buf3)][..]; + &mut [IoSlice::new(&buf1), IoSlice::new(&buf2), IoSlice::new(&buf3)][..]; // Only in a single buffer.. - bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 1); + bufs = IoSlice::advance(bufs, 1); assert_eq!(bufs[0].deref(), [1; 7].as_ref()); assert_eq!(bufs[1].deref(), [2; 16].as_ref()); assert_eq!(bufs[2].deref(), [3; 8].as_ref()); // Removing a buffer, leaving others as is. - bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 7); + bufs = IoSlice::advance(bufs, 7); assert_eq!(bufs[0].deref(), [2; 16].as_ref()); assert_eq!(bufs[1].deref(), [3; 8].as_ref()); // Removing a buffer and removing from the next buffer. - bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 18); + bufs = IoSlice::advance(bufs, 18); assert_eq!(bufs[0].deref(), [3; 6].as_ref()); } #[test] fn io_slice_advance_empty_slice() { - let mut empty_bufs = &mut [][..]; + let empty_bufs = &mut [][..]; // Shouldn't panic. - IoSlice::advance(&mut empty_bufs, 1); + IoSlice::advance(empty_bufs, 1); } #[test] fn io_slice_advance_beyond_total_length() { - let mut buf1 = [1; 8]; - let mut bufs = &mut [IoSlice::new(&mut buf1)][..]; + let buf1 = [1; 8]; + let mut bufs = &mut [IoSlice::new(&buf1)][..]; // Going beyond the total length should be ok. - bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 9); + bufs = IoSlice::advance(bufs, 9); assert!(bufs.is_empty()); } } diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index 8106d1c3315aa..686fa8c61a109 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -44,19 +44,6 @@ impl<'a> Parser<'a> { self.read_atomically(move |p| cb(p).filter(|_| p.is_eof())) } - // Return result of first successful parser - fn read_or( - &mut self, - parsers: &mut [Box) -> Option + 'static>], - ) -> Option { - for pf in parsers { - if let Some(r) = self.read_atomically(|p: &mut Parser<'_>| pf(p)) { - return Some(r); - } - } - None - } - // Apply 3 parsers sequentially fn read_seq_3(&mut self, pa: PA, pb: PB, pc: PC) -> Option<(A, B, C)> where @@ -235,9 +222,8 @@ impl<'a> Parser<'a> { } fn read_ip_addr(&mut self) -> Option { - let ipv4_addr = |p: &mut Parser<'_>| p.read_ipv4_addr().map(IpAddr::V4); - let ipv6_addr = |p: &mut Parser<'_>| p.read_ipv6_addr().map(IpAddr::V6); - self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)]) + self.read_ipv4_addr().map(IpAddr::V4) + .or_else(|| self.read_ipv6_addr().map(IpAddr::V6)) } fn read_socket_addr_v4(&mut self) -> Option { @@ -268,9 +254,8 @@ impl<'a> Parser<'a> { } fn read_socket_addr(&mut self) -> Option { - let v4 = |p: &mut Parser<'_>| p.read_socket_addr_v4().map(SocketAddr::V4); - let v6 = |p: &mut Parser<'_>| p.read_socket_addr_v6().map(SocketAddr::V6); - self.read_or(&mut [Box::new(v4), Box::new(v6)]) + self.read_socket_addr_v4().map(SocketAddr::V4) + .or_else(|| self.read_socket_addr_v6().map(SocketAddr::V6)) } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index a83ba9a8f1308..720928e48e382 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -129,8 +129,9 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, } extern "C" LLVMValueRef -LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) { - return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty))); +LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { + StringRef NameRef(Name, NameLen); + return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty))); } extern "C" LLVMValueRef @@ -1287,11 +1288,12 @@ extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, } extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, - const char *Name) { + const char *Name, size_t NameLen) { Triple TargetTriple(unwrap(M)->getTargetTriple()); GlobalObject *GV = unwrap(V); if (!TargetTriple.isOSBinFormatMachO()) { - GV->setComdat(unwrap(M)->getOrInsertComdat(Name)); + StringRef NameRef(Name, NameLen); + GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef)); } } diff --git a/src/test/codegen/set-discriminant-invalid.rs b/src/test/codegen/set-discriminant-invalid.rs new file mode 100644 index 0000000000000..d9614f062b7e9 --- /dev/null +++ b/src/test/codegen/set-discriminant-invalid.rs @@ -0,0 +1,43 @@ +// compile-flags: -C opt-level=0 +#![crate_type = "lib"] + +pub enum ApiError {} +#[allow(dead_code)] +pub struct TokioError { + b: bool, +} +pub enum Error { + Api { + source: ApiError, + }, + Ethereum, + Tokio { + source: TokioError, + }, +} +struct Api; +impl IntoError for Api +{ + type Source = ApiError; + // CHECK-LABEL: @into_error + // CHECK: llvm.trap() + // Also check the next two instructions to make sure we do not match against `trap` + // elsewhere in the code. + // CHECK-NEXT: load + // CHECK-NEXT: ret + #[no_mangle] + fn into_error(self, error: Self::Source) -> Error { + Error::Api { + source: (|v| v)(error), + } + } +} + +pub trait IntoError +{ + /// The underlying error + type Source; + + /// Combine the information to produce the error + fn into_error(self, source: Self::Source) -> E; +} diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs new file mode 100644 index 0000000000000..448ce367b8c6b --- /dev/null +++ b/src/test/incremental/issue-61323.rs @@ -0,0 +1,15 @@ +// revisions: rpass cfail + +enum A { + //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072] + B(C), +} + +#[cfg(rpass)] +struct C(Box); + +#[cfg(cfail)] +struct C(A); +//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072] + +fn main() {} diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs new file mode 100644 index 0000000000000..d4835c092248e --- /dev/null +++ b/src/test/rustdoc-ui/issue-61732.rs @@ -0,0 +1,4 @@ +// This previously triggered an ICE. + +pub(in crate::r#mod) fn main() {} +//~^ ERROR expected module, found unresolved item diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr new file mode 100644 index 0000000000000..6c8ba48864df0 --- /dev/null +++ b/src/test/rustdoc-ui/issue-61732.stderr @@ -0,0 +1,11 @@ +error[E0577]: expected module, found unresolved item `crate::r#mod` + --> $DIR/issue-61732.rs:3:8 + | +LL | pub(in crate::r#mod) fn main() {} + | ^^^^^^^^^^^^ not a module + +error: Compilation failed, aborting rustdoc + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0577`. diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs new file mode 100644 index 0000000000000..505d6ee769ab3 --- /dev/null +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -0,0 +1,15 @@ +#![crate_name = "foo"] +#![feature(doc_cfg)] + +// @has 'foo/index.html' +// @!has '-' '//*[@class="stab portability"]' 'feature="sync" and' +// @has '-' '//*[@class="stab portability"]' 'feature="sync"' +#[doc(cfg(feature = "sync"))] +#[doc(cfg(feature = "sync"))] +pub struct Foo; + +#[doc(cfg(feature = "sync"))] +pub mod bar { + #[doc(cfg(feature = "sync"))] + pub struct Bar; +}