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:
bors 2022-01-22 19:26:42 +00:00
commit bfe1564676
49 changed files with 584 additions and 411 deletions

View File

@ -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",

View File

@ -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,
)),

View File

@ -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();

View File

@ -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 } => {

View File

@ -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

View 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

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -990,6 +990,7 @@ symbols! {
panic_implementation,
panic_info,
panic_location,
panic_no_unwind,
panic_runtime,
panic_str,
panic_unwind,

View File

@ -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()

View File

@ -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"),

View File

@ -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(),

View File

@ -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")]

View File

@ -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) }

View File

@ -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;

View File

@ -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)]

View File

@ -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)

View File

@ -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
);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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));
}

View File

@ -7,7 +7,6 @@
use std::arch::asm;
#[inline(always)]
#[naked]
#[no_mangle]
pub unsafe extern "C" fn f() {

View File

@ -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();

View File

@ -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

View File

@ -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"

View File

@ -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")

View File

@ -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']",

View File

@ -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]",

View File

@ -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")

View File

@ -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")

View File

@ -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.

View File

@ -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")

View File

@ -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...

View File

@ -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...

View File

@ -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"}

View File

@ -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.

View File

@ -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"

View File

@ -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": ""})

View File

@ -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", "[]")

View File

@ -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")

View File

@ -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));
}

View File

@ -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`.