mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #135525 - jhpratt:rollup-4gu2wpm, r=jhpratt
Rollup of 7 pull requests Successful merges: - #132397 (Make missing_abi lint warn-by-default.) - #133807 (ci: Enable opt-dist for dist-aarch64-linux builds) - #134143 (Convert `struct FromBytesWithNulError` into enum) - #134338 (Use a C-safe return type for `__rust_[ui]128_*` overflowing intrinsics) - #134678 (Update `ReadDir::next` in `std::sys::pal::unix::fs` to use `&raw const (*p).field` instead of `p.byte_offset().cast()`) - #135424 (Detect unstable lint docs that dont enable their feature) - #135520 (Make sure we actually use the right trivial lifetime substs when eagerly monomorphizing drop for ADTs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
2776bdfe42
@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
-compiler_builtins = { version = "=0.1.141", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.141", features = ['rustc-dep-of-std', 'no-f16-f128'] }
|
||||
-compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std', 'no-f16-f128'] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
|
||||
|
@ -76,20 +76,22 @@ pub(crate) fn maybe_codegen_mul_checked<'tcx>(
|
||||
}
|
||||
|
||||
let is_signed = type_sign(lhs.layout().ty);
|
||||
|
||||
let out_ty = Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]);
|
||||
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
|
||||
let oflow_out_place = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32));
|
||||
let param_types = vec![
|
||||
AbiParam::special(fx.pointer_type, ArgumentPurpose::StructReturn),
|
||||
AbiParam::new(types::I128),
|
||||
AbiParam::new(types::I128),
|
||||
AbiParam::special(fx.pointer_type, ArgumentPurpose::Normal),
|
||||
];
|
||||
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)];
|
||||
fx.lib_call(
|
||||
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx), oflow_out_place.to_ptr().get_addr(fx)];
|
||||
let ret = fx.lib_call(
|
||||
if is_signed { "__rust_i128_mulo" } else { "__rust_u128_mulo" },
|
||||
param_types,
|
||||
vec![],
|
||||
vec![AbiParam::new(types::I128)],
|
||||
&args,
|
||||
);
|
||||
Some(out_place.to_cvalue(fx))
|
||||
let mul = ret[0];
|
||||
let oflow = oflow_out_place.to_cvalue(fx).load_scalar(fx);
|
||||
let oflow = clif_intcast(fx, oflow, types::I8, false);
|
||||
let layout = fx.layout_of(Ty::new_tup(fx.tcx, &[lhs.layout().ty, fx.tcx.types.bool]));
|
||||
Some(CValue::by_val_pair(mul, oflow, layout))
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ builtin_functions! {
|
||||
fn __divti3(n: i128, d: i128) -> i128;
|
||||
fn __umodti3(n: u128, d: u128) -> u128;
|
||||
fn __modti3(n: i128, d: i128) -> i128;
|
||||
fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool);
|
||||
fn __rust_u128_mulo(a: u128, b: u128, oflow: &mut i32) -> u128;
|
||||
|
||||
// floats
|
||||
fn __floattisf(i: i128) -> f32;
|
||||
|
@ -689,7 +689,7 @@ impl<T> Index<usize> for [T] {
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type VaListImpl;
|
||||
}
|
||||
|
||||
|
@ -258,13 +258,13 @@ fn main() {
|
||||
|
||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
||||
{
|
||||
extern {
|
||||
extern "C" {
|
||||
#[linkage = "weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![allow(internal_features)]
|
||||
|
||||
#[link(name = "c")]
|
||||
extern {}
|
||||
extern "C" {}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! {
|
||||
|
@ -7,7 +7,7 @@ use std::arch::x86_64::*;
|
||||
use std::io::Write;
|
||||
use std::ops::Coroutine;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
|
||||
|
@ -322,36 +322,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match new_kind {
|
||||
Int(I128) | Uint(U128) => {
|
||||
let func_name = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => "__rust_i128_addo",
|
||||
Uint(U128) => "__rust_u128_addo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => "__rust_i128_subo",
|
||||
Uint(U128) => "__rust_u128_subo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => "__rust_u128_mulo",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs);
|
||||
}
|
||||
_ => match oop {
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => "__mulosi4",
|
||||
Int(I64) => "__mulodi4",
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unimplemented!("overflow operation for {:?}", new_kind),
|
||||
let (func_name, width) = match oop {
|
||||
OverflowOp::Add => match new_kind {
|
||||
Int(I128) => ("__rust_i128_addo", 128),
|
||||
Uint(U128) => ("__rust_u128_addo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}
|
||||
OverflowOp::Sub => match new_kind {
|
||||
Int(I128) => ("__rust_i128_subo", 128),
|
||||
Uint(U128) => ("__rust_u128_subo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
OverflowOp::Mul => match new_kind {
|
||||
Int(I32) => ("__mulosi4", 32),
|
||||
Int(I64) => ("__mulodi4", 64),
|
||||
Int(I128) => ("__rust_i128_mulo", 128), // TODO(antoyo): use __muloti4d instead?
|
||||
Uint(U128) => ("__rust_u128_mulo", 128),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
return self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
};
|
||||
|
||||
let intrinsic = self.context.get_builtin_function(name);
|
||||
@ -364,80 +354,87 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
(res.dereference(self.location).to_rvalue(), overflow)
|
||||
}
|
||||
|
||||
/// Non-`__builtin_*` overflow operations with a `fn(T, T, &mut i32) -> T` signature.
|
||||
pub fn operation_with_overflow(
|
||||
&self,
|
||||
func_name: &str,
|
||||
lhs: RValue<'gcc>,
|
||||
rhs: RValue<'gcc>,
|
||||
width: u64,
|
||||
) -> (RValue<'gcc>, RValue<'gcc>) {
|
||||
let a_type = lhs.get_type();
|
||||
let b_type = rhs.get_type();
|
||||
debug_assert!(a_type.dyncast_array().is_some());
|
||||
debug_assert!(b_type.dyncast_array().is_some());
|
||||
let overflow_type = self.i32_type;
|
||||
let overflow_param_type = overflow_type.make_pointer();
|
||||
let res_type = a_type;
|
||||
|
||||
let overflow_value =
|
||||
self.current_func().new_local(self.location, overflow_type, "overflow");
|
||||
let overflow_addr = overflow_value.get_address(self.location);
|
||||
|
||||
let param_a = self.context.new_parameter(self.location, a_type, "a");
|
||||
let param_b = self.context.new_parameter(self.location, b_type, "b");
|
||||
let result_field = self.context.new_field(self.location, a_type, "result");
|
||||
let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
|
||||
let param_overflow =
|
||||
self.context.new_parameter(self.location, overflow_param_type, "overflow");
|
||||
|
||||
let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
|
||||
let a_elem_type = a_type.dyncast_array().expect("non-array a value");
|
||||
debug_assert!(a_elem_type.is_integral());
|
||||
let res_ty = match width {
|
||||
32 => self.tcx.types.i32,
|
||||
64 => self.tcx.types.i64,
|
||||
128 => self.tcx.types.i128,
|
||||
_ => unreachable!("unexpected integer size"),
|
||||
};
|
||||
let layout = self
|
||||
.tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ret_ty))
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(res_ty))
|
||||
.unwrap();
|
||||
|
||||
let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
|
||||
let mut fn_abi = FnAbi {
|
||||
args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
args: vec![arg_abi.clone(), arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
|
||||
ret: arg_abi,
|
||||
c_variadic: false,
|
||||
fixed_count: 2,
|
||||
fixed_count: 3,
|
||||
conv: Conv::C,
|
||||
can_unwind: false,
|
||||
};
|
||||
fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap();
|
||||
|
||||
let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
let result = if ret_indirect {
|
||||
let res_value = self.current_func().new_local(self.location, res_type, "result_value");
|
||||
let res_addr = res_value.get_address(self.location);
|
||||
let res_param_type = res_type.make_pointer();
|
||||
let param_res = self.context.new_parameter(self.location, res_param_type, "result");
|
||||
|
||||
let return_type = self
|
||||
.context
|
||||
.new_struct_type(self.location, "result_overflow", &[result_field, overflow_field]);
|
||||
let result = if indirect {
|
||||
let return_value =
|
||||
self.current_func().new_local(self.location, return_type.as_type(), "return_value");
|
||||
let return_param_type = return_type.as_type().make_pointer();
|
||||
let return_param =
|
||||
self.context.new_parameter(self.location, return_param_type, "return_value");
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
self.type_void(),
|
||||
&[return_param, param_a, param_b],
|
||||
&[param_res, param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.llbb().add_eval(
|
||||
self.location,
|
||||
self.context.new_call(self.location, func, &[
|
||||
return_value.get_address(self.location),
|
||||
lhs,
|
||||
rhs,
|
||||
]),
|
||||
);
|
||||
return_value.to_rvalue()
|
||||
let _void =
|
||||
self.context.new_call(self.location, func, &[res_addr, lhs, rhs, overflow_addr]);
|
||||
res_value.to_rvalue()
|
||||
} else {
|
||||
let func = self.context.new_function(
|
||||
self.location,
|
||||
FunctionType::Extern,
|
||||
return_type.as_type(),
|
||||
&[param_a, param_b],
|
||||
res_type,
|
||||
&[param_a, param_b, param_overflow],
|
||||
func_name,
|
||||
false,
|
||||
);
|
||||
self.context.new_call(self.location, func, &[lhs, rhs])
|
||||
self.context.new_call(self.location, func, &[lhs, rhs, overflow_addr])
|
||||
};
|
||||
let overflow = result.access_field(self.location, overflow_field);
|
||||
let int_result = result.access_field(self.location, result_field);
|
||||
(int_result, overflow)
|
||||
|
||||
(result, self.context.new_cast(self.location, overflow_value, self.bool_type).to_rvalue())
|
||||
}
|
||||
|
||||
pub fn gcc_icmp(
|
||||
|
@ -1001,7 +1001,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
128 => "__rust_i128_addo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
@ -1071,7 +1072,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
128 => "__rust_i128_subo",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
|
||||
let (int_result, overflow) =
|
||||
self.operation_with_overflow(func_name, lhs, rhs, width);
|
||||
self.llbb().add_assignment(self.location, res, int_result);
|
||||
overflow
|
||||
};
|
||||
|
@ -3597,7 +3597,7 @@ declare_lint! {
|
||||
///
|
||||
/// [Other ABIs]: https://doc.rust-lang.org/reference/items/external-blocks.html#abi
|
||||
pub MISSING_ABI,
|
||||
Allow,
|
||||
Warn,
|
||||
"No declared ABI for extern declaration"
|
||||
}
|
||||
|
||||
|
@ -1410,19 +1410,33 @@ impl<'v> RootCollector<'_, 'v> {
|
||||
&& !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx)
|
||||
{
|
||||
debug!("RootCollector: ADT drop-glue for `{id:?}`",);
|
||||
let id_args =
|
||||
ty::GenericArgs::for_item(self.tcx, id.owner_id.to_def_id(), |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
self.tcx.lifetimes.re_erased.into()
|
||||
}
|
||||
GenericParamDefKind::Type { .. }
|
||||
| GenericParamDefKind::Const { .. } => {
|
||||
unreachable!(
|
||||
"`own_requires_monomorphization` check means that \
|
||||
we should have no type/const params"
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This type is impossible to instantiate, so we should not try to
|
||||
// generate a `drop_in_place` instance for it.
|
||||
if self.tcx.instantiate_and_check_impossible_predicates((
|
||||
id.owner_id.to_def_id(),
|
||||
ty::List::empty(),
|
||||
id_args,
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ty = self.tcx.erase_regions(
|
||||
self.tcx.type_of(id.owner_id.to_def_id()).instantiate_identity(),
|
||||
);
|
||||
let ty =
|
||||
self.tcx.type_of(id.owner_id.to_def_id()).instantiate(self.tcx, id_args);
|
||||
assert!(!ty.has_non_region_param());
|
||||
visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
|
||||
}
|
||||
|
@ -804,7 +804,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> {
|
||||
#[inline(never)]
|
||||
fn region_param_out_of_range(&self, ebr: I::EarlyParamRegion, r: I::Region) -> ! {
|
||||
panic!(
|
||||
"const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
|
||||
"region parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}",
|
||||
ebr,
|
||||
r,
|
||||
ebr.index(),
|
||||
|
@ -61,9 +61,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiler_builtins"
|
||||
version = "0.1.141"
|
||||
version = "0.1.143"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e7a0206befe4e574e37d6d7a0fe82e88fdf54bedb0608f239cb11b7a6aa6be"
|
||||
checksum = "c85ba2077e3eab3dd81be4ece6b7fb2ad0887c1fb813e9a45400baf75c6c7c29"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"rustc-std-workspace-core",
|
||||
|
@ -10,7 +10,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
compiler_builtins = { version = "=0.1.141", features = ['rustc-dep-of-std'] }
|
||||
compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
|
||||
|
@ -124,37 +124,25 @@ pub struct CStr {
|
||||
///
|
||||
/// let _: FromBytesWithNulError = CStr::from_bytes_with_nul(b"f\0oo").unwrap_err();
|
||||
/// ```
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "core_c_str", since = "1.64.0")]
|
||||
pub struct FromBytesWithNulError {
|
||||
kind: FromBytesWithNulErrorKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
enum FromBytesWithNulErrorKind {
|
||||
InteriorNul(usize),
|
||||
pub enum FromBytesWithNulError {
|
||||
/// Data provided contains an interior nul byte at byte `position`.
|
||||
InteriorNul {
|
||||
/// The position of the interior nul byte.
|
||||
position: usize,
|
||||
},
|
||||
/// Data provided is not nul terminated.
|
||||
NotNulTerminated,
|
||||
}
|
||||
|
||||
// FIXME: const stability attributes should not be required here, I think
|
||||
impl FromBytesWithNulError {
|
||||
const fn interior_nul(pos: usize) -> FromBytesWithNulError {
|
||||
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
|
||||
}
|
||||
const fn not_nul_terminated() -> FromBytesWithNulError {
|
||||
FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
|
||||
impl Error for FromBytesWithNulError {
|
||||
#[allow(deprecated)]
|
||||
fn description(&self) -> &str {
|
||||
match self.kind {
|
||||
FromBytesWithNulErrorKind::InteriorNul(..) => {
|
||||
"data provided contains an interior nul byte"
|
||||
}
|
||||
FromBytesWithNulErrorKind::NotNulTerminated => "data provided is not nul terminated",
|
||||
match self {
|
||||
Self::InteriorNul { .. } => "data provided contains an interior nul byte",
|
||||
Self::NotNulTerminated => "data provided is not nul terminated",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,8 +187,8 @@ impl fmt::Display for FromBytesWithNulError {
|
||||
#[allow(deprecated, deprecated_in_future)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.description())?;
|
||||
if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
|
||||
write!(f, " at byte pos {pos}")?;
|
||||
if let Self::InteriorNul { position } = self {
|
||||
write!(f, " at byte pos {position}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -349,25 +337,25 @@ impl CStr {
|
||||
/// use std::ffi::CStr;
|
||||
///
|
||||
/// let cstr = CStr::from_bytes_with_nul(b"hello\0");
|
||||
/// assert!(cstr.is_ok());
|
||||
/// assert_eq!(cstr, Ok(c"hello"));
|
||||
/// ```
|
||||
///
|
||||
/// Creating a `CStr` without a trailing nul terminator is an error:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::ffi::{CStr, FromBytesWithNulError};
|
||||
///
|
||||
/// let cstr = CStr::from_bytes_with_nul(b"hello");
|
||||
/// assert!(cstr.is_err());
|
||||
/// assert_eq!(cstr, Err(FromBytesWithNulError::NotNulTerminated));
|
||||
/// ```
|
||||
///
|
||||
/// Creating a `CStr` with an interior nul byte is an error:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::ffi::{CStr, FromBytesWithNulError};
|
||||
///
|
||||
/// let cstr = CStr::from_bytes_with_nul(b"he\0llo\0");
|
||||
/// assert!(cstr.is_err());
|
||||
/// assert_eq!(cstr, Err(FromBytesWithNulError::InteriorNul { position: 2 }));
|
||||
/// ```
|
||||
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
|
||||
#[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
|
||||
@ -379,8 +367,8 @@ impl CStr {
|
||||
// of the byte slice.
|
||||
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
|
||||
}
|
||||
Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)),
|
||||
None => Err(FromBytesWithNulError::not_nul_terminated()),
|
||||
Some(position) => Err(FromBytesWithNulError::InteriorNul { position }),
|
||||
None => Err(FromBytesWithNulError::NotNulTerminated),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
panic_unwind = { path = "../panic_unwind", optional = true }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
core = { path = "../core", public = true }
|
||||
compiler_builtins = { version = "=0.1.141" }
|
||||
compiler_builtins = { version = "=0.1.143" }
|
||||
unwind = { path = "../unwind" }
|
||||
hashbrown = { version = "0.15", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
|
@ -709,7 +709,7 @@ impl Iterator for ReadDir {
|
||||
// thread safety for readdir() as long an individual DIR* is not accessed
|
||||
// concurrently, which is sufficient for Rust.
|
||||
super::os::set_errno(0);
|
||||
let entry_ptr = readdir64(self.inner.dirp.0);
|
||||
let entry_ptr: *const dirent64 = readdir64(self.inner.dirp.0);
|
||||
if entry_ptr.is_null() {
|
||||
// We either encountered an error, or reached the end. Either way,
|
||||
// the next call to next() should return None.
|
||||
@ -735,29 +735,19 @@ impl Iterator for ReadDir {
|
||||
// contents were "simply" partially initialized data.
|
||||
//
|
||||
// Like for uninitialized contents, converting entry_ptr to `&dirent64`
|
||||
// would not be legal. However, unique to dirent64 is that we don't even
|
||||
// get to use `&raw const (*entry_ptr).d_name` because that operation
|
||||
// requires the full extent of *entry_ptr to be in bounds of the same
|
||||
// allocation, which is not necessarily the case here.
|
||||
//
|
||||
// Instead we must access fields individually through their offsets.
|
||||
macro_rules! offset_ptr {
|
||||
($entry_ptr:expr, $field:ident) => {{
|
||||
const OFFSET: isize = mem::offset_of!(dirent64, $field) as isize;
|
||||
if true {
|
||||
// Cast to the same type determined by the else branch.
|
||||
$entry_ptr.byte_offset(OFFSET).cast::<_>()
|
||||
} else {
|
||||
#[allow(deref_nullptr)]
|
||||
{
|
||||
&raw const (*ptr::null::<dirent64>()).$field
|
||||
}
|
||||
}
|
||||
}};
|
||||
// would not be legal. However, we can use `&raw const (*entry_ptr).d_name`
|
||||
// to refer the fields individually, because that operation is equivalent
|
||||
// to `byte_offset` and thus does not require the full extent of `*entry_ptr`
|
||||
// to be in bounds of the same allocation, only the offset of the field
|
||||
// being referenced.
|
||||
macro_rules! entry_field_ptr {
|
||||
($field:ident) => {
|
||||
&raw const (*entry_ptr).$field
|
||||
};
|
||||
}
|
||||
|
||||
// d_name is guaranteed to be null-terminated.
|
||||
let name = CStr::from_ptr(offset_ptr!(entry_ptr, d_name).cast());
|
||||
let name = CStr::from_ptr(entry_field_ptr!(d_name).cast());
|
||||
let name_bytes = name.to_bytes();
|
||||
if name_bytes == b"." || name_bytes == b".." {
|
||||
continue;
|
||||
@ -765,14 +755,14 @@ impl Iterator for ReadDir {
|
||||
|
||||
#[cfg(not(target_os = "vita"))]
|
||||
let entry = dirent64_min {
|
||||
d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
|
||||
d_ino: *entry_field_ptr!(d_ino) as u64,
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "aix",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
|
||||
d_type: *entry_field_ptr!(d_type) as u8,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "vita")]
|
||||
|
@ -91,9 +91,12 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--set rust.debug-assertions=false \
|
||||
--set rust.jemalloc \
|
||||
--set rust.use-lld=true \
|
||||
--set rust.lto=thin \
|
||||
--set rust.codegen-units=1
|
||||
|
||||
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
|
||||
./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
|
||||
--host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap
|
||||
|
||||
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang
|
||||
ENV LIBCURL_NO_PKG_CONFIG 1
|
||||
|
@ -173,6 +173,7 @@ mod issue_3739 {
|
||||
/// This shouldn't warn for `boxed_local` as it is intended to called from non-Rust code.
|
||||
pub extern "C" fn do_not_warn_me(_c_pointer: Box<String>) -> () {}
|
||||
|
||||
#[allow(missing_abi)]
|
||||
#[rustfmt::skip] // Forces rustfmt to not add ABI
|
||||
pub extern fn do_not_warn_me_no_abi(_c_pointer: Box<String>) -> () {}
|
||||
|
||||
|
@ -14,13 +14,13 @@ LL | pub fn new(_needs_name: Box<PeekableSeekable<&()>>) -> () {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: local variable doesn't need to be boxed here
|
||||
--> tests/ui/boxed_local.rs:188:44
|
||||
--> tests/ui/boxed_local.rs:189:44
|
||||
|
|
||||
LL | fn default_impl_x(self: Box<Self>, x: Box<u32>) -> u32 {
|
||||
| ^
|
||||
|
||||
error: local variable doesn't need to be boxed here
|
||||
--> tests/ui/boxed_local.rs:196:16
|
||||
--> tests/ui/boxed_local.rs:197:16
|
||||
|
|
||||
LL | fn foo(x: Box<u32>) {}
|
||||
| ^
|
||||
|
@ -240,7 +240,7 @@ fn parenthesized_word() {}
|
||||
/// UXes
|
||||
fn plural_acronym_test() {}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
/// `foo()`
|
||||
fn in_extern();
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ fn parenthesized_word() {}
|
||||
/// UXes
|
||||
fn plural_acronym_test() {}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
/// foo()
|
||||
fn in_extern();
|
||||
}
|
||||
|
@ -149,6 +149,7 @@ mod msrv {
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(missing_abi)]
|
||||
const extern fn implicit_c() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
|
@ -149,6 +149,7 @@ mod msrv {
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(missing_abi)]
|
||||
extern fn implicit_c() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
|
@ -222,7 +222,7 @@ LL | const extern "C" fn c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:152:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
|
||||
|
|
||||
LL | extern fn implicit_c() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -233,7 +233,7 @@ LL | const extern fn implicit_c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:169:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
|
||||
|
|
||||
LL | / pub fn new(strings: Vec<String>) -> Self {
|
||||
LL | | Self { strings }
|
||||
@ -246,7 +246,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:174:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
|
||||
|
|
||||
LL | / pub fn empty() -> Self {
|
||||
LL | | Self { strings: Vec::new() }
|
||||
@ -259,7 +259,7 @@ LL | pub const fn empty() -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:185:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
|
||||
|
|
||||
LL | / pub fn new(text: String) -> Self {
|
||||
LL | | let vec = Vec::new();
|
||||
@ -273,7 +273,7 @@ LL | pub const fn new(text: String) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:204:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
|
||||
|
|
||||
LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -284,7 +284,7 @@ LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:208:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:209:5
|
||||
|
|
||||
LL | extern "C-unwind" fn c_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -295,7 +295,7 @@ LL | const extern "C-unwind" fn c_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:211:5
|
||||
|
|
||||
LL | extern "system" fn system() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -306,7 +306,7 @@ LL | const extern "system" fn system() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:213:5
|
||||
|
|
||||
LL | extern "system-unwind" fn system_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -473,37 +473,64 @@ impl<'a> LintExtractor<'a> {
|
||||
.filter(|line| line.starts_with('{'))
|
||||
.map(serde_json::from_str)
|
||||
.collect::<Result<Vec<serde_json::Value>, _>>()?;
|
||||
|
||||
// First try to find the messages with the `code` field set to our lint.
|
||||
let matches: Vec<_> = msgs
|
||||
.iter()
|
||||
.filter(|msg| matches!(&msg["code"]["code"], serde_json::Value::String(s) if s==name))
|
||||
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
|
||||
.collect();
|
||||
if matches.is_empty() {
|
||||
// Some lints override their code to something else (E0566).
|
||||
// Try to find something that looks like it could be our lint.
|
||||
let matches: Vec<_> = msgs.iter().filter(|msg|
|
||||
matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)))
|
||||
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
|
||||
.collect();
|
||||
if matches.is_empty() {
|
||||
let rendered: Vec<&str> =
|
||||
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
|
||||
let non_json: Vec<&str> =
|
||||
stderr.lines().filter(|line| !line.starts_with('{')).collect();
|
||||
Err(format!(
|
||||
"did not find lint `{}` in output of example, got:\n{}\n{}",
|
||||
name,
|
||||
non_json.join("\n"),
|
||||
rendered.join("\n")
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
Ok(matches.join("\n"))
|
||||
}
|
||||
} else {
|
||||
Ok(matches.join("\n"))
|
||||
if !matches.is_empty() {
|
||||
return Ok(matches.join("\n"));
|
||||
}
|
||||
|
||||
// Try to detect if an unstable lint forgot to enable a `#![feature(..)]`.
|
||||
// Specifically exclude `test_unstable_lint` which exercises this on purpose.
|
||||
if name != "test_unstable_lint"
|
||||
&& msgs.iter().any(|msg| {
|
||||
matches!(&msg["code"]["code"], serde_json::Value::String(s) if s=="unknown_lints")
|
||||
&& matches!(&msg["message"], serde_json::Value::String(s) if s.contains(name))
|
||||
})
|
||||
{
|
||||
let rendered: Vec<&str> =
|
||||
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
|
||||
let non_json: Vec<&str> =
|
||||
stderr.lines().filter(|line| !line.starts_with('{')).collect();
|
||||
return Err(format!(
|
||||
"did not find lint `{}` in output of example (got unknown_lints)\n\
|
||||
Is the lint possibly misspelled, or does it need a `#![feature(...)]`?\n\
|
||||
Output was:\n\
|
||||
{}\n{}",
|
||||
name,
|
||||
rendered.join("\n"),
|
||||
non_json.join("\n"),
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
// Some lints override their code to something else (E0566).
|
||||
// Try to find something that looks like it could be our lint.
|
||||
let matches: Vec<_> = msgs
|
||||
.iter()
|
||||
.filter(
|
||||
|msg| matches!(&msg["rendered"], serde_json::Value::String(s) if s.contains(name)),
|
||||
)
|
||||
.map(|msg| msg["rendered"].as_str().expect("rendered field should exist").to_string())
|
||||
.collect();
|
||||
if !matches.is_empty() {
|
||||
return Ok(matches.join("\n"));
|
||||
}
|
||||
|
||||
// Otherwise, give a descriptive error.
|
||||
let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
|
||||
let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
|
||||
Err(format!(
|
||||
"did not find lint `{}` in output of example, got:\n{}\n{}",
|
||||
name,
|
||||
non_json.join("\n"),
|
||||
rendered.join("\n")
|
||||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
/// Saves the mdbook lint chapters at the given path.
|
||||
|
@ -1,6 +1,7 @@
|
||||
use anyhow::Context;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
|
||||
use crate::environment::Environment;
|
||||
use crate::exec::cmd;
|
||||
use crate::training::BoltProfile;
|
||||
use crate::utils::io::copy_file;
|
||||
@ -45,13 +46,21 @@ pub fn with_bolt_instrumented<F: FnOnce(&Utf8Path) -> anyhow::Result<R>, R>(
|
||||
}
|
||||
|
||||
/// Optimizes the file at `path` with BOLT in-place using the given `profile`.
|
||||
pub fn bolt_optimize(path: &Utf8Path, profile: &BoltProfile) -> anyhow::Result<()> {
|
||||
pub fn bolt_optimize(
|
||||
path: &Utf8Path,
|
||||
profile: &BoltProfile,
|
||||
env: &Environment,
|
||||
) -> anyhow::Result<()> {
|
||||
// Copy the artifact to a new location, so that we do not use the same input and output file.
|
||||
// BOLT cannot handle optimizing when the input and output is the same file, because it performs
|
||||
// in-place patching.
|
||||
let temp_path = tempfile::NamedTempFile::new()?.into_temp_path();
|
||||
copy_file(path, &temp_path)?;
|
||||
|
||||
// FIXME: cdsplit in llvm-bolt is currently broken on AArch64, drop this once it's fixed upstream
|
||||
let split_strategy =
|
||||
if env.host_tuple().starts_with("aarch64") { "profile2" } else { "cdsplit" };
|
||||
|
||||
cmd(&["llvm-bolt"])
|
||||
.arg(temp_path.display())
|
||||
.arg("-data")
|
||||
@ -65,7 +74,7 @@ pub fn bolt_optimize(path: &Utf8Path, profile: &BoltProfile) -> anyhow::Result<(
|
||||
// Split function code into hot and code regions
|
||||
.arg("-split-functions")
|
||||
// Split using best available strategy (three-way splitting, Cache-Directed Sort)
|
||||
.arg("-split-strategy=cdsplit")
|
||||
.arg(format!("-split-strategy={split_strategy}"))
|
||||
// Split as many basic blocks as possible
|
||||
.arg("-split-all-cold")
|
||||
// Move jump tables to a separate section
|
||||
|
@ -146,6 +146,21 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
|
||||
let target_triple =
|
||||
std::env::var("PGO_HOST").expect("PGO_HOST environment variable missing");
|
||||
|
||||
let is_aarch64 = target_triple.starts_with("aarch64");
|
||||
|
||||
let mut skip_tests = vec![
|
||||
// Fails because of linker errors, as of June 2023.
|
||||
"tests/ui/process/nofile-limit.rs".to_string(),
|
||||
];
|
||||
|
||||
if is_aarch64 {
|
||||
skip_tests.extend([
|
||||
// Those tests fail only inside of Docker on aarch64, as of December 2024
|
||||
"tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs".to_string(),
|
||||
"tests/ui/consts/large_const_alloc.rs".to_string(),
|
||||
]);
|
||||
}
|
||||
|
||||
let checkout_dir = Utf8PathBuf::from("/checkout");
|
||||
let env = EnvironmentBuilder::default()
|
||||
.host_tuple(target_triple)
|
||||
@ -155,11 +170,9 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec<String>)>
|
||||
.artifact_dir(Utf8PathBuf::from("/tmp/tmp-multistage/opt-artifacts"))
|
||||
.build_dir(checkout_dir.join("obj"))
|
||||
.shared_llvm(true)
|
||||
.use_bolt(true)
|
||||
.skipped_tests(vec![
|
||||
// Fails because of linker errors, as of June 2023.
|
||||
"tests/ui/process/nofile-limit.rs".to_string(),
|
||||
])
|
||||
// FIXME: Enable bolt for aarch64 once it's fixed upstream. Broken as of December 2024.
|
||||
.use_bolt(!is_aarch64)
|
||||
.skipped_tests(skip_tests)
|
||||
.build()?;
|
||||
|
||||
(env, shared.build_args)
|
||||
@ -304,7 +317,8 @@ fn execute_pipeline(
|
||||
// the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*,
|
||||
// therefore it will actually optimize all the hard links, which means that the final
|
||||
// packaged `libLLVM.so` file *will* be BOLT optimized.
|
||||
bolt_optimize(&llvm_lib, &llvm_profile).context("Could not optimize LLVM with BOLT")?;
|
||||
bolt_optimize(&llvm_lib, &llvm_profile, env)
|
||||
.context("Could not optimize LLVM with BOLT")?;
|
||||
|
||||
let rustc_lib = io::find_file_in_dir(&libdir, "librustc_driver", ".so")?;
|
||||
|
||||
@ -319,7 +333,7 @@ fn execute_pipeline(
|
||||
print_free_disk_space()?;
|
||||
|
||||
// Now optimize the library with BOLT.
|
||||
bolt_optimize(&rustc_lib, &rustc_profile)
|
||||
bolt_optimize(&rustc_lib, &rustc_profile, env)
|
||||
.context("Could not optimize rustc with BOLT")?;
|
||||
|
||||
// LLVM is not being cleared here, we want to use the BOLT-optimized LLVM
|
||||
|
@ -41,3 +41,16 @@ impl<'a> Drop for StructWithDropAndLt<'a> {
|
||||
struct StructWithDropAndLt<'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
|
||||
// Make sure we don't ICE when checking impossible predicates for the struct.
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/135515>.
|
||||
//~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithLtAndPredicate<'_>> - shim(Some(StructWithLtAndPredicate<'_>))
|
||||
struct StructWithLtAndPredicate<'a: 'a> {
|
||||
x: &'a i32,
|
||||
}
|
||||
|
||||
// We should be able to monomorphize drops for struct with lifetimes.
|
||||
impl<'a> Drop for StructWithLtAndPredicate<'a> {
|
||||
//~ MONO_ITEM fn <StructWithLtAndPredicate<'_> as std::ops::Drop>::drop
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#![feature(extern_types)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type Extern;
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ bug!();
|
||||
macro_rules! doc_comment {
|
||||
($x:expr) => {
|
||||
#[doc = $x]
|
||||
extern {}
|
||||
extern "C" {}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[link(name = "c")]
|
||||
extern {}
|
||||
extern "C" {}
|
||||
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
|
||||
|
@ -18,7 +18,7 @@ impl !Copy for WithDrop {}
|
||||
|
||||
struct Type;
|
||||
trait Trait {}
|
||||
extern {
|
||||
extern "C" {
|
||||
type ExternType;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ const B: bool = true;
|
||||
|
||||
// ForeignType::unresolved - error
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type ForeignType;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type Opaque;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ trait OtherTrait {
|
||||
reuse Trait::*; //~ ERROR glob delegation is only supported in impls
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
reuse Trait::*; //~ ERROR delegation is not supported in `extern` blocks
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
// because they are both extern types.
|
||||
|
||||
#![feature(extern_types)]
|
||||
extern {
|
||||
extern "C" {
|
||||
type ShouldNotBeMentioned;
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type Foo;
|
||||
}
|
||||
|
||||
|
2
tests/ui/extern/issue-10025.rs
vendored
2
tests/ui/extern/issue-10025.rs
vendored
@ -1,5 +1,5 @@
|
||||
//@ run-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, missing_abi)]
|
||||
|
||||
unsafe extern fn foo() {}
|
||||
unsafe extern "C" fn bar() {}
|
||||
|
2
tests/ui/extern/issue-95829.rs
vendored
2
tests/ui/extern/issue-95829.rs
vendored
@ -1,6 +1,6 @@
|
||||
//@ edition:2018
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
async fn L() { //~ ERROR: incorrect function inside `extern` block
|
||||
//~^ ERROR: functions in `extern` blocks cannot have `async` qualifier
|
||||
async fn M() {}
|
||||
|
8
tests/ui/extern/issue-95829.stderr
vendored
8
tests/ui/extern/issue-95829.stderr
vendored
@ -1,8 +1,8 @@
|
||||
error: incorrect function inside `extern` block
|
||||
--> $DIR/issue-95829.rs:4:14
|
||||
|
|
||||
LL | extern {
|
||||
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
|
||||
LL | extern "C" {
|
||||
| ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
|
||||
LL | async fn L() {
|
||||
| ______________^___-
|
||||
| | |
|
||||
@ -18,8 +18,8 @@ LL | | }
|
||||
error: functions in `extern` blocks cannot have `async` qualifier
|
||||
--> $DIR/issue-95829.rs:4:5
|
||||
|
|
||||
LL | extern {
|
||||
| ------ in this `extern` block
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
LL | async fn L() {
|
||||
| ^^^^^ help: remove the `async` qualifier
|
||||
|
||||
|
1
tests/ui/extern/not-in-block.rs
vendored
1
tests/ui/extern/not-in-block.rs
vendored
@ -1,4 +1,5 @@
|
||||
#![crate_type = "lib"]
|
||||
#![allow(missing_abi)]
|
||||
|
||||
extern fn none_fn(x: bool) -> i32;
|
||||
//~^ ERROR free function without a body
|
||||
|
4
tests/ui/extern/not-in-block.stderr
vendored
4
tests/ui/extern/not-in-block.stderr
vendored
@ -1,5 +1,5 @@
|
||||
error: free function without a body
|
||||
--> $DIR/not-in-block.rs:3:1
|
||||
--> $DIR/not-in-block.rs:4:1
|
||||
|
|
||||
LL | extern fn none_fn(x: bool) -> i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -14,7 +14,7 @@ LL | extern { fn none_fn(x: bool) -> i32; }
|
||||
| ~~~~~~~~ +
|
||||
|
||||
error: free function without a body
|
||||
--> $DIR/not-in-block.rs:5:1
|
||||
--> $DIR/not-in-block.rs:6:1
|
||||
|
|
||||
LL | extern "C" fn c_fn(x: bool) -> i32;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Regression test for issue #91370.
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
//~^ `extern` blocks define existing foreign functions
|
||||
fn f() {
|
||||
//~^ incorrect function inside `extern` block
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: incorrect function inside `extern` block
|
||||
--> $DIR/issue-91370-foreign-fn-block-impl.rs:5:8
|
||||
|
|
||||
LL | extern {
|
||||
| ------ `extern` blocks define existing foreign functions and functions inside of them cannot have a body
|
||||
LL | extern "C" {
|
||||
| ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
|
||||
LL |
|
||||
LL | fn f() {
|
||||
| ________^___-
|
||||
|
@ -21,7 +21,7 @@ struct S;
|
||||
#[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes
|
||||
fn foo6<const X: usize>() {}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
#[rustc_legacy_const_generics(1)] //~ ERROR attribute should be applied to a function
|
||||
fn foo7<const X: usize>(); //~ ERROR foreign items may not have const parameters
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![crate_type = "lib"]
|
||||
#[link(kind = "static", modifiers = "+whole-archive,+bundle")]
|
||||
//~^ ERROR `#[link]` attribute requires a `name = "string"` argument
|
||||
extern {}
|
||||
extern "C" {}
|
||||
|
@ -1,6 +1,14 @@
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/suggest-libname-only-1.rs:7:1
|
||||
|
|
||||
LL | extern { }
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
|
|
||||
= note: `#[warn(missing_abi)]` on by default
|
||||
|
||||
error: could not find native static library `libfoo.a`, perhaps an -L flag is missing?
|
||||
|
|
||||
= help: only provide the library name `foo`, not the full filename
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
@ -1,6 +1,14 @@
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/suggest-libname-only-2.rs:7:1
|
||||
|
|
||||
LL | extern { }
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
|
|
||||
= note: `#[warn(missing_abi)]` on by default
|
||||
|
||||
error: could not find native static library `bar.lib`, perhaps an -L flag is missing?
|
||||
|
|
||||
= help: only provide the library name `bar`, not the full filename
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
@ -11,7 +11,7 @@ fn baz(x: u32, y: u32) -> u32 { x + y }
|
||||
unsafe fn unsafe_fn() { }
|
||||
extern "C" fn c_fn() { }
|
||||
unsafe extern "C" fn unsafe_c_fn() { }
|
||||
unsafe extern fn variadic(_x: u32, _args: ...) { }
|
||||
unsafe extern "C" fn variadic(_x: u32, _args: ...) { }
|
||||
fn take_generic_ref<'a, T>(_x: &'a T) { }
|
||||
fn take_generic_array<T, const N: usize>(_x: [T; N]) { }
|
||||
fn multiple_generic<T, U>(_x: T, _y: U) { }
|
||||
|
@ -72,7 +72,7 @@ extern "C" {
|
||||
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `Box<u32>`
|
||||
pub fn raw_array(arr: [u8; 8]); //~ ERROR: uses type `[u8; 8]`
|
||||
|
||||
pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
|
||||
pub fn no_niche_a(a: Option<UnsafeCell<extern "C" fn()>>);
|
||||
//~^ ERROR: uses type `Option<UnsafeCell<extern "C" fn()>>`
|
||||
pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
|
||||
//~^ ERROR: uses type `Option<UnsafeCell<&i32>>`
|
||||
|
@ -227,8 +227,8 @@ LL | pub fn raw_array(arr: [u8; 8]);
|
||||
error: `extern` block uses type `Option<UnsafeCell<extern "C" fn()>>`, which is not FFI-safe
|
||||
--> $DIR/lint-ctypes.rs:75:26
|
||||
|
|
||||
LL | pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
LL | pub fn no_niche_a(a: Option<UnsafeCell<extern "C" fn()>>);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
||||
|
|
||||
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
|
||||
= note: enum has no representation hint
|
||||
|
@ -16,7 +16,7 @@ struct Beta {
|
||||
z: dyn Trait,
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type Extern;
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T2 = unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T4 = extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T6 = unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
@ -14,9 +14,9 @@ pub type T6 = unsafe extern "C" fn();
|
||||
|
||||
pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT2 = for<'a> unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT4 = for<'a> extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT5 = for<'a> unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT6 = for<'a> unsafe extern "C" fn();
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
pub type T0 = const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T1 = const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T2 = const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T2 = const unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type T3 = async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T4 = async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T4 = async extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T5 = async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type T6 = const async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
@ -14,9 +14,9 @@ pub type T6 = const async unsafe extern "C" fn();
|
||||
|
||||
pub type FTT0 = for<'a> const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT1 = for<'a> const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT2 = for<'a> const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT2 = for<'a> const unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
pub type FTT3 = for<'a> async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT4 = for<'a> async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT4 = for<'a> async extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT5 = for<'a> async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `async`
|
||||
pub type FTT6 = for<'a> const async unsafe extern "C" fn();
|
||||
|
@ -29,15 +29,15 @@ LL + pub type T1 = extern "C" fn();
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/bad-fn-ptr-qualifier.rs:7:15
|
||||
|
|
||||
LL | pub type T2 = const unsafe extern fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^
|
||||
LL | pub type T2 = const unsafe extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
|
|
||||
help: remove the `const` qualifier
|
||||
|
|
||||
LL - pub type T2 = const unsafe extern fn();
|
||||
LL + pub type T2 = unsafe extern fn();
|
||||
LL - pub type T2 = const unsafe extern "C" fn();
|
||||
LL + pub type T2 = unsafe extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -57,15 +57,15 @@ LL + pub type T3 = fn();
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/bad-fn-ptr-qualifier.rs:9:15
|
||||
|
|
||||
LL | pub type T4 = async extern fn();
|
||||
| -----^^^^^^^^^^^^
|
||||
LL | pub type T4 = async extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
|
|
||||
help: remove the `async` qualifier
|
||||
|
|
||||
LL - pub type T4 = async extern fn();
|
||||
LL + pub type T4 = extern fn();
|
||||
LL - pub type T4 = async extern "C" fn();
|
||||
LL + pub type T4 = extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -141,15 +141,15 @@ LL + pub type FTT1 = for<'a> extern "C" fn();
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/bad-fn-ptr-qualifier.rs:17:17
|
||||
|
|
||||
LL | pub type FTT2 = for<'a> const unsafe extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^
|
||||
LL | pub type FTT2 = for<'a> const unsafe extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
|
|
||||
help: remove the `const` qualifier
|
||||
|
|
||||
LL - pub type FTT2 = for<'a> const unsafe extern fn();
|
||||
LL + pub type FTT2 = for<'a> unsafe extern fn();
|
||||
LL - pub type FTT2 = for<'a> const unsafe extern "C" fn();
|
||||
LL + pub type FTT2 = for<'a> unsafe extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -169,15 +169,15 @@ LL + pub type FTT3 = for<'a> fn();
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/bad-fn-ptr-qualifier.rs:19:17
|
||||
|
|
||||
LL | pub type FTT4 = for<'a> async extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^
|
||||
LL | pub type FTT4 = for<'a> async extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
|
|
||||
help: remove the `async` qualifier
|
||||
|
|
||||
LL - pub type FTT4 = for<'a> async extern fn();
|
||||
LL + pub type FTT4 = for<'a> extern fn();
|
||||
LL - pub type FTT4 = for<'a> async extern "C" fn();
|
||||
LL + pub type FTT4 = for<'a> extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
|
@ -1,10 +1,10 @@
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
extern
|
||||
extern //~ WARN missing_abi
|
||||
"C"suffix //~ ERROR suffixes on string literals are invalid
|
||||
fn foo() {}
|
||||
|
||||
extern
|
||||
extern //~ WARN missing_abi
|
||||
"C"suffix //~ ERROR suffixes on string literals are invalid
|
||||
{}
|
||||
|
||||
|
@ -49,6 +49,20 @@ LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
|
||||
|
|
||||
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
|
||||
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/bad-lit-suffixes.rs:3:1
|
||||
|
|
||||
LL | extern
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
|
|
||||
= note: `#[warn(missing_abi)]` on by default
|
||||
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/bad-lit-suffixes.rs:7:1
|
||||
|
|
||||
LL | extern
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
|
||||
error: suffixes on string literals are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:12:5
|
||||
|
|
||||
@ -149,5 +163,5 @@ LL | 1.0e10suffix;
|
||||
|
|
||||
= help: valid suffixes are `f32` and `f64`
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: aborting due to 21 previous errors; 2 warnings emitted
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ edition:2018
|
||||
#![allow(missing_abi)]
|
||||
|
||||
// There is an order to respect for keywords before a function:
|
||||
// `<visibility>, const, async, unsafe, extern, "<ABI>"`
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: expected `fn`, found keyword `unsafe`
|
||||
--> $DIR/wrong-unsafe.rs:9:8
|
||||
--> $DIR/wrong-unsafe.rs:10:8
|
||||
|
|
||||
LL | extern unsafe fn test() {}
|
||||
| -------^^^^^^
|
||||
|
@ -25,7 +25,7 @@ const unsafe fn _e() {}
|
||||
//~| ERROR keyword `unsafe` is written in the wrong case
|
||||
//~| ERROR keyword `fn` is written in the wrong case
|
||||
|
||||
unsafe extern fn _f() {}
|
||||
unsafe extern "C" fn _f() {}
|
||||
//~^ ERROR keyword `unsafe` is written in the wrong case
|
||||
//~| ERROR keyword `extern` is written in the wrong case
|
||||
|
||||
|
@ -25,7 +25,7 @@ CONST UNSAFE FN _e() {}
|
||||
//~| ERROR keyword `unsafe` is written in the wrong case
|
||||
//~| ERROR keyword `fn` is written in the wrong case
|
||||
|
||||
unSAFE EXTern fn _f() {}
|
||||
unSAFE EXTern "C" fn _f() {}
|
||||
//~^ ERROR keyword `unsafe` is written in the wrong case
|
||||
//~| ERROR keyword `extern` is written in the wrong case
|
||||
|
||||
|
@ -111,23 +111,23 @@ LL | CONST UNSAFE fn _e() {}
|
||||
error: keyword `unsafe` is written in the wrong case
|
||||
--> $DIR/item-kw-case-mismatch.rs:28:1
|
||||
|
|
||||
LL | unSAFE EXTern fn _f() {}
|
||||
LL | unSAFE EXTern "C" fn _f() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
help: write it in the correct case
|
||||
|
|
||||
LL | unsafe EXTern fn _f() {}
|
||||
LL | unsafe EXTern "C" fn _f() {}
|
||||
| ~~~~~~
|
||||
|
||||
error: keyword `extern` is written in the wrong case
|
||||
--> $DIR/item-kw-case-mismatch.rs:28:8
|
||||
|
|
||||
LL | unSAFE EXTern fn _f() {}
|
||||
LL | unSAFE EXTern "C" fn _f() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
help: write it in the correct case
|
||||
|
|
||||
LL | unSAFE extern fn _f() {}
|
||||
LL | unSAFE extern "C" fn _f() {}
|
||||
| ~~~~~~
|
||||
|
||||
error: keyword `extern` is written in the wrong case
|
||||
|
@ -1,6 +1,6 @@
|
||||
macro_rules! f {
|
||||
($abi:literal) => {
|
||||
extern $abi fn f() {}
|
||||
extern $abi fn f() {} //~ WARN missing_abi
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,5 +4,17 @@ error: suffixes on string literals are invalid
|
||||
LL | f!("Foo"__);
|
||||
| ^^^^^^^ invalid suffix `__`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/lit-err-in-macro.rs:3:9
|
||||
|
|
||||
LL | extern $abi fn f() {}
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
...
|
||||
LL | f!("Foo"__);
|
||||
| ----------- in this macro invocation
|
||||
|
|
||||
= note: `#[warn(missing_abi)]` on by default
|
||||
= note: this warning originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
type T0 = const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T1 = const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T2 = const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T2 = const unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T3 = async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T4 = async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T4 = async extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T5 = async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T6 = const async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
@ -12,9 +12,9 @@ type T6 = const async unsafe extern "C" fn();
|
||||
|
||||
type FT0 = for<'a> const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT1 = for<'a> const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT2 = for<'a> const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT2 = for<'a> const unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT3 = for<'a> async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT4 = for<'a> async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT4 = for<'a> async extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT5 = for<'a> async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT6 = for<'a> const async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
|
@ -29,15 +29,15 @@ LL + type T1 = extern "C" fn();
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:5:11
|
||||
|
|
||||
LL | type T2 = const unsafe extern fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^
|
||||
LL | type T2 = const unsafe extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
|
|
||||
help: remove the `const` qualifier
|
||||
|
|
||||
LL - type T2 = const unsafe extern fn();
|
||||
LL + type T2 = unsafe extern fn();
|
||||
LL - type T2 = const unsafe extern "C" fn();
|
||||
LL + type T2 = unsafe extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -57,15 +57,15 @@ LL + type T3 = fn();
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:7:11
|
||||
|
|
||||
LL | type T4 = async extern fn();
|
||||
| -----^^^^^^^^^^^^
|
||||
LL | type T4 = async extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
|
|
||||
help: remove the `async` qualifier
|
||||
|
|
||||
LL - type T4 = async extern fn();
|
||||
LL + type T4 = extern fn();
|
||||
LL - type T4 = async extern "C" fn();
|
||||
LL + type T4 = extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -141,15 +141,15 @@ LL + type FT1 = for<'a> extern "C" fn();
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:15:12
|
||||
|
|
||||
LL | type FT2 = for<'a> const unsafe extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^
|
||||
LL | type FT2 = for<'a> const unsafe extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
|
|
||||
help: remove the `const` qualifier
|
||||
|
|
||||
LL - type FT2 = for<'a> const unsafe extern fn();
|
||||
LL + type FT2 = for<'a> unsafe extern fn();
|
||||
LL - type FT2 = for<'a> const unsafe extern "C" fn();
|
||||
LL + type FT2 = for<'a> unsafe extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
@ -169,15 +169,15 @@ LL + type FT3 = for<'a> fn();
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:17:12
|
||||
|
|
||||
LL | type FT4 = for<'a> async extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^
|
||||
LL | type FT4 = for<'a> async extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
|
|
||||
help: remove the `async` qualifier
|
||||
|
|
||||
LL - type FT4 = for<'a> async extern fn();
|
||||
LL + type FT4 = for<'a> extern fn();
|
||||
LL - type FT4 = for<'a> async extern "C" fn();
|
||||
LL + type FT4 = for<'a> extern "C" fn();
|
||||
|
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
||||
type Hmm = fn<>();
|
||||
//~^ ERROR function pointer types may not have generic parameters
|
||||
|
||||
let _: extern fn<'a: 'static>();
|
||||
let _: extern "C" fn<'a: 'static>();
|
||||
//~^ ERROR function pointer types may not have generic parameters
|
||||
//~| ERROR bounds cannot be used in this context
|
||||
|
||||
|
@ -59,15 +59,15 @@ LL | type Hmm = fn<>();
|
||||
| ^^
|
||||
|
||||
error: function pointer types may not have generic parameters
|
||||
--> $DIR/recover-fn-ptr-with-generics.rs:22:21
|
||||
--> $DIR/recover-fn-ptr-with-generics.rs:22:25
|
||||
|
|
||||
LL | let _: extern fn<'a: 'static>();
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | let _: extern "C" fn<'a: 'static>();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
help: consider moving the lifetime parameter to a `for` parameter list
|
||||
|
|
||||
LL - let _: extern fn<'a: 'static>();
|
||||
LL + let _: for<'a> extern fn();
|
||||
LL - let _: extern "C" fn<'a: 'static>();
|
||||
LL + let _: for<'a> extern "C" fn();
|
||||
|
|
||||
|
||||
error: function pointer types may not have generic parameters
|
||||
@ -101,10 +101,10 @@ LL | type Identity = fn<T>(T) -> T;
|
||||
| ^ not found in this scope
|
||||
|
||||
error: bounds cannot be used in this context
|
||||
--> $DIR/recover-fn-ptr-with-generics.rs:22:26
|
||||
--> $DIR/recover-fn-ptr-with-generics.rs:22:30
|
||||
|
|
||||
LL | let _: extern fn<'a: 'static>();
|
||||
| ^^^^^^^
|
||||
LL | let _: extern "C" fn<'a: 'static>();
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
@ -28,7 +28,7 @@ fn for_fn() {
|
||||
|
||||
fn for_extern() {
|
||||
let foo = 3; //~ ERROR expected `;`, found keyword `extern`
|
||||
extern fn foo() {}
|
||||
extern "C" fn foo() {}
|
||||
}
|
||||
|
||||
fn for_impl() {
|
||||
|
@ -28,7 +28,7 @@ fn for_fn() {
|
||||
|
||||
fn for_extern() {
|
||||
let foo = 3 //~ ERROR expected `;`, found keyword `extern`
|
||||
extern fn foo() {}
|
||||
extern "C" fn foo() {}
|
||||
}
|
||||
|
||||
fn for_impl() {
|
||||
|
@ -35,7 +35,7 @@ error: expected `;`, found keyword `extern`
|
||||
|
|
||||
LL | let foo = 3
|
||||
| ^ help: add `;` here
|
||||
LL | extern fn foo() {}
|
||||
LL | extern "C" fn foo() {}
|
||||
| ------ unexpected token
|
||||
|
||||
error: expected `;`, found keyword `impl`
|
||||
|
@ -22,5 +22,13 @@ error: expected non-macro inner attribute, found attribute macro `print_attr`
|
||||
LL | #![print_attr]
|
||||
| ^^^^^^^^^^ not a non-macro inner attribute
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
warning: extern declarations without an explicit ABI are deprecated
|
||||
--> $DIR/inner-attrs.rs:82:1
|
||||
|
|
||||
LL | extern {
|
||||
| ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
|
||||
|
|
||||
= note: `#[warn(missing_abi)]` on by default
|
||||
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
extern crate issue_66286;
|
||||
|
||||
#[issue_66286::vec_ice]
|
||||
pub extern fn foo(_: Vec(u32)) -> u32 {
|
||||
pub extern "C" fn foo(_: Vec(u32)) -> u32 {
|
||||
//~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait
|
||||
0
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
|
||||
--> $DIR/issue-66286.rs:8:22
|
||||
--> $DIR/issue-66286.rs:8:26
|
||||
|
|
||||
LL | pub extern fn foo(_: Vec(u32)) -> u32 {
|
||||
| ^^^^^^^^ only `Fn` traits may use parentheses
|
||||
LL | pub extern "C" fn foo(_: Vec(u32)) -> u32 {
|
||||
| ^^^^^^^^ only `Fn` traits may use parentheses
|
||||
|
|
||||
help: use angle brackets instead
|
||||
|
|
||||
LL | pub extern fn foo(_: Vec<u32>) -> u32 {
|
||||
| ~ ~
|
||||
LL | pub extern "C" fn foo(_: Vec<u32>) -> u32 {
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -11,7 +11,7 @@ fn test() {}
|
||||
static mut imported_val: i32 = 123;
|
||||
|
||||
#[link(name = "exporter", kind = "raw-dylib")]
|
||||
extern {
|
||||
extern "C" {
|
||||
#[link_ordinal(13)]
|
||||
fn imported_function();
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
macro_rules! tt {
|
||||
($e:tt) => {
|
||||
#$e
|
||||
extern fn foo() {}
|
||||
extern "C" fn foo() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ macro_rules! ident {
|
||||
#[unsafe($e)]
|
||||
//~^ ERROR: unsafe attribute used without unsafe
|
||||
//~| WARN this is accepted in the current edition
|
||||
extern fn bar() {}
|
||||
extern "C" fn bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,21 +22,21 @@ macro_rules! ident2 {
|
||||
#[unsafe($e = $l)]
|
||||
//~^ ERROR: unsafe attribute used without unsafe
|
||||
//~| WARN this is accepted in the current edition
|
||||
extern fn bars() {}
|
||||
extern "C" fn bars() {}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! meta {
|
||||
($m:meta) => {
|
||||
#[$m]
|
||||
extern fn baz() {}
|
||||
extern "C" fn baz() {}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! meta2 {
|
||||
($m:meta) => {
|
||||
#[$m]
|
||||
extern fn baw() {}
|
||||
extern "C" fn baw() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
macro_rules! tt {
|
||||
($e:tt) => {
|
||||
#$e
|
||||
extern fn foo() {}
|
||||
extern "C" fn foo() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ macro_rules! ident {
|
||||
#[$e]
|
||||
//~^ ERROR: unsafe attribute used without unsafe
|
||||
//~| WARN this is accepted in the current edition
|
||||
extern fn bar() {}
|
||||
extern "C" fn bar() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,21 +22,21 @@ macro_rules! ident2 {
|
||||
#[$e = $l]
|
||||
//~^ ERROR: unsafe attribute used without unsafe
|
||||
//~| WARN this is accepted in the current edition
|
||||
extern fn bars() {}
|
||||
extern "C" fn bars() {}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! meta {
|
||||
($m:meta) => {
|
||||
#[$m]
|
||||
extern fn baz() {}
|
||||
extern "C" fn baz() {}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! meta2 {
|
||||
($m:meta) => {
|
||||
#[$m]
|
||||
extern fn baw() {}
|
||||
extern "C" fn baw() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
use std::ptr::NonNull;
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
type Extern;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![deny(uninhabited_static)]
|
||||
|
||||
enum Void {}
|
||||
extern {
|
||||
extern "C" {
|
||||
static VOID: Void; //~ ERROR static of uninhabited type
|
||||
//~| WARN: previously accepted
|
||||
static NEVER: !; //~ ERROR static of uninhabited type
|
||||
|
@ -452,15 +452,15 @@ mod items {
|
||||
/// ItemKind::Fn
|
||||
mod item_fn {
|
||||
pub const unsafe extern "C" fn f() {}
|
||||
pub async unsafe extern fn g() {}
|
||||
pub async unsafe extern "C" fn g() {}
|
||||
fn h<'a, T>() where T: 'a {}
|
||||
|
||||
trait TraitItems {
|
||||
unsafe extern fn f();
|
||||
unsafe extern "C" fn f();
|
||||
}
|
||||
|
||||
impl TraitItems for _ {
|
||||
default unsafe extern fn f() {}
|
||||
default unsafe extern "C" fn f() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,7 +472,7 @@ mod items {
|
||||
/// ItemKind::ForeignMod
|
||||
mod item_foreign_mod {
|
||||
unsafe extern "C++" {}
|
||||
unsafe extern {}
|
||||
unsafe extern "C" {}
|
||||
}
|
||||
|
||||
/// ItemKind::GlobalAsm
|
||||
|
@ -433,13 +433,13 @@ mod items {
|
||||
/// ItemKind::Fn
|
||||
mod item_fn {
|
||||
pub const unsafe extern "C" fn f() {}
|
||||
pub async unsafe extern fn g() {}
|
||||
pub async unsafe extern "C" fn g() {}
|
||||
fn h<'a, T>() where T: 'a {}
|
||||
trait TraitItems {
|
||||
unsafe extern fn f();
|
||||
unsafe extern "C" fn f();
|
||||
}
|
||||
impl TraitItems for _ {
|
||||
default unsafe extern fn f() {}
|
||||
default unsafe extern "C" fn f() {}
|
||||
}
|
||||
}
|
||||
/// ItemKind::Mod
|
||||
@ -447,7 +447,7 @@ mod items {
|
||||
/// ItemKind::ForeignMod
|
||||
mod item_foreign_mod {
|
||||
unsafe extern "C++" {}
|
||||
unsafe extern {}
|
||||
unsafe extern "C" {}
|
||||
}
|
||||
/// ItemKind::GlobalAsm
|
||||
mod item_global_asm {
|
||||
|
Loading…
Reference in New Issue
Block a user