Auto merge of #120341 - matthiaskrgr:rollup-lvm59cj, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #118208 (Rewrite the BTreeMap cursor API using gaps) - #120099 (linker: Refactor library linking methods in `trait Linker`) - #120288 (Bump `askama` version) - #120306 (Clean up after clone3 removal from pidfd code (docs and tests)) - #120316 (Don't call `walk_` functions directly if there is an equivalent `visit_` method) - #120330 (Remove coroutine info when building coroutine drop body) - #120332 (Remove unused struct) - #120338 (Fix links to [strict|exposed] provenance sections of `[std|core]::ptr`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0c1fb2a1e6
21 changed files with 916 additions and 847 deletions
19
Cargo.lock
19
Cargo.lock
|
@ -212,9 +212,9 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
|||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.12.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e"
|
||||
checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
"askama_escape",
|
||||
|
@ -222,14 +222,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.12.1"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c22fbe0413545c098358e56966ff22cdd039e10215ae213cfbd65032b119fc94"
|
||||
checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
|
||||
dependencies = [
|
||||
"askama_parser",
|
||||
"basic-toml",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"nom",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
|
@ -242,6 +242,15 @@ version = "0.10.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||
|
||||
[[package]]
|
||||
name = "askama_parser"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -375,11 +375,11 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||
}
|
||||
ItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
|
||||
ItemKind::MacroDef(ts) => visitor.visit_mac_def(ts, item.id),
|
||||
ItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
|
||||
ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
visitor.visit_ty(&qself.ty);
|
||||
}
|
||||
walk_path(visitor, path);
|
||||
visitor.visit_path(path, *id);
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
|
@ -502,7 +502,7 @@ where
|
|||
}
|
||||
GenericArgs::Parenthesized(data) => {
|
||||
walk_list!(visitor, visit_ty, &data.inputs);
|
||||
walk_fn_ret_ty(visitor, &data.output);
|
||||
visitor.visit_fn_ret_ty(&data.output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -713,11 +713,11 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
|
|||
AssocItemKind::MacCall(mac) => {
|
||||
visitor.visit_mac_call(mac);
|
||||
}
|
||||
AssocItemKind::Delegation(box Delegation { id: _, qself, path, body }) => {
|
||||
AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
|
||||
if let Some(qself) = qself {
|
||||
visitor.visit_ty(&qself.ty);
|
||||
}
|
||||
walk_path(visitor, path);
|
||||
visitor.visit_path(path, *id);
|
||||
if let Some(body) = body {
|
||||
visitor.visit_block(body);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,15 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::{ExitStatus, Output, Stdio};
|
||||
use std::{env, fmt, fs, io, mem, str};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SearchPaths(OnceCell<Vec<PathBuf>>);
|
||||
|
||||
impl SearchPaths {
|
||||
pub(super) fn get(&self, sess: &Session) -> &[PathBuf] {
|
||||
self.0.get_or_init(|| archive_search_paths(sess))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_removed(dcx: &DiagCtxt, path: &Path) {
|
||||
if let Err(e) = fs::remove_file(path) {
|
||||
if e.kind() != io::ErrorKind::NotFound {
|
||||
|
@ -1265,7 +1274,7 @@ fn link_sanitizer_runtime(
|
|||
let path = find_sanitizer_runtime(sess, &filename);
|
||||
let rpath = path.to_str().expect("non-utf8 component in path");
|
||||
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||
linker.link_dylib(&filename, false, true);
|
||||
linker.link_dylib_by_name(&filename, false, true);
|
||||
} else if sess.target.is_like_msvc && flavor == LinkerFlavor::Msvc(Lld::No) && name == "asan" {
|
||||
// MSVC provides the `/INFERASANLIBS` argument to automatically find the
|
||||
// compatible ASAN library.
|
||||
|
@ -1273,7 +1282,7 @@ fn link_sanitizer_runtime(
|
|||
} else {
|
||||
let filename = format!("librustc{channel}_rt.{name}.a");
|
||||
let path = find_sanitizer_runtime(sess, &filename).join(&filename);
|
||||
linker.link_whole_rlib(&path);
|
||||
linker.link_staticlib_by_path(&path, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2445,7 +2454,7 @@ fn add_native_libs_from_crate(
|
|||
archive_builder_builder: &dyn ArchiveBuilderBuilder,
|
||||
codegen_results: &CodegenResults,
|
||||
tmpdir: &Path,
|
||||
search_paths: &OnceCell<Vec<PathBuf>>,
|
||||
search_paths: &SearchPaths,
|
||||
bundled_libs: &FxHashSet<Symbol>,
|
||||
cnum: CrateNum,
|
||||
link_static: bool,
|
||||
|
@ -2505,28 +2514,16 @@ fn add_native_libs_from_crate(
|
|||
if let Some(filename) = lib.filename {
|
||||
// If rlib contains native libs as archives, they are unpacked to tmpdir.
|
||||
let path = tmpdir.join(filename.as_str());
|
||||
if whole_archive {
|
||||
cmd.link_whole_rlib(&path);
|
||||
} else {
|
||||
cmd.link_rlib(&path);
|
||||
}
|
||||
cmd.link_staticlib_by_path(&path, whole_archive);
|
||||
}
|
||||
} else {
|
||||
if whole_archive {
|
||||
cmd.link_whole_staticlib(
|
||||
name,
|
||||
verbatim,
|
||||
search_paths.get_or_init(|| archive_search_paths(sess)),
|
||||
);
|
||||
} else {
|
||||
cmd.link_staticlib(name, verbatim)
|
||||
}
|
||||
cmd.link_staticlib_by_name(name, verbatim, whole_archive, search_paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
NativeLibKind::Dylib { as_needed } => {
|
||||
if link_dynamic {
|
||||
cmd.link_dylib(name, verbatim, as_needed.unwrap_or(true))
|
||||
cmd.link_dylib_by_name(name, verbatim, as_needed.unwrap_or(true))
|
||||
}
|
||||
}
|
||||
NativeLibKind::Unspecified => {
|
||||
|
@ -2534,17 +2531,17 @@ fn add_native_libs_from_crate(
|
|||
// link kind is unspecified.
|
||||
if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs {
|
||||
if link_static {
|
||||
cmd.link_staticlib(name, verbatim)
|
||||
cmd.link_staticlib_by_name(name, verbatim, false, search_paths);
|
||||
}
|
||||
} else {
|
||||
if link_dynamic {
|
||||
cmd.link_dylib(name, verbatim, true);
|
||||
cmd.link_dylib_by_name(name, verbatim, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
NativeLibKind::Framework { as_needed } => {
|
||||
if link_dynamic {
|
||||
cmd.link_framework(name, as_needed.unwrap_or(true))
|
||||
cmd.link_framework_by_name(name, verbatim, as_needed.unwrap_or(true))
|
||||
}
|
||||
}
|
||||
NativeLibKind::RawDylib => {
|
||||
|
@ -2581,7 +2578,7 @@ fn add_local_native_libraries(
|
|||
}
|
||||
}
|
||||
|
||||
let search_paths = OnceCell::new();
|
||||
let search_paths = SearchPaths::default();
|
||||
// All static and dynamic native library dependencies are linked to the local crate.
|
||||
let link_static = true;
|
||||
let link_dynamic = true;
|
||||
|
@ -2623,7 +2620,7 @@ fn add_upstream_rust_crates<'a>(
|
|||
.find(|(ty, _)| *ty == crate_type)
|
||||
.expect("failed to find crate type in dependency format list");
|
||||
|
||||
let search_paths = OnceCell::new();
|
||||
let search_paths = SearchPaths::default();
|
||||
for &cnum in &codegen_results.crate_info.used_crates {
|
||||
// We may not pass all crates through to the linker. Some crates may appear statically in
|
||||
// an existing dylib, meaning we'll pick up all the symbols from the dylib.
|
||||
|
@ -2698,7 +2695,7 @@ fn add_upstream_native_libraries(
|
|||
tmpdir: &Path,
|
||||
link_output_kind: LinkOutputKind,
|
||||
) {
|
||||
let search_path = OnceCell::new();
|
||||
let search_paths = SearchPaths::default();
|
||||
for &cnum in &codegen_results.crate_info.used_crates {
|
||||
// Static libraries are not linked here, they are linked in `add_upstream_rust_crates`.
|
||||
// FIXME: Merge this function to `add_upstream_rust_crates` so that all native libraries
|
||||
|
@ -2720,7 +2717,7 @@ fn add_upstream_native_libraries(
|
|||
archive_builder_builder,
|
||||
codegen_results,
|
||||
tmpdir,
|
||||
&search_path,
|
||||
&search_paths,
|
||||
&Default::default(),
|
||||
cnum,
|
||||
link_static,
|
||||
|
@ -2791,7 +2788,7 @@ fn add_static_crate<'a>(
|
|||
} else {
|
||||
fix_windows_verbatim_for_gcc(path)
|
||||
};
|
||||
cmd.link_rlib(&rlib_path);
|
||||
cmd.link_staticlib_by_path(&rlib_path, false);
|
||||
};
|
||||
|
||||
if !are_upstream_rust_objects_already_included(sess)
|
||||
|
@ -2859,13 +2856,24 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
|||
// Just need to tell the linker about where the library lives and
|
||||
// what its name is
|
||||
let parent = cratepath.parent();
|
||||
// When producing a dll, the MSVC linker may not actually emit a
|
||||
// `foo.lib` file if the dll doesn't actually export any symbols, so we
|
||||
// check to see if the file is there and just omit linking to it if it's
|
||||
// not present.
|
||||
if sess.target.is_like_msvc && !cratepath.with_extension("dll.lib").exists() {
|
||||
return;
|
||||
}
|
||||
if let Some(dir) = parent {
|
||||
cmd.include_path(&rehome_sysroot_lib_dir(sess, dir));
|
||||
}
|
||||
let stem = cratepath.file_stem().unwrap().to_str().unwrap();
|
||||
// "<dir>/name.dll -> name.dll" on windows-msvc
|
||||
// "<dir>/name.dll -> name" on windows-gnu
|
||||
// "<dir>/libname.<ext> -> name" elsewhere
|
||||
let stem = if sess.target.is_like_msvc { cratepath.file_name() } else { cratepath.file_stem() };
|
||||
let stem = stem.unwrap().to_str().unwrap();
|
||||
// Convert library file-stem into a cc -l argument.
|
||||
let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 };
|
||||
cmd.link_rust_dylib(&stem[prefix..], parent.unwrap_or_else(|| Path::new("")));
|
||||
cmd.link_dylib_by_name(&stem[prefix..], false, true);
|
||||
}
|
||||
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::command::Command;
|
||||
use super::symbol_export;
|
||||
use crate::back::link::SearchPaths;
|
||||
use crate::errors;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
|
@ -166,13 +167,18 @@ pub fn get_linker<'a>(
|
|||
pub trait Linker {
|
||||
fn cmd(&mut self) -> &mut Command;
|
||||
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path);
|
||||
fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool);
|
||||
fn link_rust_dylib(&mut self, lib: &str, path: &Path);
|
||||
fn link_framework(&mut self, framework: &str, as_needed: bool);
|
||||
fn link_staticlib(&mut self, lib: &str, verbatim: bool);
|
||||
fn link_rlib(&mut self, lib: &Path);
|
||||
fn link_whole_rlib(&mut self, lib: &Path);
|
||||
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]);
|
||||
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool);
|
||||
fn link_framework_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
bug!("framework linked with unsupported linker")
|
||||
}
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
verbatim: bool,
|
||||
whole_archive: bool,
|
||||
search_paths: &SearchPaths,
|
||||
);
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool);
|
||||
fn include_path(&mut self, path: &Path);
|
||||
fn framework_path(&mut self, path: &Path);
|
||||
fn output_filename(&mut self, path: &Path);
|
||||
|
@ -432,8 +438,8 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, lib: &str, verbatim: bool, as_needed: bool) {
|
||||
if self.sess.target.os == "illumos" && lib == "c" {
|
||||
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) {
|
||||
if self.sess.target.os == "illumos" && name == "c" {
|
||||
// libc will be added via late_link_args on illumos so that it will
|
||||
// appear last in the library search order.
|
||||
// FIXME: This should be replaced by a more complete and generic
|
||||
|
@ -454,7 +460,7 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
self.hint_dynamic();
|
||||
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
|
||||
self.cmd.arg(format!("-l{}{name}", if verbatim && self.is_gnu { ":" } else { "" },));
|
||||
if !as_needed {
|
||||
if self.sess.target.is_like_osx {
|
||||
// See above FIXME comment
|
||||
|
@ -463,14 +469,56 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
|
||||
|
||||
fn link_framework_by_name(&mut self, name: &str, _verbatim: bool, as_needed: bool) {
|
||||
self.hint_dynamic();
|
||||
if !as_needed {
|
||||
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
|
||||
// flag but we have no way to detect that here.
|
||||
// self.cmd.arg("-needed_framework").arg(name);
|
||||
self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
|
||||
}
|
||||
self.cmd.arg("-framework").arg(name);
|
||||
}
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
verbatim: bool,
|
||||
whole_archive: bool,
|
||||
search_paths: &SearchPaths,
|
||||
) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(lib);
|
||||
let colon = if verbatim && self.is_gnu { ":" } else { "" };
|
||||
if !whole_archive {
|
||||
self.cmd.arg(format!("-l{colon}{name}"));
|
||||
} else if self.sess.target.is_like_osx {
|
||||
// -force_load is the macOS equivalent of --whole-archive, but it
|
||||
// involves passing the full path to the library to link.
|
||||
self.linker_arg("-force_load");
|
||||
let search_paths = search_paths.get(self.sess);
|
||||
self.linker_arg(find_native_static_library(name, verbatim, search_paths, self.sess));
|
||||
} else {
|
||||
self.linker_arg("--whole-archive");
|
||||
self.cmd.arg(format!("-l{colon}{name}"));
|
||||
self.linker_arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
|
||||
self.hint_static();
|
||||
if !whole_archive {
|
||||
self.cmd.arg(path);
|
||||
} else if self.sess.target.is_like_osx {
|
||||
self.linker_arg("-force_load");
|
||||
self.linker_arg(path);
|
||||
} else {
|
||||
self.linker_arg("--whole-archive");
|
||||
self.linker_arg(path);
|
||||
self.linker_arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
}
|
||||
|
@ -493,55 +541,6 @@ impl<'a> Linker for GccLinker<'a> {
|
|||
self.linker_args(&["-z", "norelro"]);
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
||||
self.hint_dynamic();
|
||||
self.cmd.arg(format!("-l{lib}"));
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, framework: &str, as_needed: bool) {
|
||||
self.hint_dynamic();
|
||||
if !as_needed {
|
||||
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
|
||||
// flag but we have no way to detect that here.
|
||||
// self.cmd.arg("-needed_framework").arg(framework);
|
||||
self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier);
|
||||
}
|
||||
self.cmd.arg("-framework").arg(framework);
|
||||
}
|
||||
|
||||
// Here we explicitly ask that the entire archive is included into the
|
||||
// result artifact. For more details see #15460, but the gist is that
|
||||
// the linker will strip away any unused objects in the archive if we
|
||||
// don't otherwise explicitly reference them. This can occur for
|
||||
// libraries which are just providing bindings, libraries with generic
|
||||
// functions, etc.
|
||||
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
|
||||
self.hint_static();
|
||||
let target = &self.sess.target;
|
||||
if !target.is_like_osx {
|
||||
self.linker_arg("--whole-archive");
|
||||
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
|
||||
self.linker_arg("--no-whole-archive");
|
||||
} else {
|
||||
// -force_load is the macOS equivalent of --whole-archive, but it
|
||||
// involves passing the full path to the library to link.
|
||||
self.linker_arg("-force_load");
|
||||
let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
|
||||
self.linker_arg(&lib);
|
||||
}
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
self.hint_static();
|
||||
if self.sess.target.is_like_osx {
|
||||
self.linker_arg("-force_load");
|
||||
self.linker_arg(&lib);
|
||||
} else {
|
||||
self.linker_args(&[OsString::from("--whole-archive"), lib.into()]);
|
||||
self.linker_arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, keep_metadata: bool) {
|
||||
// The dead_strip option to the linker specifies that functions and data
|
||||
// unreachable by the entry point will be removed. This is quite useful
|
||||
|
@ -821,9 +820,32 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
self.cmd.arg(lib);
|
||||
fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, _as_needed: bool) {
|
||||
self.cmd.arg(format!("{}{}", name, if verbatim { "" } else { ".lib" }));
|
||||
}
|
||||
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
verbatim: bool,
|
||||
whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
let prefix = if whole_archive { "/WHOLEARCHIVE:" } else { "" };
|
||||
let suffix = if verbatim { "" } else { ".lib" };
|
||||
self.cmd.arg(format!("{prefix}{name}{suffix}"));
|
||||
}
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
|
||||
if !whole_archive {
|
||||
self.cmd.arg(path);
|
||||
} else {
|
||||
let mut arg = OsString::from("/WHOLEARCHIVE:");
|
||||
arg.push(path);
|
||||
self.cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_object(&mut self, path: &Path) {
|
||||
self.cmd.arg(path);
|
||||
}
|
||||
|
@ -845,25 +867,6 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
self.cmd.arg("/OPT:NOREF,NOICF");
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) {
|
||||
self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" }));
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
|
||||
// When producing a dll, the MSVC linker may not actually emit a
|
||||
// `foo.lib` file if the dll doesn't actually export any symbols, so we
|
||||
// check to see if the file is there and just omit linking to it if it's
|
||||
// not present.
|
||||
let name = format!("{lib}.dll.lib");
|
||||
if path.join(&name).exists() {
|
||||
self.cmd.arg(name);
|
||||
}
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
|
||||
self.cmd.arg(format!("{}{}", lib, if verbatim { "" } else { ".lib" }));
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
@ -899,18 +902,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
|||
fn framework_path(&mut self, _path: &Path) {
|
||||
bug!("frameworks are not supported on windows")
|
||||
}
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
bug!("frameworks are not supported on windows")
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
|
||||
self.cmd.arg(format!("/WHOLEARCHIVE:{}{}", lib, if verbatim { "" } else { ".lib" }));
|
||||
}
|
||||
fn link_whole_rlib(&mut self, path: &Path) {
|
||||
let mut arg = OsString::from("/WHOLEARCHIVE:");
|
||||
arg.push(path);
|
||||
self.cmd.arg(arg);
|
||||
}
|
||||
fn optimize(&mut self) {
|
||||
// Needs more investigation of `/OPT` arguments
|
||||
}
|
||||
|
@ -1057,12 +1049,27 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
|
||||
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
// Emscripten always links statically
|
||||
self.cmd.arg("-l").arg(name);
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
_verbatim: bool,
|
||||
_whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
self.cmd.arg("-l").arg(name);
|
||||
}
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
|
||||
self.cmd.arg(path);
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
}
|
||||
|
||||
fn output_filename(&mut self, path: &Path) {
|
||||
|
@ -1073,29 +1080,6 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
self.cmd.arg(path);
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, lib: &str, verbatim: bool, _as_needed: bool) {
|
||||
// Emscripten always links statically
|
||||
self.link_staticlib(lib, verbatim);
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, _search_path: &[PathBuf]) {
|
||||
// not supported?
|
||||
self.link_staticlib(lib, verbatim);
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
// not supported?
|
||||
self.link_rlib(lib);
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
||||
self.link_dylib(lib, false, true);
|
||||
}
|
||||
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
self.add_object(lib);
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
// noop
|
||||
}
|
||||
|
@ -1112,10 +1096,6 @@ impl<'a> Linker for EmLinker<'a> {
|
|||
bug!("frameworks are not supported on Emscripten")
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
bug!("frameworks are not supported on Emscripten")
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {
|
||||
// noop
|
||||
}
|
||||
|
@ -1249,16 +1229,30 @@ impl<'a> Linker for WasmLd<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
self.cmd.arg("-l").arg(name);
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
_verbatim: bool,
|
||||
whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
if !whole_archive {
|
||||
self.cmd.arg("-l").arg(name);
|
||||
} else {
|
||||
self.cmd.arg("--whole-archive").arg("-l").arg(name).arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
self.cmd.arg(lib);
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
|
||||
if !whole_archive {
|
||||
self.cmd.arg(path);
|
||||
} else {
|
||||
self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
|
@ -1283,22 +1277,6 @@ impl<'a> Linker for WasmLd<'a> {
|
|||
|
||||
fn no_relro(&mut self) {}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
|
||||
self.cmd.arg("--whole-archive").arg("-l").arg(lib).arg("--no-whole-archive");
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
self.cmd.arg("--whole-archive").arg(lib).arg("--no-whole-archive");
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {
|
||||
self.cmd.arg("--gc-sections");
|
||||
}
|
||||
|
@ -1398,17 +1376,40 @@ pub struct L4Bender<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Linker for L4Bender<'a> {
|
||||
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
|
||||
fn cmd(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
|
||||
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
|
||||
|
||||
fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
bug!("dylibs are not supported on L4Re");
|
||||
}
|
||||
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
|
||||
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
_verbatim: bool,
|
||||
whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(format!("-PC{lib}"));
|
||||
if !whole_archive {
|
||||
self.cmd.arg(format!("-PC{name}"));
|
||||
} else {
|
||||
self.cmd.arg("--whole-archive").arg(format!("-l{name}")).arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(lib);
|
||||
if !whole_archive {
|
||||
self.cmd.arg(path);
|
||||
} else {
|
||||
self.cmd.arg("--whole-archive").arg(path).arg("--no-whole-archive");
|
||||
}
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
}
|
||||
|
@ -1436,31 +1437,6 @@ impl<'a> Linker for L4Bender<'a> {
|
|||
self.cmd.arg("-z").arg("norelro");
|
||||
}
|
||||
|
||||
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, _: &str, _: &Path) {
|
||||
panic!("Rust dylibs not supported");
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
bug!("frameworks not supported on L4Re");
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, _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");
|
||||
|
@ -1571,19 +1547,56 @@ impl<'a> AixLinker<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Linker for AixLinker<'a> {
|
||||
fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) {
|
||||
fn cmd(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
|
||||
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
|
||||
match output_kind {
|
||||
LinkOutputKind::DynamicDylib => {
|
||||
self.hint_dynamic();
|
||||
self.build_dylib(out_filename);
|
||||
}
|
||||
LinkOutputKind::StaticDylib => {
|
||||
self.hint_static();
|
||||
self.build_dylib(out_filename);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
self.hint_dynamic();
|
||||
self.cmd.arg(format!("-l{lib}"));
|
||||
self.cmd.arg(format!("-l{name}"));
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, lib: &str, _verbatim: bool) {
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
name: &str,
|
||||
verbatim: bool,
|
||||
whole_archive: bool,
|
||||
search_paths: &SearchPaths,
|
||||
) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(format!("-l{lib}"));
|
||||
if !whole_archive {
|
||||
self.cmd.arg(format!("-l{name}"));
|
||||
} else {
|
||||
let mut arg = OsString::from("-bkeepfile:");
|
||||
let search_path = search_paths.get(self.sess);
|
||||
arg.push(find_native_static_library(name, verbatim, search_path, self.sess));
|
||||
self.cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, whole_archive: bool) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(lib);
|
||||
if !whole_archive {
|
||||
self.cmd.arg(path);
|
||||
} else {
|
||||
let mut arg = OsString::from("-bkeepfile:");
|
||||
arg.push(path);
|
||||
self.cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
|
@ -1608,44 +1621,6 @@ impl<'a> Linker for AixLinker<'a> {
|
|||
|
||||
fn no_relro(&mut self) {}
|
||||
|
||||
fn cmd(&mut self) -> &mut Command {
|
||||
&mut self.cmd
|
||||
}
|
||||
|
||||
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
|
||||
match output_kind {
|
||||
LinkOutputKind::DynamicDylib => {
|
||||
self.hint_dynamic();
|
||||
self.build_dylib(out_filename);
|
||||
}
|
||||
LinkOutputKind::StaticDylib => {
|
||||
self.hint_static();
|
||||
self.build_dylib(out_filename);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _: &Path) {
|
||||
self.hint_dynamic();
|
||||
self.cmd.arg(format!("-l{lib}"));
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
bug!("frameworks not supported on AIX");
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) {
|
||||
self.hint_static();
|
||||
let lib = find_native_static_library(lib, verbatim, search_path, self.sess);
|
||||
self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap()));
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
self.hint_static();
|
||||
self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap()));
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {
|
||||
self.cmd.arg("-bgc");
|
||||
}
|
||||
|
@ -1810,11 +1785,21 @@ impl<'a> Linker for PtxLinker<'a> {
|
|||
|
||||
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
|
||||
|
||||
fn link_rlib(&mut self, path: &Path) {
|
||||
self.cmd.arg("--rlib").arg(path);
|
||||
fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, path: &Path) {
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
_name: &str,
|
||||
_verbatim: bool,
|
||||
_whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
|
||||
self.cmd.arg("--rlib").arg(path);
|
||||
}
|
||||
|
||||
|
@ -1844,30 +1829,10 @@ impl<'a> Linker for PtxLinker<'a> {
|
|||
self.cmd.arg("-o").arg(path);
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn framework_path(&mut self, _path: &Path) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {}
|
||||
|
||||
fn partial_relro(&mut self) {}
|
||||
|
@ -1907,11 +1872,21 @@ impl<'a> Linker for BpfLinker<'a> {
|
|||
|
||||
fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
|
||||
|
||||
fn link_rlib(&mut self, path: &Path) {
|
||||
self.cmd.arg(path);
|
||||
fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, path: &Path) {
|
||||
fn link_staticlib_by_name(
|
||||
&mut self,
|
||||
_name: &str,
|
||||
_verbatim: bool,
|
||||
_whole_archive: bool,
|
||||
_search_paths: &SearchPaths,
|
||||
) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
|
||||
self.cmd.arg(path);
|
||||
}
|
||||
|
||||
|
@ -1942,30 +1917,10 @@ impl<'a> Linker for BpfLinker<'a> {
|
|||
self.cmd.arg("-o").arg(path);
|
||||
}
|
||||
|
||||
fn link_dylib(&mut self, _lib: &str, _verbatim: bool, _as_needed: bool) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
|
||||
panic!("external dylibs not supported")
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, _lib: &str, _verbatim: bool) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, _lib: &str, _verbatim: bool, _search_path: &[PathBuf]) {
|
||||
panic!("staticlibs not supported")
|
||||
}
|
||||
|
||||
fn framework_path(&mut self, _path: &Path) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str, _as_needed: bool) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {}
|
||||
|
||||
fn partial_relro(&mut self) {}
|
||||
|
|
|
@ -244,18 +244,23 @@ impl<'tcx> MirSource<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Additional information carried by a MIR body when it is lowered from a coroutine.
|
||||
/// This information is modified as it is lowered during the `StateTransform` MIR pass,
|
||||
/// so not all fields will be active at a given time. For example, the `yield_ty` is
|
||||
/// taken out of the field after yields are turned into returns, and the `coroutine_drop`
|
||||
/// body is only populated after the state transform pass.
|
||||
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub struct CoroutineInfo<'tcx> {
|
||||
/// The yield type of the function, if it is a coroutine.
|
||||
/// The yield type of the function. This field is removed after the state transform pass.
|
||||
pub yield_ty: Option<Ty<'tcx>>,
|
||||
|
||||
/// The resume type of the function, if it is a coroutine.
|
||||
/// The resume type of the function. This field is removed after the state transform pass.
|
||||
pub resume_ty: Option<Ty<'tcx>>,
|
||||
|
||||
/// Coroutine drop glue.
|
||||
/// Coroutine drop glue. This field is populated after the state transform pass.
|
||||
pub coroutine_drop: Option<Body<'tcx>>,
|
||||
|
||||
/// The layout of a coroutine. Produced by the state transformation.
|
||||
/// The layout of a coroutine. This field is populated after the state transform pass.
|
||||
pub coroutine_layout: Option<CoroutineLayout<'tcx>>,
|
||||
|
||||
/// If this is a coroutine then record the type of source expression that caused this coroutine
|
||||
|
@ -303,6 +308,12 @@ pub struct Body<'tcx> {
|
|||
/// and used for debuginfo. Indexed by a `SourceScope`.
|
||||
pub source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
|
||||
|
||||
/// Additional information carried by a MIR body when it is lowered from a coroutine.
|
||||
///
|
||||
/// Note that the coroutine drop shim, any promoted consts, and other synthetic MIR
|
||||
/// bodies that come from processing a coroutine body are not typically coroutines
|
||||
/// themselves, and should probably set this to `None` to avoid carrying redundant
|
||||
/// information.
|
||||
pub coroutine: Option<Box<CoroutineInfo<'tcx>>>,
|
||||
|
||||
/// Declarations of locals.
|
||||
|
|
|
@ -1231,7 +1231,12 @@ fn create_coroutine_drop_shim<'tcx>(
|
|||
drop_clean: BasicBlock,
|
||||
) -> Body<'tcx> {
|
||||
let mut body = body.clone();
|
||||
body.arg_count = 1; // make sure the resume argument is not included here
|
||||
// Take the coroutine info out of the body, since the drop shim is
|
||||
// not a coroutine body itself; it just has its drop built out of it.
|
||||
let _ = body.coroutine.take();
|
||||
// Make sure the resume argument is not included here, since we're
|
||||
// building a body for `drop_in_place`.
|
||||
body.arg_count = 1;
|
||||
|
||||
let source_info = SourceInfo::outermost(body.span);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2349,112 +2349,151 @@ fn test_cursor() {
|
|||
let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
|
||||
let mut cur = map.lower_bound(Bound::Unbounded);
|
||||
assert_eq!(cur.key(), Some(&1));
|
||||
cur.move_next();
|
||||
assert_eq!(cur.key(), Some(&2));
|
||||
assert_eq!(cur.peek_next(), Some((&3, &'c')));
|
||||
cur.move_prev();
|
||||
assert_eq!(cur.key(), Some(&1));
|
||||
assert_eq!(cur.peek_next(), Some((&1, &'a')));
|
||||
assert_eq!(cur.peek_prev(), None);
|
||||
assert_eq!(cur.prev(), None);
|
||||
assert_eq!(cur.next(), Some((&1, &'a')));
|
||||
|
||||
assert_eq!(cur.next(), Some((&2, &'b')));
|
||||
|
||||
assert_eq!(cur.peek_next(), Some((&3, &'c')));
|
||||
assert_eq!(cur.prev(), Some((&2, &'b')));
|
||||
assert_eq!(cur.peek_prev(), Some((&1, &'a')));
|
||||
|
||||
let mut cur = map.upper_bound(Bound::Excluded(&1));
|
||||
assert_eq!(cur.key(), None);
|
||||
cur.move_next();
|
||||
assert_eq!(cur.key(), Some(&1));
|
||||
cur.move_prev();
|
||||
assert_eq!(cur.key(), None);
|
||||
assert_eq!(cur.peek_prev(), Some((&3, &'c')));
|
||||
assert_eq!(cur.peek_prev(), None);
|
||||
assert_eq!(cur.next(), Some((&1, &'a')));
|
||||
assert_eq!(cur.prev(), Some((&1, &'a')));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cursor_mut() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]);
|
||||
let mut cur = map.lower_bound_mut(Bound::Excluded(&3));
|
||||
assert_eq!(cur.key(), Some(&5));
|
||||
cur.insert_before(4, 'd');
|
||||
assert_eq!(cur.key(), Some(&5));
|
||||
assert_eq!(cur.peek_next(), Some((&5, &mut 'e')));
|
||||
assert_eq!(cur.peek_prev(), Some((&3, &mut 'c')));
|
||||
|
||||
cur.insert_before(4, 'd').unwrap();
|
||||
assert_eq!(cur.peek_next(), Some((&5, &mut 'e')));
|
||||
assert_eq!(cur.peek_prev(), Some((&4, &mut 'd')));
|
||||
cur.move_next();
|
||||
assert_eq!(cur.key(), None);
|
||||
cur.insert_before(6, 'f');
|
||||
assert_eq!(cur.key(), None);
|
||||
assert_eq!(cur.remove_current(), None);
|
||||
assert_eq!(cur.key(), None);
|
||||
cur.insert_after(0, '?');
|
||||
assert_eq!(cur.key(), None);
|
||||
assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]));
|
||||
|
||||
assert_eq!(cur.next(), Some((&5, &mut 'e')));
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.peek_prev(), Some((&5, &mut 'e')));
|
||||
cur.insert_before(6, 'f').unwrap();
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.peek_prev(), Some((&6, &mut 'f')));
|
||||
assert_eq!(cur.remove_prev(), Some((6, 'f')));
|
||||
assert_eq!(cur.remove_prev(), Some((5, 'e')));
|
||||
assert_eq!(cur.remove_next(), None);
|
||||
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')]));
|
||||
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&5));
|
||||
assert_eq!(cur.key(), Some(&5));
|
||||
assert_eq!(cur.remove_current(), Some((5, 'e')));
|
||||
assert_eq!(cur.key(), Some(&6));
|
||||
assert_eq!(cur.remove_current_and_move_back(), Some((6, 'f')));
|
||||
assert_eq!(cur.key(), Some(&4));
|
||||
assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')]));
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.prev(), Some((&4, &mut 'd')));
|
||||
assert_eq!(cur.peek_next(), Some((&4, &mut 'd')));
|
||||
assert_eq!(cur.peek_prev(), Some((&3, &mut 'c')));
|
||||
assert_eq!(cur.remove_next(), Some((4, 'd')));
|
||||
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cursor_mut_key() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]);
|
||||
let mut cur = unsafe { map.lower_bound_mut(Bound::Excluded(&3)).with_mutable_key() };
|
||||
assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e')));
|
||||
assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c')));
|
||||
|
||||
cur.insert_before(4, 'd').unwrap();
|
||||
assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e')));
|
||||
assert_eq!(cur.peek_prev(), Some((&mut 4, &mut 'd')));
|
||||
|
||||
assert_eq!(cur.next(), Some((&mut 5, &mut 'e')));
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.peek_prev(), Some((&mut 5, &mut 'e')));
|
||||
cur.insert_before(6, 'f').unwrap();
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.peek_prev(), Some((&mut 6, &mut 'f')));
|
||||
assert_eq!(cur.remove_prev(), Some((6, 'f')));
|
||||
assert_eq!(cur.remove_prev(), Some((5, 'e')));
|
||||
assert_eq!(cur.remove_next(), None);
|
||||
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')]));
|
||||
|
||||
let mut cur = unsafe { map.upper_bound_mut(Bound::Included(&5)).with_mutable_key() };
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.prev(), Some((&mut 4, &mut 'd')));
|
||||
assert_eq!(cur.peek_next(), Some((&mut 4, &mut 'd')));
|
||||
assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c')));
|
||||
assert_eq!(cur.remove_next(), Some((4, 'd')));
|
||||
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cursor_empty() {
|
||||
let mut map = BTreeMap::new();
|
||||
let mut cur = map.lower_bound_mut(Bound::Excluded(&3));
|
||||
assert_eq!(cur.peek_next(), None);
|
||||
assert_eq!(cur.peek_prev(), None);
|
||||
cur.insert_after(0, 0).unwrap();
|
||||
assert_eq!(cur.peek_next(), Some((&0, &mut 0)));
|
||||
assert_eq!(cur.peek_prev(), None);
|
||||
assert_eq!(map, BTreeMap::from([(0, 0)]));
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the previous element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_1() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(0, 'd');
|
||||
cur.insert_before(0, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the previous element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_2() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(1, 'd');
|
||||
cur.insert_before(1, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_3() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(2, 'd');
|
||||
cur.insert_before(2, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_4() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(3, 'd');
|
||||
cur.insert_before(3, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_1() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(1, 'd');
|
||||
cur.insert_after(1, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_2() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(2, 'd');
|
||||
cur.insert_after(2, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the next element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_3() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(3, 'd');
|
||||
cur.insert_after(3, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the next element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_4() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(4, 'd');
|
||||
cur.insert_after(4, 'd').unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2462,14 +2501,14 @@ fn cursor_peek_prev_agrees_with_cursor_mut() {
|
|||
let mut map = BTreeMap::from([(1, 1), (2, 2), (3, 3)]);
|
||||
|
||||
let cursor = map.lower_bound(Bound::Excluded(&3));
|
||||
assert!(cursor.key().is_none());
|
||||
assert!(cursor.peek_next().is_none());
|
||||
|
||||
let prev = cursor.peek_prev();
|
||||
assert_matches!(prev, Some((&3, _)));
|
||||
|
||||
// Shadow names so the two parts of this test match.
|
||||
let mut cursor = map.lower_bound_mut(Bound::Excluded(&3));
|
||||
assert!(cursor.key().is_none());
|
||||
assert!(cursor.peek_next().is_none());
|
||||
|
||||
let prev = cursor.peek_prev();
|
||||
assert_matches!(prev, Some((&3, _)));
|
||||
|
|
|
@ -648,17 +648,36 @@ impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
|
|||
|
||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||
/// Adds a key-value pair to the end of the node, and returns
|
||||
/// the mutable reference of the inserted value.
|
||||
pub fn push(&mut self, key: K, val: V) -> &mut V {
|
||||
/// a handle to the inserted value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The returned handle has an unbound lifetime.
|
||||
pub unsafe fn push_with_handle<'b>(
|
||||
&mut self,
|
||||
key: K,
|
||||
val: V,
|
||||
) -> Handle<NodeRef<marker::Mut<'b>, K, V, marker::Leaf>, marker::KV> {
|
||||
let len = self.len_mut();
|
||||
let idx = usize::from(*len);
|
||||
assert!(idx < CAPACITY);
|
||||
*len += 1;
|
||||
unsafe {
|
||||
self.key_area_mut(idx).write(key);
|
||||
self.val_area_mut(idx).write(val)
|
||||
self.val_area_mut(idx).write(val);
|
||||
Handle::new_kv(
|
||||
NodeRef { height: self.height, node: self.node, _marker: PhantomData },
|
||||
idx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a key-value pair to the end of the node, and returns
|
||||
/// the mutable reference of the inserted value.
|
||||
pub fn push(&mut self, key: K, val: V) -> *mut V {
|
||||
// SAFETY: The unbound handle is no longer accessible.
|
||||
unsafe { self.push_with_handle(key, val).into_val_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
|
@ -1100,10 +1119,10 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
|
|||
unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }
|
||||
}
|
||||
|
||||
pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) {
|
||||
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
|
||||
debug_assert!(self.idx < self.node.len());
|
||||
let leaf = self.node.into_leaf_mut();
|
||||
let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() };
|
||||
let k = unsafe { leaf.keys.get_unchecked_mut(self.idx).assume_init_mut() };
|
||||
let v = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() };
|
||||
(k, v)
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ impl<T: ?Sized> *const T {
|
|||
/// provenance. (Reconstructing address space information, if required, is your responsibility.)
|
||||
///
|
||||
/// Using this method means that code is *not* following [Strict
|
||||
/// Provenance][../index.html#strict-provenance] rules. Supporting
|
||||
/// Provenance][super#strict-provenance] rules. Supporting
|
||||
/// [`from_exposed_addr`][] complicates specification and reasoning and may not be supported by
|
||||
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
|
||||
/// use [`addr`][pointer::addr] wherever possible.
|
||||
|
@ -232,7 +232,7 @@ impl<T: ?Sized> *const T {
|
|||
/// available.
|
||||
///
|
||||
/// It is unclear whether this method can be given a satisfying unambiguous specification. This
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance].
|
||||
///
|
||||
/// [`from_exposed_addr`]: from_exposed_addr
|
||||
#[must_use]
|
||||
|
|
|
@ -649,7 +649,7 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
|
|||
/// address makes sense in the address space that this pointer will be used with.
|
||||
///
|
||||
/// Using this function means that code is *not* following [Strict
|
||||
/// Provenance][../index.html#strict-provenance] rules. "Guessing" a
|
||||
/// Provenance][self#strict-provenance] rules. "Guessing" a
|
||||
/// suitable provenance complicates specification and reasoning and may not be supported by
|
||||
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
|
||||
/// use [`with_addr`][pointer::with_addr] wherever possible.
|
||||
|
@ -660,7 +660,7 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
|
|||
/// pointer has to pick up.
|
||||
///
|
||||
/// It is unclear whether this function can be given a satisfying unambiguous specification. This
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][self#exposed-provenance].
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "exposed_provenance", issue = "95228")]
|
||||
|
@ -689,7 +689,7 @@ where
|
|||
/// address makes sense in the address space that this pointer will be used with.
|
||||
///
|
||||
/// Using this function means that code is *not* following [Strict
|
||||
/// Provenance][../index.html#strict-provenance] rules. "Guessing" a
|
||||
/// Provenance][self#strict-provenance] rules. "Guessing" a
|
||||
/// suitable provenance complicates specification and reasoning and may not be supported by
|
||||
/// tools that help you to stay conformant with the Rust memory model, so it is recommended to
|
||||
/// use [`with_addr`][pointer::with_addr] wherever possible.
|
||||
|
@ -700,7 +700,7 @@ where
|
|||
/// pointer has to pick up.
|
||||
///
|
||||
/// It is unclear whether this function can be given a satisfying unambiguous specification. This
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][self#exposed-provenance].
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "exposed_provenance", issue = "95228")]
|
||||
|
|
|
@ -227,7 +227,7 @@ impl<T: ?Sized> *mut T {
|
|||
/// provenance. (Reconstructing address space information, if required, is your responsibility.)
|
||||
///
|
||||
/// Using this method means that code is *not* following [Strict
|
||||
/// Provenance][../index.html#strict-provenance] rules. Supporting
|
||||
/// Provenance][super#strict-provenance] rules. Supporting
|
||||
/// [`from_exposed_addr_mut`][] complicates specification and reasoning and may not be supported
|
||||
/// by tools that help you to stay conformant with the Rust memory model, so it is recommended
|
||||
/// to use [`addr`][pointer::addr] wherever possible.
|
||||
|
@ -239,7 +239,7 @@ impl<T: ?Sized> *mut T {
|
|||
/// available.
|
||||
///
|
||||
/// It is unclear whether this method can be given a satisfying unambiguous specification. This
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][../index.html#exposed-provenance].
|
||||
/// API and its claimed semantics are part of [Exposed Provenance][super#exposed-provenance].
|
||||
///
|
||||
/// [`from_exposed_addr_mut`]: from_exposed_addr_mut
|
||||
#[must_use]
|
||||
|
|
|
@ -149,8 +149,7 @@ pub trait CommandExt: Sealed {
|
|||
/// The pidfd can be retrieved from the child with [`pidfd`] or [`take_pidfd`].
|
||||
///
|
||||
/// A pidfd will only be created if it is possible to do so
|
||||
/// in a guaranteed race-free manner (e.g. if the `clone3` system call
|
||||
/// is supported). Otherwise, [`pidfd`] will return an error.
|
||||
/// in a guaranteed race-free manner. Otherwise, [`pidfd`] will return an error.
|
||||
///
|
||||
/// If a pidfd has been successfully created and not been taken from the `Child`
|
||||
/// then calls to `kill()`, `wait()` and `try_wait()` will use the pidfd
|
||||
|
|
|
@ -147,8 +147,7 @@ impl Command {
|
|||
#[cfg(not(target_os = "linux"))]
|
||||
let pidfd = -1;
|
||||
|
||||
// Safety: We obtained the pidfd from calling `clone3` with
|
||||
// `CLONE_PIDFD` so it's valid an otherwise unowned.
|
||||
// Safety: We obtained the pidfd (on Linux) using SOCK_SEQPACKET, so it's valid.
|
||||
let mut p = unsafe { Process::new(pid, pidfd) };
|
||||
let mut bytes = [0; 8];
|
||||
|
||||
|
|
|
@ -62,13 +62,14 @@ fn test_command_fork_no_unwind() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(target_os = "linux")] // pidfds are a linux-specific concept
|
||||
fn test_command_pidfd() {
|
||||
use crate::assert_matches::assert_matches;
|
||||
use crate::os::fd::{AsRawFd, RawFd};
|
||||
use crate::os::linux::process::{ChildExt, CommandExt};
|
||||
use crate::process::Command;
|
||||
|
||||
// pidfds require the pidfd_open syscall
|
||||
let our_pid = crate::process::id();
|
||||
let pidfd = unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) };
|
||||
let pidfd_open_available = if pidfd >= 0 {
|
||||
|
@ -81,7 +82,9 @@ fn test_command_pidfd() {
|
|||
// always exercise creation attempts
|
||||
let mut child = Command::new("false").create_pidfd(true).spawn().unwrap();
|
||||
|
||||
// but only check if we know that the kernel supports pidfds
|
||||
// but only check if we know that the kernel supports pidfds.
|
||||
// We don't assert the precise value, since the standard library
|
||||
// might have opened other file descriptors before our code runs.
|
||||
if pidfd_open_available {
|
||||
assert!(child.pidfd().is_ok());
|
||||
}
|
||||
|
@ -97,4 +100,17 @@ fn test_command_pidfd() {
|
|||
child.kill().expect("failed to kill child");
|
||||
let status = child.wait().expect("error waiting on pidfd");
|
||||
assert_eq!(status.signal(), Some(libc::SIGKILL));
|
||||
|
||||
let _ = Command::new("echo")
|
||||
.create_pidfd(false)
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.pidfd()
|
||||
.expect_err("pidfd should not have been created when create_pid(false) is set");
|
||||
|
||||
let _ = Command::new("echo")
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.pidfd()
|
||||
.expect_err("pidfd should not have been created");
|
||||
}
|
||||
|
|
|
@ -106,7 +106,18 @@ mod imp {
|
|||
// supported on the current kernel.
|
||||
//
|
||||
// Also fall back in case it is disabled by something like
|
||||
// seccomp or inside of virtual machines.
|
||||
// seccomp or inside of docker.
|
||||
//
|
||||
// If the `getrandom` syscall is not implemented in the current kernel version it should return an
|
||||
// `ENOSYS` error. Docker also blocks the whole syscall inside unprivileged containers, and
|
||||
// returns `EPERM` (instead of `ENOSYS`) when a program tries to invoke the syscall. Because of
|
||||
// that we need to check for *both* `ENOSYS` and `EPERM`.
|
||||
//
|
||||
// Note that Docker's behavior is breaking other projects (notably glibc), so they're planning
|
||||
// to update their filtering to return `ENOSYS` in a future release:
|
||||
//
|
||||
// https://github.com/moby/moby/issues/42680
|
||||
//
|
||||
GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
|
||||
return false;
|
||||
} else if err == libc::EAGAIN {
|
||||
|
|
|
@ -364,7 +364,4 @@ pub mod netc {
|
|||
pub sin6_flowinfo: u32,
|
||||
pub sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sockaddr {}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<pre class="rust item-decl"><code>
|
||||
{{ self.render_attributes_in_pre() | safe }}
|
||||
{{ self.render_union() | safe }}
|
||||
{{ self.render_attributes_in_pre()|safe }}
|
||||
{{ self.render_union()|safe }}
|
||||
</code></pre>
|
||||
{{ self.document() | safe }}
|
||||
{{ self.document()|safe }}
|
||||
{% if self.fields_iter().peek().is_some() %}
|
||||
<h2 id="fields" class="fields section-header"> {# #}
|
||||
Fields<a href="#fields" class="anchor">§</a> {# #}
|
||||
|
@ -12,13 +12,13 @@
|
|||
<span id="structfield.{{ name }}" {#+ #}
|
||||
class="{{ ItemType::StructField +}} section-header"> {# #}
|
||||
<a href="#structfield.{{ name }}" class="anchor field">§</a> {# #}
|
||||
<code>{{ name }}: {{+ self.print_ty(ty) | safe }}</code> {# #}
|
||||
<code>{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
|
||||
</span>
|
||||
{% if let Some(stability_class) = self.stability_field(field) %}
|
||||
<span class="stab {{ stability_class }}"></span>
|
||||
{% endif %}
|
||||
{{ self.document_field(field) | safe }}
|
||||
{{ self.document_field(field)|safe }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ self.render_assoc_items() | safe }}
|
||||
{{ self.document_type_layout() | safe }}
|
||||
{{ self.render_assoc_items()|safe }}
|
||||
{{ self.document_type_layout()|safe }}
|
||||
|
|
|
@ -1,25 +1,4 @@
|
|||
// MIR for `main::{closure#0}` 0 coroutine_drop
|
||||
/* coroutine_layout = CoroutineLayout {
|
||||
field_tys: {
|
||||
_0: CoroutineSavedTy {
|
||||
ty: std::string::String,
|
||||
source_info: SourceInfo {
|
||||
span: $DIR/coroutine_drop_cleanup.rs:12:13: 12:15 (#0),
|
||||
scope: scope[0],
|
||||
},
|
||||
ignore_for_traits: false,
|
||||
},
|
||||
},
|
||||
variant_fields: {
|
||||
Unresumed(0): [],
|
||||
Returned (1): [],
|
||||
Panicked (2): [],
|
||||
Suspend0 (3): [_0],
|
||||
},
|
||||
storage_conflicts: BitMatrix(1x1) {
|
||||
(_0, _0),
|
||||
},
|
||||
} */
|
||||
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
|
||||
let mut _0: ();
|
||||
|
|
|
@ -1,25 +1,4 @@
|
|||
// MIR for `main::{closure#0}` 0 coroutine_drop
|
||||
/* coroutine_layout = CoroutineLayout {
|
||||
field_tys: {
|
||||
_0: CoroutineSavedTy {
|
||||
ty: std::string::String,
|
||||
source_info: SourceInfo {
|
||||
span: $DIR/coroutine_drop_cleanup.rs:12:13: 12:15 (#0),
|
||||
scope: scope[0],
|
||||
},
|
||||
ignore_for_traits: false,
|
||||
},
|
||||
},
|
||||
variant_fields: {
|
||||
Unresumed(0): [],
|
||||
Returned (1): [],
|
||||
Panicked (2): [],
|
||||
Suspend0 (3): [_0],
|
||||
},
|
||||
storage_conflicts: BitMatrix(1x1) {
|
||||
(_0, _0),
|
||||
},
|
||||
} */
|
||||
|
||||
fn main::{closure#0}(_1: *mut {coroutine@$DIR/coroutine_drop_cleanup.rs:11:15: 11:17}) -> () {
|
||||
let mut _0: ();
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
// run-pass
|
||||
// only-linux - pidfds are a linux-specific concept
|
||||
|
||||
#![feature(linux_pidfd)]
|
||||
#![feature(rustc_private)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use std::io::Error;
|
||||
use std::os::linux::process::{ChildExt, CommandExt};
|
||||
use std::process::Command;
|
||||
|
||||
fn has_clone3() -> bool {
|
||||
let res = unsafe { libc::syscall(libc::SYS_clone3, 0, 0) };
|
||||
let err = (res == -1)
|
||||
.then(|| Error::last_os_error())
|
||||
.expect("probe syscall should not succeed");
|
||||
|
||||
// If the `clone3` syscall is not implemented in the current kernel version it should return an
|
||||
// `ENOSYS` error. Docker also blocks the whole syscall inside unprivileged containers, and
|
||||
// returns `EPERM` (instead of `ENOSYS`) when a program tries to invoke the syscall. Because of
|
||||
// that we need to check for *both* `ENOSYS` and `EPERM`.
|
||||
//
|
||||
// Note that Docker's behavior is breaking other projects (notably glibc), so they're planning
|
||||
// to update their filtering to return `ENOSYS` in a future release:
|
||||
//
|
||||
// https://github.com/moby/moby/issues/42680
|
||||
//
|
||||
err.raw_os_error() != Some(libc::ENOSYS) && err.raw_os_error() != Some(libc::EPERM)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// pidfds require the clone3 syscall
|
||||
if !has_clone3() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't assert the precise value, since the standard library
|
||||
// might have opened other file descriptors before our code runs.
|
||||
let _ = Command::new("echo")
|
||||
.create_pidfd(true)
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.pidfd().expect("failed to obtain pidfd");
|
||||
|
||||
let _ = Command::new("echo")
|
||||
.create_pidfd(false)
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.pidfd().expect_err("pidfd should not have been created when create_pid(false) is set");
|
||||
|
||||
let _ = Command::new("echo")
|
||||
.spawn()
|
||||
.unwrap()
|
||||
.pidfd().expect_err("pidfd should not have been created");
|
||||
}
|
Loading…
Add table
Reference in a new issue