Auto merge of #67091 - JohnTitor:rollup-kitphze, r=JohnTitor
Rollup of 11 pull requests Successful merges: - #66846 (Make try_mark_previous_green aware of cycles.) - #66959 (Remove potential cfgs duplicates) - #66988 (Fix angle bracket formatting when dumping MIR debug vars) - #66998 (Modified the testcases for VxWorks) - #67008 (rustdoc: Add test for fixed issue) - #67023 (SGX: Fix target linker used by bootstrap) - #67033 (Migrate to LLVM{Get,Set}ValueName2) - #67049 (Simplify {IoSlice, IoSliceMut}::advance examples and tests) - #67054 (codegen "unreachable" for invalid SetDiscriminant) - #67081 (Fix Query type docs) - #67085 (Remove boxed closures in address parser.) Failed merges: r? @ghost
This commit is contained in:
commit
9630dbbc3c
23 changed files with 214 additions and 101 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<String, FromUtf8Error> {
|
||||
let sr = RustString {
|
||||
bytes: RefCell::new(Vec::new()),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
||||
result: RefCell<Option<Result<T>>>,
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ impl<T> Query<T> {
|
|||
}
|
||||
|
||||
/// 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()
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ fn write_graph_label<'tcx, W: Write>(
|
|||
}
|
||||
|
||||
for var_debug_info in &body.var_debug_info {
|
||||
write!(w, r#"debug {} => {};<br align="left"/>"#,
|
||||
write!(w, r#"debug {} => {};<br align="left"/>"#,
|
||||
var_debug_info.name, escape(&var_debug_info.place))?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T>(
|
||||
&mut self,
|
||||
parsers: &mut [Box<dyn FnMut(&mut Parser<'_>) -> Option<T> + 'static>],
|
||||
) -> Option<T> {
|
||||
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<A, B, C, PA, PB, PC>(&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<IpAddr> {
|
||||
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<SocketAddrV4> {
|
||||
|
|
@ -268,9 +254,8 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<GlobalObject>(V);
|
||||
if (!TargetTriple.isOSBinFormatMachO()) {
|
||||
GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
|
||||
StringRef NameRef(Name, NameLen);
|
||||
GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
43
src/test/codegen/set-discriminant-invalid.rs
Normal file
43
src/test/codegen/set-discriminant-invalid.rs
Normal file
|
|
@ -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<Error> 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<E>
|
||||
{
|
||||
/// The underlying error
|
||||
type Source;
|
||||
|
||||
/// Combine the information to produce the error
|
||||
fn into_error(self, source: Self::Source) -> E;
|
||||
}
|
||||
15
src/test/incremental/issue-61323.rs
Normal file
15
src/test/incremental/issue-61323.rs
Normal file
|
|
@ -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<A>);
|
||||
|
||||
#[cfg(cfail)]
|
||||
struct C(A);
|
||||
//[cfail]~^ ERROR 12:1: 12:13: recursive type `C` has infinite size [E0072]
|
||||
|
||||
fn main() {}
|
||||
4
src/test/rustdoc-ui/issue-61732.rs
Normal file
4
src/test/rustdoc-ui/issue-61732.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// This previously triggered an ICE.
|
||||
|
||||
pub(in crate::r#mod) fn main() {}
|
||||
//~^ ERROR expected module, found unresolved item
|
||||
11
src/test/rustdoc-ui/issue-61732.stderr
Normal file
11
src/test/rustdoc-ui/issue-61732.stderr
Normal file
|
|
@ -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`.
|
||||
15
src/test/rustdoc/duplicate-cfg.rs
Normal file
15
src/test/rustdoc/duplicate-cfg.rs
Normal file
|
|
@ -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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue