mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #93202 - matthiaskrgr:rollup-rki39xg, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #85967 (add support for the l4-bender linker on the x86_64-unknown-l4re-uclibc tier 3 target) - #92828 (Print a helpful message if unwinding aborts when it reaches a nounwind function) - #93012 (Update pulldown-cmark version to fix markdown list issue) - #93116 (Simplify use of `map_or`) - #93132 (Increase the format version of rustdoc-json-types) - #93147 (Interner cleanups) - #93153 (Reject unsupported naked functions) - #93170 (Add missing GUI test explanations) - #93172 (rustdoc: remove dashed underline under main heading) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
bfe1564676
25
Cargo.lock
25
Cargo.lock
@ -689,7 +689,7 @@ dependencies = [
|
||||
"clippy_utils",
|
||||
"if_chain",
|
||||
"itertools 0.10.1",
|
||||
"pulldown-cmark 0.9.0",
|
||||
"pulldown-cmark",
|
||||
"quine-mc_cluskey",
|
||||
"regex-syntax",
|
||||
"rustc-semver",
|
||||
@ -2186,9 +2186,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.4.14"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6e77253c46a90eb7e96b2807201dab941a4db5ea05eca5aaaf7027395f352b3"
|
||||
checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
@ -2201,7 +2201,7 @@ dependencies = [
|
||||
"log",
|
||||
"memchr",
|
||||
"opener",
|
||||
"pulldown-cmark 0.8.0",
|
||||
"pulldown-cmark",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@ -2865,9 +2865,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.8.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
|
||||
checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
@ -2875,17 +2875,6 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acd16514d1af5f7a71f909a44ef253cdb712a376d7ebc8ae4a471a9be9743548"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "punycode"
|
||||
version = "0.4.1"
|
||||
@ -4440,7 +4429,7 @@ dependencies = [
|
||||
"expect-test",
|
||||
"itertools 0.9.0",
|
||||
"minifier",
|
||||
"pulldown-cmark 0.9.0",
|
||||
"pulldown-cmark",
|
||||
"rayon",
|
||||
"regex",
|
||||
"rustdoc-json-types",
|
||||
|
@ -1159,6 +1159,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
LinkerFlavor::Lld(_) => "lld",
|
||||
LinkerFlavor::PtxLinker => "rust-ptx-linker",
|
||||
LinkerFlavor::BpfLinker => "bpf-linker",
|
||||
LinkerFlavor::L4Bender => "l4-bender",
|
||||
}),
|
||||
flavor,
|
||||
)),
|
||||
|
@ -126,7 +126,6 @@ pub fn get_linker<'a>(
|
||||
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
|
||||
// to the linker args construction.
|
||||
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
||||
|
||||
match flavor {
|
||||
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
|
||||
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
|
||||
@ -149,6 +148,8 @@ pub fn get_linker<'a>(
|
||||
LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
||||
LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
||||
LinkerFlavor::L4Bender => Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1355,6 +1356,157 @@ impl<'a> Linker for WasmLd<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Linker shepherd script for L4Re (Fiasco)
|
||||
pub struct L4Bender<'a> {
|
||||
cmd: Command,
|
||||
sess: &'a Session,
|
||||
hinted_static: bool,
|
||||
}
|
||||
|
||||
impl<'a> Linker for L4Bender<'a> {
|
||||
fn link_dylib(&mut self, _lib: Symbol, _verbatim: bool, _as_needed: bool) {
|
||||
bug!("dylibs are not supported on L4Re");
|
||||
}
|
||||
fn link_staticlib(&mut self, lib: Symbol, _verbatim: bool) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(format!("-PC{}", lib));
|
||||
}
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(lib);
|
||||
}
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
}
|
||||
fn framework_path(&mut self, _: &Path) {
|
||||
bug!("frameworks are not supported on L4Re");
|
||||
}
|
||||
fn output_filename(&mut self, path: &Path) {
|
||||
self.cmd.arg("-o").arg(path);
|
||||
}
|
||||
|
||||
fn add_object(&mut self, path: &Path) {
|
||||
self.cmd.arg(path);
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
self.cmd.arg("-zrelro");
|
||||
self.cmd.arg("-znow");
|
||||
}
|
||||
|
||||
fn partial_relro(&mut self) {
|
||||
self.cmd.arg("-zrelro");
|
||||
}
|
||||
|
||||
fn no_relro(&mut self) {
|
||||
self.cmd.arg("-znorelro");
|
||||
}
|
||||
|
||||
fn cmd(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
|
||||
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
|
||||
|
||||
fn link_rust_dylib(&mut self, _: Symbol, _: &Path) {
|
||||
panic!("Rust dylibs not supported");
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: Symbol, _as_needed: bool) {
|
||||
bug!("frameworks not supported on L4Re");
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: Symbol, _verbatim: bool, _search_path: &[PathBuf]) {
|
||||
self.hint_static();
|
||||
self.cmd.arg("--whole-archive").arg(format!("-l{}", lib));
|
||||
self.cmd.arg("--no-whole-archive");
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
self.hint_static();
|
||||
self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, keep_metadata: bool) {
|
||||
if !keep_metadata {
|
||||
self.cmd.arg("--gc-sections");
|
||||
}
|
||||
}
|
||||
|
||||
fn no_gc_sections(&mut self) {
|
||||
self.cmd.arg("--no-gc-sections");
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
// GNU-style linkers support optimization with -O. GNU ld doesn't
|
||||
// need a numeric argument, but other linkers do.
|
||||
if self.sess.opts.optimize == config::OptLevel::Default
|
||||
|| self.sess.opts.optimize == config::OptLevel::Aggressive
|
||||
{
|
||||
self.cmd.arg("-O1");
|
||||
}
|
||||
}
|
||||
|
||||
fn pgo_gen(&mut self) {}
|
||||
|
||||
fn debuginfo(&mut self, strip: Strip) {
|
||||
match strip {
|
||||
Strip::None => {}
|
||||
Strip::Debuginfo => {
|
||||
self.cmd().arg("--strip-debug");
|
||||
}
|
||||
Strip::Symbols => {
|
||||
self.cmd().arg("--strip-all");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn no_default_libraries(&mut self) {
|
||||
self.cmd.arg("-nostdlib");
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
|
||||
// ToDo, not implemented, copy from GCC
|
||||
self.sess.warn("exporting symbols not implemented yet for L4Bender");
|
||||
return;
|
||||
}
|
||||
|
||||
fn subsystem(&mut self, subsystem: &str) {
|
||||
self.cmd.arg(&format!("--subsystem {}", subsystem));
|
||||
}
|
||||
|
||||
fn reset_per_library_state(&mut self) {
|
||||
self.hint_static(); // Reset to default before returning the composed command line.
|
||||
}
|
||||
|
||||
fn group_start(&mut self) {
|
||||
self.cmd.arg("--start-group");
|
||||
}
|
||||
|
||||
fn group_end(&mut self) {
|
||||
self.cmd.arg("--end-group");
|
||||
}
|
||||
|
||||
fn linker_plugin_lto(&mut self) {}
|
||||
|
||||
fn control_flow_guard(&mut self) {}
|
||||
|
||||
fn no_crt_objects(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'a> L4Bender<'a> {
|
||||
pub fn new(cmd: Command, sess: &'a Session) -> L4Bender<'a> {
|
||||
L4Bender { cmd: cmd, sess: sess, hinted_static: false }
|
||||
}
|
||||
|
||||
fn hint_static(&mut self) {
|
||||
if !self.hinted_static {
|
||||
self.cmd.arg("-static");
|
||||
self.hinted_static = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
|
||||
return exports.clone();
|
||||
|
@ -477,6 +477,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup);
|
||||
}
|
||||
|
||||
fn codegen_abort_terminator(
|
||||
&mut self,
|
||||
helper: TerminatorCodegenHelper<'tcx>,
|
||||
mut bx: Bx,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
) {
|
||||
let span = terminator.source_info.span;
|
||||
self.set_debug_loc(&mut bx, terminator.source_info);
|
||||
|
||||
// Get the location information.
|
||||
let location = self.get_caller_location(&mut bx, terminator.source_info).immediate();
|
||||
|
||||
// Obtain the panic entry point.
|
||||
let def_id = common::langcall(bx.tcx(), Some(span), "", LangItem::PanicNoUnwind);
|
||||
let instance = ty::Instance::mono(bx.tcx(), def_id);
|
||||
let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let llfn = bx.get_fn_addr(instance);
|
||||
|
||||
// Codegen the actual panic invoke/call.
|
||||
helper.do_call(self, &mut bx, fn_abi, llfn, &[location], None, None);
|
||||
}
|
||||
|
||||
/// Returns `true` if this is indeed a panic intrinsic and codegen is done.
|
||||
fn codegen_panic_intrinsic(
|
||||
&mut self,
|
||||
@ -1014,10 +1036,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
mir::TerminatorKind::Resume => self.codegen_resume_terminator(helper, 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();
|
||||
self.codegen_abort_terminator(helper, bx, terminator);
|
||||
}
|
||||
|
||||
mir::TerminatorKind::Goto { target } => {
|
||||
|
@ -486,6 +486,7 @@ E0783: include_str!("./error_codes/E0783.md"),
|
||||
E0784: include_str!("./error_codes/E0784.md"),
|
||||
E0785: include_str!("./error_codes/E0785.md"),
|
||||
E0786: include_str!("./error_codes/E0786.md"),
|
||||
E0787: include_str!("./error_codes/E0787.md"),
|
||||
;
|
||||
// E0006, // merged with E0005
|
||||
// E0008, // cannot bind by-move into a pattern guard
|
||||
|
28
compiler/rustc_error_codes/src/error_codes/E0787.md
Normal file
28
compiler/rustc_error_codes/src/error_codes/E0787.md
Normal file
@ -0,0 +1,28 @@
|
||||
An unsupported naked function definition.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0787
|
||||
#![feature(naked_functions)]
|
||||
|
||||
#[naked]
|
||||
pub extern "C" fn f() -> u32 {
|
||||
42
|
||||
}
|
||||
```
|
||||
|
||||
The naked functions must be defined using a single inline assembly
|
||||
block.
|
||||
|
||||
The execution must never fall through past the end of the assembly
|
||||
code so the block must use `noreturn` option. The asm block can also
|
||||
use `att_syntax` and `raw` options, but others options are not allowed.
|
||||
|
||||
The asm block must not contain any operands other than `const` and
|
||||
`sym`.
|
||||
|
||||
### Additional information
|
||||
|
||||
For more information, please see [RFC 2972].
|
||||
|
||||
[RFC 2972]: https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md
|
@ -283,6 +283,7 @@ language_item_table! {
|
||||
PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
|
||||
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
|
||||
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
|
||||
PanicNoUnwind, sym::panic_no_unwind, panic_no_unwind, Target::Fn, GenericRequirement::Exact(0);
|
||||
/// libstd panic entry point. Necessary for const eval to be able to catch it
|
||||
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
|
@ -481,6 +481,11 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
|
||||
<https://github.com/rust-lang/rust/issues/59014> for more information",
|
||||
);
|
||||
store.register_removed("plugin_as_library", "plugins have been deprecated and retired");
|
||||
store.register_removed(
|
||||
"unsupported_naked_functions",
|
||||
"converted into hard error, see RFC 2972 \
|
||||
<https://github.com/rust-lang/rfcs/blob/master/text/2972-constrained-naked.md> for more information",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
@ -2759,52 +2759,6 @@ declare_lint! {
|
||||
"undefined naked function ABI"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `unsupported_naked_functions` lint detects naked function
|
||||
/// definitions that are unsupported but were previously accepted.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(naked_functions)]
|
||||
///
|
||||
/// #[naked]
|
||||
/// pub extern "C" fn f() -> u32 {
|
||||
/// 42
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// The naked functions must be defined using a single inline assembly
|
||||
/// block.
|
||||
///
|
||||
/// The execution must never fall through past the end of the assembly
|
||||
/// code so the block must use `noreturn` option. The asm block can also
|
||||
/// use `att_syntax` option, but other options are not allowed.
|
||||
///
|
||||
/// The asm block must not contain any operands other than `const` and
|
||||
/// `sym`. Additionally, naked function should specify a non-Rust ABI.
|
||||
///
|
||||
/// Naked functions cannot be inlined. All forms of the `inline` attribute
|
||||
/// are prohibited.
|
||||
///
|
||||
/// While other definitions of naked functions were previously accepted,
|
||||
/// they are unsupported and might not work reliably. This is a
|
||||
/// [future-incompatible] lint that will transition into hard error in
|
||||
/// the future.
|
||||
///
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub UNSUPPORTED_NAKED_FUNCTIONS,
|
||||
Warn,
|
||||
"unsupported naked function definitions",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #32408 <https://github.com/rust-lang/rust/issues/32408>",
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ineffective_unstable_trait_impl` lint detects `#[unstable]` attributes which are not used.
|
||||
///
|
||||
@ -3070,7 +3024,6 @@ declare_lint_pass! {
|
||||
UNINHABITED_STATIC,
|
||||
FUNCTION_ITEM_REFERENCES,
|
||||
USELESS_DEPRECATED,
|
||||
UNSUPPORTED_NAKED_FUNCTIONS,
|
||||
MISSING_ABI,
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
|
@ -113,6 +113,12 @@ pub struct CtxtInterners<'tcx> {
|
||||
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
|
||||
layout: InternedSet<'tcx, Layout>,
|
||||
adt_def: InternedSet<'tcx, AdtDef>,
|
||||
|
||||
/// `#[stable]` and `#[unstable]` attributes
|
||||
stability: InternedSet<'tcx, attr::Stability>,
|
||||
|
||||
/// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes
|
||||
const_stability: InternedSet<'tcx, attr::ConstStability>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtInterners<'tcx> {
|
||||
@ -134,6 +140,8 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||
bound_variable_kinds: Default::default(),
|
||||
layout: Default::default(),
|
||||
adt_def: Default::default(),
|
||||
stability: Default::default(),
|
||||
const_stability: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1035,12 +1043,6 @@ pub struct GlobalCtxt<'tcx> {
|
||||
/// Data layout specification for the current target.
|
||||
pub data_layout: TargetDataLayout,
|
||||
|
||||
/// `#[stable]` and `#[unstable]` attributes
|
||||
stability_interner: ShardedHashMap<&'tcx attr::Stability, ()>,
|
||||
|
||||
/// `#[rustc_const_stable]` and `#[rustc_const_unstable]` attributes
|
||||
const_stability_interner: ShardedHashMap<&'tcx attr::ConstStability, ()>,
|
||||
|
||||
/// Stores memory for globals (statics/consts).
|
||||
pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
|
||||
|
||||
@ -1092,16 +1094,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self.create_memory_alloc(alloc)
|
||||
}
|
||||
|
||||
// FIXME(eddyb) move to `direct_interners!`.
|
||||
pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
|
||||
self.stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
||||
}
|
||||
|
||||
// FIXME(eddyb) move to `direct_interners!`.
|
||||
pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability {
|
||||
self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab))
|
||||
}
|
||||
|
||||
/// Returns a range of the start/end indices specified with the
|
||||
/// `rustc_layout_scalar_valid_range` attribute.
|
||||
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
|
||||
@ -1185,8 +1177,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
evaluation_cache: Default::default(),
|
||||
crate_name: Symbol::intern(crate_name),
|
||||
data_layout,
|
||||
stability_interner: Default::default(),
|
||||
const_stability_interner: Default::default(),
|
||||
alloc_map: Lock::new(interpret::AllocMap::new()),
|
||||
output_filenames: Arc::new(output_filenames),
|
||||
}
|
||||
@ -1952,11 +1942,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
writeln!(fmt, "InternalSubsts interner: #{}", self.0.interners.substs.len())?;
|
||||
writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?;
|
||||
writeln!(fmt, "Stability interner: #{}", self.0.stability_interner.len())?;
|
||||
writeln!(fmt, "Stability interner: #{}", self.0.interners.stability.len())?;
|
||||
writeln!(
|
||||
fmt,
|
||||
"Const Stability interner: #{}",
|
||||
self.0.const_stability_interner.len()
|
||||
self.0.interners.const_stability.len()
|
||||
)?;
|
||||
writeln!(
|
||||
fmt,
|
||||
@ -1973,7 +1963,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An entry in an interner.
|
||||
// This type holds a `T` in the interner. The `T` is stored in the arena and
|
||||
// this type just holds a pointer to it, but it still effectively owns it. It
|
||||
// impls `Borrow` so that it can be looked up using the original
|
||||
// (non-arena-memory-owning) types.
|
||||
struct Interned<'tcx, T: ?Sized>(&'tcx T);
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> {
|
||||
@ -1981,6 +1974,7 @@ impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> {
|
||||
Interned(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {}
|
||||
|
||||
impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
|
||||
@ -1988,20 +1982,6 @@ impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
|
||||
self.0 as *const _ as *const ()
|
||||
}
|
||||
}
|
||||
// N.B., an `Interned<Ty>` compares and hashes as a `TyKind`.
|
||||
impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
|
||||
fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
|
||||
self.0.kind() == other.0.kind()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {}
|
||||
|
||||
impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
self.0.kind().hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
|
||||
@ -2009,18 +1989,21 @@ impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> {
|
||||
&self.0.kind()
|
||||
}
|
||||
}
|
||||
// N.B., an `Interned<PredicateInner>` compares and hashes as a `PredicateKind`.
|
||||
impl<'tcx> PartialEq for Interned<'tcx, PredicateInner<'tcx>> {
|
||||
fn eq(&self, other: &Interned<'tcx, PredicateInner<'tcx>>) -> bool {
|
||||
self.0.kind == other.0.kind
|
||||
|
||||
impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
|
||||
fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
|
||||
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
|
||||
// `x == y`.
|
||||
self.0.kind() == other.0.kind()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Eq for Interned<'tcx, PredicateInner<'tcx>> {}
|
||||
impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {}
|
||||
|
||||
impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> {
|
||||
impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
self.0.kind.hash(s)
|
||||
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
|
||||
self.0.kind().hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2030,18 +2013,20 @@ impl<'tcx> Borrow<Binder<'tcx, PredicateKind<'tcx>>> for Interned<'tcx, Predicat
|
||||
}
|
||||
}
|
||||
|
||||
// N.B., an `Interned<List<T>>` compares and hashes as its elements.
|
||||
impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> {
|
||||
fn eq(&self, other: &Interned<'tcx, List<T>>) -> bool {
|
||||
self.0[..] == other.0[..]
|
||||
impl<'tcx> PartialEq for Interned<'tcx, PredicateInner<'tcx>> {
|
||||
fn eq(&self, other: &Interned<'tcx, PredicateInner<'tcx>>) -> bool {
|
||||
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
|
||||
// `x == y`.
|
||||
self.0.kind == other.0.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: Eq> Eq for Interned<'tcx, List<T>> {}
|
||||
impl<'tcx> Eq for Interned<'tcx, PredicateInner<'tcx>> {}
|
||||
|
||||
impl<'tcx, T: Hash> Hash for Interned<'tcx, List<T>> {
|
||||
impl<'tcx> Hash for Interned<'tcx, PredicateInner<'tcx>> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
self.0[..].hash(s)
|
||||
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
|
||||
self.0.kind.hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2051,10 +2036,35 @@ impl<'tcx, T> Borrow<[T]> for Interned<'tcx, List<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: PartialEq> PartialEq for Interned<'tcx, List<T>> {
|
||||
fn eq(&self, other: &Interned<'tcx, List<T>>) -> bool {
|
||||
// The `Borrow` trait requires that `x.borrow() == y.borrow()` equals
|
||||
// `x == y`.
|
||||
self.0[..] == other.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: Eq> Eq for Interned<'tcx, List<T>> {}
|
||||
|
||||
impl<'tcx, T: Hash> Hash for Interned<'tcx, List<T>> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
// The `Borrow` trait requires that `x.borrow().hash(s) == x.hash(s)`.
|
||||
self.0[..].hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! direct_interners {
|
||||
($($name:ident: $method:ident($ty:ty),)+) => {
|
||||
$(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
|
||||
$(impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> {
|
||||
fn borrow<'a>(&'a self) -> &'a $ty {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PartialEq for Interned<'tcx, $ty> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
// The `Borrow` trait requires that `x.borrow() == y.borrow()`
|
||||
// equals `x == y`.
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
@ -2063,16 +2073,12 @@ macro_rules! direct_interners {
|
||||
|
||||
impl<'tcx> Hash for Interned<'tcx, $ty> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
// The `Borrow` trait requires that `x.borrow().hash(s) ==
|
||||
// x.hash(s)`.
|
||||
self.0.hash(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> {
|
||||
fn borrow<'a>(&'a self) -> &'a $ty {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn $method(self, v: $ty) -> &'tcx $ty {
|
||||
self.interners.$name.intern(v, |v| {
|
||||
@ -2089,6 +2095,8 @@ direct_interners! {
|
||||
const_allocation: intern_const_alloc(Allocation),
|
||||
layout: intern_layout(Layout),
|
||||
adt_def: intern_adt_def(AdtDef),
|
||||
stability: intern_stability(attr::Stability),
|
||||
const_stability: intern_const_stability(attr::ConstStability),
|
||||
}
|
||||
|
||||
macro_rules! slice_interners {
|
||||
|
@ -376,15 +376,28 @@ pub struct CReaderCacheKey {
|
||||
pub pos: usize,
|
||||
}
|
||||
|
||||
/// Represents a type.
|
||||
///
|
||||
/// IMPORTANT: Every `TyS` is *required* to have unique contents. The type's
|
||||
/// correctness relies on this, *but it does not enforce it*. Therefore, any
|
||||
/// code that creates a `TyS` must ensure uniqueness itself. In practice this
|
||||
/// is achieved by interning.
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
pub struct TyS<'tcx> {
|
||||
/// This field shouldn't be used directly and may be removed in the future.
|
||||
/// Use `TyS::kind()` instead.
|
||||
kind: TyKind<'tcx>,
|
||||
|
||||
/// This field provides fast access to information that is also contained
|
||||
/// in `kind`.
|
||||
///
|
||||
/// This field shouldn't be used directly and may be removed in the future.
|
||||
/// Use `TyS::flags()` instead.
|
||||
flags: TypeFlags,
|
||||
|
||||
/// This field provides fast access to information that is also contained
|
||||
/// in `kind`.
|
||||
///
|
||||
/// This is a kind of confusing thing: it stores the smallest
|
||||
/// binder such that
|
||||
///
|
||||
@ -436,6 +449,8 @@ impl<'tcx> PartialOrd for TyS<'tcx> {
|
||||
impl<'tcx> PartialEq for TyS<'tcx> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &TyS<'tcx>) -> bool {
|
||||
// Pointer equality implies equality (due to the unique contents
|
||||
// assumption).
|
||||
ptr::eq(self, other)
|
||||
}
|
||||
}
|
||||
@ -443,6 +458,8 @@ impl<'tcx> Eq for TyS<'tcx> {}
|
||||
|
||||
impl<'tcx> Hash for TyS<'tcx> {
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
// Pointer hashing is sufficient (due to the unique contents
|
||||
// assumption).
|
||||
(self as *const TyS<'_>).hash(s)
|
||||
}
|
||||
}
|
||||
|
@ -418,7 +418,7 @@ impl BasicCoverageBlockData {
|
||||
pub fn take_edge_counters(
|
||||
&mut self,
|
||||
) -> Option<impl Iterator<Item = (BasicCoverageBlock, CoverageKind)>> {
|
||||
self.edge_from_bcbs.take().map_or(None, |m| Some(m.into_iter()))
|
||||
self.edge_from_bcbs.take().map(|m| m.into_iter())
|
||||
}
|
||||
|
||||
pub fn id(&self) -> String {
|
||||
|
@ -807,10 +807,18 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
self.output.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::Abort { .. } => {
|
||||
let instance = Instance::mono(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::PanicNoUnwind, Some(source)),
|
||||
);
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
self.output.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::Goto { .. }
|
||||
| mir::TerminatorKind::SwitchInt { .. }
|
||||
| mir::TerminatorKind::Resume
|
||||
| mir::TerminatorKind::Abort
|
||||
| mir::TerminatorKind::Return
|
||||
| mir::TerminatorKind::Unreachable => {}
|
||||
mir::TerminatorKind::GeneratorDrop
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Checks validity of naked functions.
|
||||
|
||||
use rustc_ast::{Attribute, InlineAsmOptions};
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{FnKind, Visitor};
|
||||
@ -8,7 +9,6 @@ use rustc_hir::{ExprKind, HirId, InlineAsmOperand, StmtKind};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
|
||||
use rustc_session::lint::builtin::UNSUPPORTED_NAKED_FUNCTIONS;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
@ -64,18 +64,16 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> {
|
||||
check_abi(self.tcx, hir_id, fn_header.abi, ident_span);
|
||||
check_no_patterns(self.tcx, body.params);
|
||||
check_no_parameters_use(self.tcx, body);
|
||||
check_asm(self.tcx, hir_id, body, span);
|
||||
check_inline(self.tcx, hir_id, attrs);
|
||||
check_asm(self.tcx, body, span);
|
||||
check_inline(self.tcx, attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the function isn't inlined.
|
||||
fn check_inline(tcx: TyCtxt<'_>, hir_id: HirId, attrs: &[Attribute]) {
|
||||
fn check_inline(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
||||
for attr in attrs.iter().filter(|attr| attr.has_name(sym::inline)) {
|
||||
tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, attr.span, |lint| {
|
||||
lint.build("naked functions cannot be inlined").emit();
|
||||
});
|
||||
tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,31 +144,31 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
|
||||
}
|
||||
|
||||
/// Checks that function body contains a single inline assembly block.
|
||||
fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
|
||||
fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
|
||||
let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
|
||||
this.visit_body(body);
|
||||
if let [(ItemKind::Asm, _)] = this.items[..] {
|
||||
// Ok.
|
||||
} else {
|
||||
tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| {
|
||||
let mut diag = lint.build("naked functions must contain a single asm block");
|
||||
let mut has_asm = false;
|
||||
for &(kind, span) in &this.items {
|
||||
match kind {
|
||||
ItemKind::Asm if has_asm => {
|
||||
diag.span_label(
|
||||
span,
|
||||
"multiple asm blocks are unsupported in naked functions",
|
||||
);
|
||||
}
|
||||
ItemKind::Asm => has_asm = true,
|
||||
ItemKind::NonAsm => {
|
||||
diag.span_label(span, "non-asm is unsupported in naked functions");
|
||||
}
|
||||
let mut diag = struct_span_err!(
|
||||
tcx.sess,
|
||||
fn_span,
|
||||
E0787,
|
||||
"naked functions must contain a single asm block"
|
||||
);
|
||||
let mut has_asm = false;
|
||||
for &(kind, span) in &this.items {
|
||||
match kind {
|
||||
ItemKind::Asm if has_asm => {
|
||||
diag.span_label(span, "multiple asm blocks are unsupported in naked functions");
|
||||
}
|
||||
ItemKind::Asm => has_asm = true,
|
||||
ItemKind::NonAsm => {
|
||||
diag.span_label(span, "non-asm is unsupported in naked functions");
|
||||
}
|
||||
}
|
||||
diag.emit();
|
||||
});
|
||||
}
|
||||
diag.emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,7 +219,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||
|
||||
ExprKind::InlineAsm(ref asm) => {
|
||||
self.items.push((ItemKind::Asm, span));
|
||||
self.check_inline_asm(expr.hir_id, asm, span);
|
||||
self.check_inline_asm(asm, span);
|
||||
}
|
||||
|
||||
ExprKind::DropTemps(..) | ExprKind::Block(..) | ExprKind::Err => {
|
||||
@ -230,7 +228,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_inline_asm(&self, hir_id: HirId, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
|
||||
fn check_inline_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
|
||||
let unsupported_operands: Vec<Span> = asm
|
||||
.operands
|
||||
.iter()
|
||||
@ -243,18 +241,17 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||
})
|
||||
.collect();
|
||||
if !unsupported_operands.is_empty() {
|
||||
self.tcx.struct_span_lint_hir(
|
||||
UNSUPPORTED_NAKED_FUNCTIONS,
|
||||
hir_id,
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
unsupported_operands,
|
||||
|lint| {
|
||||
lint.build("only `const` and `sym` operands are supported in naked functions")
|
||||
.emit();
|
||||
},
|
||||
);
|
||||
E0787,
|
||||
"only `const` and `sym` operands are supported in naked functions",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
let unsupported_options: Vec<&'static str> = [
|
||||
(InlineAsmOptions::MAY_UNWIND, "`may_unwind`"),
|
||||
(InlineAsmOptions::NOMEM, "`nomem`"),
|
||||
(InlineAsmOptions::NOSTACK, "`nostack`"),
|
||||
(InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
|
||||
@ -266,19 +263,24 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||
.collect();
|
||||
|
||||
if !unsupported_options.is_empty() {
|
||||
self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
|
||||
lint.build(&format!(
|
||||
"asm options unsupported in naked functions: {}",
|
||||
unsupported_options.join(", ")
|
||||
))
|
||||
.emit();
|
||||
});
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0787,
|
||||
"asm options unsupported in naked functions: {}",
|
||||
unsupported_options.join(", ")
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
if !asm.options.contains(InlineAsmOptions::NORETURN) {
|
||||
self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
|
||||
lint.build("asm in naked functions must use `noreturn` option").emit();
|
||||
});
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0787,
|
||||
"asm in naked functions must use `noreturn` option"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::impl_stable_hash_via_hash;
|
||||
|
||||
use rustc_target::abi::{Align, TargetDataLayout};
|
||||
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TargetWarnings};
|
||||
use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
|
||||
|
||||
use rustc_serialize::json;
|
||||
|
||||
@ -2237,6 +2237,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
}
|
||||
}
|
||||
|
||||
if cg.linker_flavor == Some(LinkerFlavor::L4Bender)
|
||||
&& !nightly_options::is_unstable_enabled(matches)
|
||||
{
|
||||
early_error(
|
||||
error_format,
|
||||
"`l4-bender` linker flavor is unstable, `-Z unstable-options` \
|
||||
flag must also be passed to explicitly use it",
|
||||
);
|
||||
}
|
||||
|
||||
let prints = collect_print_requests(&mut cg, &mut debugging_opts, matches, error_format);
|
||||
|
||||
let cg = cg;
|
||||
|
@ -990,6 +990,7 @@ symbols! {
|
||||
panic_implementation,
|
||||
panic_info,
|
||||
panic_location,
|
||||
panic_no_unwind,
|
||||
panic_runtime,
|
||||
panic_str,
|
||||
panic_unwind,
|
||||
|
@ -1,25 +1,14 @@
|
||||
use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions};
|
||||
//use std::process::Command;
|
||||
|
||||
// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
|
||||
// that a few files also come from L4Re, for these, the function shouldn't be
|
||||
// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway.
|
||||
//fn get_path_or(filename: &str) -> String {
|
||||
// let child = Command::new("gcc")
|
||||
// .arg(format!("-print-file-name={}", filename)).output()
|
||||
// .expect("Failed to execute GCC");
|
||||
// String::from_utf8(child.stdout)
|
||||
// .expect("Couldn't read path from GCC").trim().into()
|
||||
//}
|
||||
use std::default::Default;
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
os: "l4re".to_string(),
|
||||
env: "uclibc".to_string(),
|
||||
linker_flavor: LinkerFlavor::Ld,
|
||||
linker_flavor: LinkerFlavor::L4Bender,
|
||||
executables: true,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
linker: Some("ld".to_string()),
|
||||
linker: Some("l4-bender".to_string()),
|
||||
linker_is_gnu: false,
|
||||
families: vec!["unix".to_string()],
|
||||
..Default::default()
|
||||
|
@ -90,6 +90,7 @@ mod windows_uwp_msvc_base;
|
||||
pub enum LinkerFlavor {
|
||||
Em,
|
||||
Gcc,
|
||||
L4Bender,
|
||||
Ld,
|
||||
Msvc,
|
||||
Lld(LldFlavor),
|
||||
@ -160,6 +161,7 @@ macro_rules! flavor_mappings {
|
||||
flavor_mappings! {
|
||||
((LinkerFlavor::Em), "em"),
|
||||
((LinkerFlavor::Gcc), "gcc"),
|
||||
((LinkerFlavor::L4Bender), "l4-bender"),
|
||||
((LinkerFlavor::Ld), "ld"),
|
||||
((LinkerFlavor::Msvc), "msvc"),
|
||||
((LinkerFlavor::PtxLinker), "ptx-linker"),
|
||||
|
@ -1,9 +1,12 @@
|
||||
use crate::spec::Target;
|
||||
use crate::spec::{PanicStrategy, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::l4re_base::opts();
|
||||
base.cpu = "x86-64".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.crt_static_allows_dylibs = false;
|
||||
base.dynamic_linking = false;
|
||||
base.panic_strategy = PanicStrategy::Abort;
|
||||
|
||||
Target {
|
||||
llvm_target: "x86_64-unknown-l4re-uclibc".to_string(),
|
||||
|
@ -31,6 +31,7 @@ pub struct PanicInfo<'a> {
|
||||
payload: &'a (dyn Any + Send),
|
||||
message: Option<&'a fmt::Arguments<'a>>,
|
||||
location: &'a Location<'a>,
|
||||
can_unwind: bool,
|
||||
}
|
||||
|
||||
impl<'a> PanicInfo<'a> {
|
||||
@ -44,9 +45,10 @@ impl<'a> PanicInfo<'a> {
|
||||
pub fn internal_constructor(
|
||||
message: Option<&'a fmt::Arguments<'a>>,
|
||||
location: &'a Location<'a>,
|
||||
can_unwind: bool,
|
||||
) -> Self {
|
||||
struct NoPayload;
|
||||
PanicInfo { location, message, payload: &NoPayload }
|
||||
PanicInfo { location, message, payload: &NoPayload, can_unwind }
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
@ -127,6 +129,18 @@ impl<'a> PanicInfo<'a> {
|
||||
// deal with that case in std::panicking::default_hook and core::panicking::panic_fmt.
|
||||
Some(&self.location)
|
||||
}
|
||||
|
||||
/// Returns whether the panic handler is allowed to unwind the stack from
|
||||
/// the point where the panic occurred.
|
||||
///
|
||||
/// This is true for most kinds of panics with the exception of panics
|
||||
/// caused by trying to unwind out of a `Drop` implementation or a function
|
||||
/// whose ABI does not support unwinding.
|
||||
#[must_use]
|
||||
#[unstable(feature = "panic_can_unwind", issue = "92988")]
|
||||
pub fn can_unwind(&self) -> bool {
|
||||
self.can_unwind
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "panic_hook_display", since = "1.26.0")]
|
||||
|
@ -77,6 +77,31 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
|
||||
panic!("index out of bounds: the len is {} but the index is {}", len, index)
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
#[cold]
|
||||
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
|
||||
#[track_caller]
|
||||
#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
|
||||
fn panic_no_unwind() -> ! {
|
||||
if cfg!(feature = "panic_immediate_abort") {
|
||||
super::intrinsics::abort()
|
||||
}
|
||||
|
||||
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
|
||||
// that gets resolved to the `#[panic_handler]` function.
|
||||
extern "Rust" {
|
||||
#[lang = "panic_impl"]
|
||||
fn panic_impl(pi: &PanicInfo<'_>) -> !;
|
||||
}
|
||||
|
||||
// PanicInfo with the `can_unwind` flag set to false forces an abort.
|
||||
let fmt = format_args!("panic in a function that cannot unwind");
|
||||
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
|
||||
|
||||
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
|
||||
unsafe { panic_impl(&pi) }
|
||||
}
|
||||
|
||||
/// The entry point for panicking with a formatted message.
|
||||
///
|
||||
/// This is designed to reduce the amount of code required at the call
|
||||
@ -104,7 +129,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
|
||||
fn panic_impl(pi: &PanicInfo<'_>) -> !;
|
||||
}
|
||||
|
||||
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller());
|
||||
let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
|
||||
|
||||
// SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
|
||||
unsafe { panic_impl(&pi) }
|
||||
|
@ -39,6 +39,10 @@ cfg_if::cfg_if! {
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
#[path = "hermit.rs"]
|
||||
mod real_imp;
|
||||
} else if #[cfg(target_os = "l4re")] {
|
||||
// L4Re is unix family but does not yet support unwinding.
|
||||
#[path = "dummy.rs"]
|
||||
mod real_imp;
|
||||
} else if #[cfg(target_env = "msvc")] {
|
||||
#[path = "seh.rs"]
|
||||
mod real_imp;
|
||||
|
@ -311,6 +311,7 @@
|
||||
#![feature(once_cell)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(pin_static_ref)]
|
||||
#![feature(portable_simd)]
|
||||
|
@ -576,9 +576,14 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! {
|
||||
let msg = info.message().unwrap(); // The current implementation always returns Some
|
||||
crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||
if let Some(msg) = msg.as_str() {
|
||||
rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc);
|
||||
rust_panic_with_hook(&mut StrPanicPayload(msg), info.message(), loc, info.can_unwind());
|
||||
} else {
|
||||
rust_panic_with_hook(&mut PanicPayload::new(msg), info.message(), loc);
|
||||
rust_panic_with_hook(
|
||||
&mut PanicPayload::new(msg),
|
||||
info.message(),
|
||||
loc,
|
||||
info.can_unwind(),
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -602,7 +607,7 @@ pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
|
||||
|
||||
let loc = Location::caller();
|
||||
return crate::sys_common::backtrace::__rust_end_short_backtrace(move || {
|
||||
rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc)
|
||||
rust_panic_with_hook(&mut PanicPayload::new(msg), None, loc, true)
|
||||
});
|
||||
|
||||
struct PanicPayload<A> {
|
||||
@ -647,6 +652,7 @@ fn rust_panic_with_hook(
|
||||
payload: &mut dyn BoxMeUp,
|
||||
message: Option<&fmt::Arguments<'_>>,
|
||||
location: &Location<'_>,
|
||||
can_unwind: bool,
|
||||
) -> ! {
|
||||
let (must_abort, panics) = panic_count::increase();
|
||||
|
||||
@ -663,14 +669,14 @@ fn rust_panic_with_hook(
|
||||
} else {
|
||||
// Unfortunately, this does not print a backtrace, because creating
|
||||
// a `Backtrace` will allocate, which we must to avoid here.
|
||||
let panicinfo = PanicInfo::internal_constructor(message, location);
|
||||
let panicinfo = PanicInfo::internal_constructor(message, location, can_unwind);
|
||||
rtprintpanic!("{}\npanicked after panic::always_abort(), aborting.\n", panicinfo);
|
||||
}
|
||||
intrinsics::abort()
|
||||
crate::sys::abort_internal();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut info = PanicInfo::internal_constructor(message, location);
|
||||
let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
|
||||
let _guard = HOOK_LOCK.read();
|
||||
match HOOK {
|
||||
// Some platforms (like wasm) know that printing to stderr won't ever actually
|
||||
@ -691,13 +697,13 @@ fn rust_panic_with_hook(
|
||||
};
|
||||
}
|
||||
|
||||
if panics > 1 {
|
||||
if panics > 1 || !can_unwind {
|
||||
// If a thread panics while it's already unwinding then we
|
||||
// have limited options. Currently our preference is to
|
||||
// just abort. In the future we may consider resuming
|
||||
// unwinding or otherwise exiting the thread cleanly.
|
||||
rtprintpanic!("thread panicked while panicking. aborting.\n");
|
||||
intrinsics::abort()
|
||||
crate::sys::abort_internal();
|
||||
}
|
||||
|
||||
rust_panic(payload)
|
||||
|
@ -53,5 +53,10 @@ fn test_command_fork_no_unwind() {
|
||||
let status = got.expect("panic unexpectedly propagated");
|
||||
dbg!(status);
|
||||
let signal = status.signal().expect("expected child process to die of signal");
|
||||
assert!(signal == libc::SIGABRT || signal == libc::SIGILL || signal == libc::SIGTRAP);
|
||||
assert!(
|
||||
signal == libc::SIGABRT
|
||||
|| signal == libc::SIGILL
|
||||
|| signal == libc::SIGTRAP
|
||||
|| signal == libc::SIGSEGV
|
||||
);
|
||||
}
|
||||
|
@ -150,7 +150,6 @@ h1.fqn {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px dashed #DDDDDD;
|
||||
padding-bottom: 6px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// rustdoc format-version.
|
||||
pub const FORMAT_VERSION: u32 = 10;
|
||||
|
||||
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
|
||||
/// about the language items in the local crate, as well as info about external items to allow
|
||||
/// tools to find or link to them.
|
||||
@ -517,8 +520,5 @@ pub struct Static {
|
||||
pub expr: String,
|
||||
}
|
||||
|
||||
/// rustdoc format-version.
|
||||
pub const FORMAT_VERSION: u32 = 9;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -1,42 +1,32 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// needs-asm-support
|
||||
// only-x86_64
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(naked_functions)]
|
||||
use std::arch::asm;
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define{{.*}}void @naked_empty()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_empty() {
|
||||
pub unsafe extern "C" fn naked_empty() {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK-NEXT: ret void
|
||||
// CHECK-NEXT: call void asm
|
||||
// CHECK-NEXT: unreachable
|
||||
asm!("ret",
|
||||
options(noreturn));
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i64 %a, i64 %b)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
// CHECK-NEXT: define{{.*}}void @naked_with_args(i{{[0-9]+( %a)?}})
|
||||
pub fn naked_with_args(a: isize) {
|
||||
pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_return()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_with_return() -> isize {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK-NEXT: ret i{{[0-9]+}} 0
|
||||
0
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked
|
||||
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}})
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub fn naked_with_args_and_return(a: isize) -> isize {
|
||||
// CHECK-NEXT: {{.+}}:
|
||||
// CHECK: ret i{{[0-9]+}} 0
|
||||
0
|
||||
// CHECK-NEXT: call void asm
|
||||
// CHECK-NEXT: unreachable
|
||||
asm!("lea rax, [rdi + rsi]",
|
||||
"ret",
|
||||
options(noreturn));
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
#[inline(always)]
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn f() {
|
||||
|
@ -9,7 +9,7 @@ extern "C-unwind" {
|
||||
|
||||
// CHECK: Function Attrs:{{.*}}nounwind
|
||||
// CHECK-NEXT: define{{.*}}void @foo
|
||||
// CHECK: call void @llvm.trap()
|
||||
// CHECK: call void @_ZN4core9panicking15panic_no_unwind
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn foo() {
|
||||
bar();
|
||||
|
@ -1,3 +1,5 @@
|
||||
// This test checks the position of the information on the code blocks (like
|
||||
// `compile_fail` or `ignore`).
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
goto: ./fn.check_list_code_block.html
|
||||
// If the codeblock is the first element of the docblock, the information tooltip must have
|
||||
|
@ -1,3 +1,4 @@
|
||||
// This test checks that the source code pages sidebar toggle is working as expected.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
click: ".srclink"
|
||||
wait-for: "#sidebar-toggle"
|
||||
|
@ -1,3 +1,5 @@
|
||||
// This test ensures that the "Escape" shortcut is handled correctly based on the
|
||||
// current content displayed.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
// First, we check that the search results are hidden when the Escape key is pressed.
|
||||
write: (".search-input", "test")
|
||||
|
@ -1,5 +1,5 @@
|
||||
goto: file://|DOC_PATH|/lib2/struct.Foo.html
|
||||
// This test checks that the font weight is correctly applied.
|
||||
goto: file://|DOC_PATH|/lib2/struct.Foo.html
|
||||
assert-css: ("//*[@class='docblock item-decl']//a[text()='Alias']", {"font-weight": "400"})
|
||||
assert-css: (
|
||||
"//*[@class='structfield small-section-header']//a[text()='Alias']",
|
||||
|
@ -1,7 +1,7 @@
|
||||
goto: file://|DOC_PATH|/test_docs/huge_amount_of_consts/index.html
|
||||
|
||||
// Make sure that the last two entries are more than 12 pixels apart and not stacked on each other.
|
||||
|
||||
goto: file://|DOC_PATH|/test_docs/huge_amount_of_consts/index.html
|
||||
|
||||
compare-elements-position-near-false: (
|
||||
"//*[@class='item-table']//div[last()-1]",
|
||||
"//*[@class='item-table']//div[last()-3]",
|
||||
|
@ -1,3 +1,4 @@
|
||||
// This test checks that code blocks in list are supported.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
goto: ./fn.check_list_code_block.html
|
||||
assert: ("pre.rust.fn")
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the crate search filtering is handled correctly and changes the results.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
show-text: true
|
||||
write: (".search-input", "test")
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the result colors are as expected.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
// We set the theme so we're sure that the correct values will be used, whatever the computer
|
||||
// this test is running on.
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the search results have the expected width.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
size: (900, 1000)
|
||||
write: (".search-input", "test")
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the "keyword" results have the expected text alongside them.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
write: (".search-input", "CookieMonster")
|
||||
// Waiting for the search results to appear...
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Checks that the first non-empty search result tab is selected if the default/currently selected
|
||||
// one is empty.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
write: (".search-input", "Foo")
|
||||
// Waiting for the search results to appear...
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks multiple things on the sidebar display (width of its elements, colors, etc).
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
show-text: true
|
||||
local-storage: {"rustdoc-theme": "light"}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the interactions with the source code pages are workined as expected.
|
||||
goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
|
||||
// Check that we can click on the line number.
|
||||
click: ".line-numbers > span:nth-child(4)" // This is the span for line 4.
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Ensures that the theme change is working as expected.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
click: "#theme-picker"
|
||||
click: "#theme-choices > button:first-child"
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Checks that the documentation toggles on mobile have the correct position, style and work
|
||||
// as expected.
|
||||
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
|
||||
size: (433, 600)
|
||||
assert-attribute: (".top-doc", {"open": ""})
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the documentation toggles have the correct position, style and work as expected.
|
||||
goto: file://|DOC_PATH|/test_docs/index.html
|
||||
assert-attribute: ("#main-content > details.top-doc", {"open": ""})
|
||||
assert-text: ("#toggle-all-docs", "[−]")
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Checks that the elements in the sidebar are alphabetically sorted.
|
||||
goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
|
||||
assert-text: (".sidebar-links a:nth-of-type(1)", "another")
|
||||
assert-text: (".sidebar-links a:nth-of-type(2)", "func1")
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#![feature(naked_functions)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(asm_const, asm_sym)]
|
||||
#![feature(asm_const, asm_sym, asm_unwind)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::arch::asm;
|
||||
@ -32,8 +32,7 @@ pub unsafe extern "C" fn patterns(
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn inc(a: u32) -> u32 {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
a + 1
|
||||
//~^ ERROR referencing function parameters is not allowed in naked functions
|
||||
}
|
||||
@ -42,21 +41,18 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 {
|
||||
pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
|
||||
asm!("/* {0} */", in(reg) a, options(noreturn));
|
||||
//~^ ERROR referencing function parameters is not allowed in naked functions
|
||||
//~| WARN only `const` and `sym` operands are supported in naked functions
|
||||
//~| WARN this was previously accepted
|
||||
//~| ERROR only `const` and `sym` operands are supported in naked functions
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
(|| a + 1)()
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn unsupported_operands() {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
let mut a = 0usize;
|
||||
let mut b = 0usize;
|
||||
let mut c = 0usize;
|
||||
@ -65,11 +61,9 @@ pub unsafe extern "C" fn unsupported_operands() {
|
||||
const F: usize = 0usize;
|
||||
static G: usize = 0usize;
|
||||
asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
|
||||
//~^ WARN asm in naked functions must use `noreturn` option
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR asm in naked functions must use `noreturn` option
|
||||
in(reg) a,
|
||||
//~^ WARN only `const` and `sym` operands are supported in naked functions
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR only `const` and `sym` operands are supported in naked functions
|
||||
inlateout(reg) b,
|
||||
inout(reg) c,
|
||||
lateout(reg) d,
|
||||
@ -81,31 +75,25 @@ pub unsafe extern "C" fn unsupported_operands() {
|
||||
|
||||
#[naked]
|
||||
pub extern "C" fn missing_assembly() {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub extern "C" fn too_many_asm_blocks() {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
asm!("");
|
||||
//~^ WARN asm in naked functions must use `noreturn` option
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR asm in naked functions must use `noreturn` option
|
||||
asm!("");
|
||||
//~^ WARN asm in naked functions must use `noreturn` option
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR asm in naked functions must use `noreturn` option
|
||||
asm!("");
|
||||
//~^ WARN asm in naked functions must use `noreturn` option
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR asm in naked functions must use `noreturn` option
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
|
||||
#[naked]
|
||||
pub extern "C" fn inner(y: usize) -> usize {
|
||||
//~^ WARN naked functions must contain a single asm block
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions must contain a single asm block
|
||||
*&y
|
||||
//~^ ERROR referencing function parameters is not allowed in naked functions
|
||||
}
|
||||
@ -115,18 +103,21 @@ pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
|
||||
#[naked]
|
||||
unsafe extern "C" fn invalid_options() {
|
||||
asm!("", options(nomem, preserves_flags, noreturn));
|
||||
//~^ WARN asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
||||
}
|
||||
|
||||
#[naked]
|
||||
unsafe extern "C" fn invalid_options_continued() {
|
||||
asm!("", options(readonly, nostack), options(pure));
|
||||
//~^ ERROR asm with the `pure` option must have at least one output
|
||||
//~| WARN asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
||||
//~| WARN this was previously accepted
|
||||
//~| WARN asm in naked functions must use `noreturn` option
|
||||
//~| WARN this was previously accepted
|
||||
//~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
||||
//~| ERROR asm in naked functions must use `noreturn` option
|
||||
}
|
||||
|
||||
#[naked]
|
||||
unsafe extern "C" fn invalid_may_unwind() {
|
||||
asm!("", options(noreturn, may_unwind));
|
||||
//~^ ERROR asm options unsupported in naked functions: `may_unwind`
|
||||
}
|
||||
|
||||
#[naked]
|
||||
@ -177,38 +168,32 @@ pub unsafe extern "C" fn inline_none() {
|
||||
|
||||
#[naked]
|
||||
#[inline]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_hint() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(always)]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_always() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(never)]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_never() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
#[inline(always)]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
#[inline(never)]
|
||||
//~^ WARN naked functions cannot be inlined
|
||||
//~| WARN this was previously accepted
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_all() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: asm with the `pure` option must have at least one output
|
||||
--> $DIR/naked-functions.rs:124:14
|
||||
--> $DIR/naked-functions.rs:111:14
|
||||
|
|
||||
LL | asm!("", options(readonly, nostack), options(pure));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
@ -29,66 +29,54 @@ LL | P { x, y }: P,
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: referencing function parameters is not allowed in naked functions
|
||||
--> $DIR/naked-functions.rs:37:5
|
||||
--> $DIR/naked-functions.rs:36:5
|
||||
|
|
||||
LL | a + 1
|
||||
| ^
|
||||
|
|
||||
= help: follow the calling convention in asm block to use parameters
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:34:1
|
||||
|
|
||||
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | a + 1
|
||||
| | ----- non-asm is unsupported in naked functions
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: `#[warn(unsupported_naked_functions)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
error: referencing function parameters is not allowed in naked functions
|
||||
--> $DIR/naked-functions.rs:43:31
|
||||
--> $DIR/naked-functions.rs:42:31
|
||||
|
|
||||
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
|
||||
| ^
|
||||
|
|
||||
= help: follow the calling convention in asm block to use parameters
|
||||
|
||||
warning: only `const` and `sym` operands are supported in naked functions
|
||||
--> $DIR/naked-functions.rs:43:23
|
||||
error[E0787]: only `const` and `sym` operands are supported in naked functions
|
||||
--> $DIR/naked-functions.rs:42:23
|
||||
|
|
||||
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:50:1
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:48:1
|
||||
|
|
||||
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | (|| a + 1)()
|
||||
| | ------------ non-asm is unsupported in naked functions
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: only `const` and `sym` operands are supported in naked functions
|
||||
--> $DIR/naked-functions.rs:70:10
|
||||
error[E0787]: only `const` and `sym` operands are supported in naked functions
|
||||
--> $DIR/naked-functions.rs:65:10
|
||||
|
|
||||
LL | in(reg) a,
|
||||
| ^^^^^^^^^
|
||||
...
|
||||
LL |
|
||||
LL | inlateout(reg) b,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
LL | inout(reg) c,
|
||||
@ -97,31 +85,24 @@ LL | lateout(reg) d,
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | out(reg) e,
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:67:5
|
||||
error[E0787]: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:63:5
|
||||
|
|
||||
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | in(reg) a,
|
||||
LL | |
|
||||
... |
|
||||
LL | | sym G,
|
||||
LL | | );
|
||||
| |_____^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:57:1
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:54:1
|
||||
|
|
||||
LL | / pub unsafe extern "C" fn unsupported_operands() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let mut a = 0usize;
|
||||
| | ------------------- non-asm is unsupported in naked functions
|
||||
LL | | let mut b = 0usize;
|
||||
@ -136,123 +117,96 @@ LL | | let mut e = 0usize;
|
||||
LL | | );
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:83:1
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:77:1
|
||||
|
|
||||
LL | / pub extern "C" fn missing_assembly() {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:92:5
|
||||
error[E0787]: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:84:5
|
||||
|
|
||||
LL | asm!("");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:95:5
|
||||
error[E0787]: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:86:5
|
||||
|
|
||||
LL | asm!("");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:98:5
|
||||
error[E0787]: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:88:5
|
||||
|
|
||||
LL | asm!("");
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:89:1
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:82:1
|
||||
|
|
||||
LL | / pub extern "C" fn too_many_asm_blocks() {
|
||||
LL | |
|
||||
LL | | asm!("");
|
||||
LL | |
|
||||
LL | | asm!("");
|
||||
... |
|
||||
| | -------- multiple asm blocks are unsupported in naked functions
|
||||
LL | |
|
||||
LL | | asm!("");
|
||||
| | -------- multiple asm blocks are unsupported in naked functions
|
||||
... |
|
||||
LL | | asm!("");
|
||||
| | -------- multiple asm blocks are unsupported in naked functions
|
||||
... |
|
||||
LL | |
|
||||
LL | | asm!("", options(noreturn));
|
||||
| | --------------------------- multiple asm blocks are unsupported in naked functions
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
error: referencing function parameters is not allowed in naked functions
|
||||
--> $DIR/naked-functions.rs:109:11
|
||||
--> $DIR/naked-functions.rs:97:11
|
||||
|
|
||||
LL | *&y
|
||||
| ^
|
||||
|
|
||||
= help: follow the calling convention in asm block to use parameters
|
||||
|
||||
warning: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:106:5
|
||||
error[E0787]: naked functions must contain a single asm block
|
||||
--> $DIR/naked-functions.rs:95:5
|
||||
|
|
||||
LL | / pub extern "C" fn inner(y: usize) -> usize {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | *&y
|
||||
| | --- non-asm is unsupported in naked functions
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
||||
--> $DIR/naked-functions.rs:117:5
|
||||
error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
|
||||
--> $DIR/naked-functions.rs:105:5
|
||||
|
|
||||
LL | asm!("", options(nomem, preserves_flags, noreturn));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
||||
--> $DIR/naked-functions.rs:124:5
|
||||
error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
||||
--> $DIR/naked-functions.rs:111:5
|
||||
|
|
||||
LL | asm!("", options(readonly, nostack), options(pure));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:124:5
|
||||
error[E0787]: asm in naked functions must use `noreturn` option
|
||||
--> $DIR/naked-functions.rs:111:5
|
||||
|
|
||||
LL | asm!("", options(readonly, nostack), options(pure));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0787]: asm options unsupported in naked functions: `may_unwind`
|
||||
--> $DIR/naked-functions.rs:119:5
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
LL | asm!("", options(noreturn, may_unwind));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: Rust ABI is unsupported in naked functions
|
||||
--> $DIR/naked-functions.rs:133:15
|
||||
--> $DIR/naked-functions.rs:124:15
|
||||
|
|
||||
LL | pub unsafe fn default_abi() {
|
||||
| ^^^^^^^^^^^
|
||||
@ -260,64 +214,47 @@ LL | pub unsafe fn default_abi() {
|
||||
= note: `#[warn(undefined_naked_function_abi)]` on by default
|
||||
|
||||
warning: Rust ABI is unsupported in naked functions
|
||||
--> $DIR/naked-functions.rs:139:15
|
||||
--> $DIR/naked-functions.rs:130:15
|
||||
|
|
||||
LL | pub unsafe fn rust_abi() {
|
||||
| ^^^^^^^^
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:179:1
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:170:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:187:1
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:177:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:184:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:191:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:193:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:195:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:203:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:206:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
warning: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:209:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
|
||||
|
||||
error: aborting due to 8 previous errors; 23 warnings emitted
|
||||
error: aborting due to 30 previous errors; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0787`.
|
||||
|
Loading…
Reference in New Issue
Block a user