From 9ccf4f22c91bbe9ce295d274d86820597be76c37 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 28 Sep 2019 12:04:06 -0700 Subject: [PATCH 01/14] Stabilize --extern flag without a path. --- src/doc/rustc/src/command-line-arguments.md | 7 ++++++- src/librustc/session/config.rs | 7 ------- src/librustdoc/config.rs | 4 ---- src/test/run-make-fulldeps/extern-flag-fun/Makefile | 1 - src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile | 3 +-- 5 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 5eea9c8687900..8ff3b463ae2b9 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -233,7 +233,12 @@ This flag, when combined with other flags, makes them produce extra output. This flag allows you to pass the name and location of an external crate that will be linked into the crate you are building. This flag may be specified -multiple times. The format of the value should be `CRATENAME=PATH`. +multiple times. This flag takes an argument with either of the following +formats: + +* `CRATENAME=PATH` — Indicates the given crate is found at the given path. +* `CRATENAME` — Indicates the given crate may be found in the search path, + such as within the sysroot or via the `-L` flag. ## `--sysroot`: Override the system root diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 675e3bbd002b0..19e618e9fcac6 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2449,13 +2449,6 @@ fn parse_externs( let name = parts.next().unwrap_or_else(|| early_error(error_format, "--extern value must not be empty")); let location = parts.next().map(|s| s.to_string()); - if location.is_none() && !is_unstable_enabled { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to \ - enable `--extern crate_name` without `=path`", - ); - }; let entry = externs .entry(name.to_owned()) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 1c0d1b3273731..1f37db574dcec 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -611,10 +611,6 @@ fn parse_externs(matches: &getopts::Matches) -> Result { let mut parts = arg.splitn(2, '='); let name = parts.next().ok_or("--extern value must not be empty".to_string())?; let location = parts.next().map(|s| s.to_string()); - if location.is_none() && !nightly_options::is_unstable_enabled(matches) { - return Err("the `-Z unstable-options` flag must also be passed to \ - enable `--extern crate_name` without `=path`".to_string()); - } let name = name.to_string(); // For Rustdoc purposes, we can treat all externs as public externs.entry(name) diff --git a/src/test/run-make-fulldeps/extern-flag-fun/Makefile b/src/test/run-make-fulldeps/extern-flag-fun/Makefile index a9f2585335003..7f54d6ea3bc6c 100644 --- a/src/test/run-make-fulldeps/extern-flag-fun/Makefile +++ b/src/test/run-make-fulldeps/extern-flag-fun/Makefile @@ -4,7 +4,6 @@ all: $(RUSTC) bar.rs --crate-type=rlib $(RUSTC) bar.rs --crate-type=rlib -C extra-filename=-a $(RUSTC) bar-alt.rs --crate-type=rlib - $(RUSTC) foo.rs --extern hello && exit 1 || exit 0 $(RUSTC) foo.rs --extern bar=no-exist && exit 1 || exit 0 $(RUSTC) foo.rs --extern bar=foo.rs && exit 1 || exit 0 $(RUSTC) foo.rs \ diff --git a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile index bf98fcd10cfde..36288c4b870e7 100644 --- a/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile +++ b/src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile @@ -1,8 +1,7 @@ -include ../tools.mk all: extern_absolute_paths.rs krate2 - $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 \ - -Z unstable-options --extern krate2 + $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 --extern krate2 cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py krate2: krate2.rs From 04c2c6083958c7c4b2f96685410f50c3442768ff Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 29 Sep 2019 18:17:27 -0700 Subject: [PATCH 02/14] Add more --extern tests. --- .../extern-flag-pathless/Makefile | 18 ++++++++++++++++++ .../extern-flag-pathless/bar-dynamic.rs | 3 +++ .../extern-flag-pathless/bar-static.rs | 3 +++ .../extern-flag-pathless/foo.rs | 3 +++ src/test/rustdoc/inline_cross/use_crate.rs | 2 +- .../ui-fulldeps/pathless-extern-unstable.rs | 10 ++++++++++ .../pathless-extern-unstable.stderr | 12 ++++++++++++ src/test/ui/pathless-extern-ok.rs | 9 +++++++++ 8 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/Makefile create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-pathless/foo.rs create mode 100644 src/test/ui-fulldeps/pathless-extern-unstable.rs create mode 100644 src/test/ui-fulldeps/pathless-extern-unstable.stderr create mode 100644 src/test/ui/pathless-extern-ok.rs diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/Makefile b/src/test/run-make-fulldeps/extern-flag-pathless/Makefile new file mode 100644 index 0000000000000..4849fc62f4a95 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test mixing pathless --extern with paths. + +all: + $(RUSTC) bar-static.rs --crate-name=bar --crate-type=rlib + $(RUSTC) bar-dynamic.rs --crate-name=bar --crate-type=dylib -C prefer-dynamic + # rlib preferred over dylib + $(RUSTC) foo.rs --extern bar + $(call RUN,foo) | $(CGREP) 'static' + $(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib --extern bar + $(call RUN,foo) | $(CGREP) 'static' + # explicit --extern overrides pathless + $(RUSTC) foo.rs --extern bar=$(call DYLIB,bar) --extern bar + $(call RUN,foo) | $(CGREP) 'dynamic' + # prefer-dynamic does what it says + $(RUSTC) foo.rs --extern bar -C prefer-dynamic + $(call RUN,foo) | $(CGREP) 'dynamic' diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs b/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs new file mode 100644 index 0000000000000..e2d68d517ff97 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/bar-dynamic.rs @@ -0,0 +1,3 @@ +pub fn f() { + println!("dynamic"); +} diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs b/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs new file mode 100644 index 0000000000000..240d8bde4d186 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/bar-static.rs @@ -0,0 +1,3 @@ +pub fn f() { + println!("static"); +} diff --git a/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs b/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs new file mode 100644 index 0000000000000..1ea64da7dad26 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-pathless/foo.rs @@ -0,0 +1,3 @@ +fn main() { + bar::f(); +} diff --git a/src/test/rustdoc/inline_cross/use_crate.rs b/src/test/rustdoc/inline_cross/use_crate.rs index f678ba0a46c0d..00e0f041c56fe 100644 --- a/src/test/rustdoc/inline_cross/use_crate.rs +++ b/src/test/rustdoc/inline_cross/use_crate.rs @@ -2,7 +2,7 @@ // aux-build:use_crate_2.rs // build-aux-docs // edition:2018 -// compile-flags:--extern use_crate --extern use_crate_2 -Z unstable-options +// compile-flags:--extern use_crate --extern use_crate_2 // During the buildup to Rust 2018, rustdoc would eagerly inline `pub use some_crate;` as if it // were a module, so we changed it to make `pub use`ing crate roots remain as a `pub use` statement diff --git a/src/test/ui-fulldeps/pathless-extern-unstable.rs b/src/test/ui-fulldeps/pathless-extern-unstable.rs new file mode 100644 index 0000000000000..a5a31816c9572 --- /dev/null +++ b/src/test/ui-fulldeps/pathless-extern-unstable.rs @@ -0,0 +1,10 @@ +// ignore-stage1 +// edition:2018 +// compile-flags:--extern rustc + +// Test that `--extern rustc` fails with `rustc_private`. + +pub use rustc; +//~^ use of unstable library feature 'rustc_private' + +fn main() {} diff --git a/src/test/ui-fulldeps/pathless-extern-unstable.stderr b/src/test/ui-fulldeps/pathless-extern-unstable.stderr new file mode 100644 index 0000000000000..edc3b1c58be22 --- /dev/null +++ b/src/test/ui-fulldeps/pathless-extern-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead? + --> $DIR/pathless-extern-unstable.rs:7:9 + | +LL | pub use rustc; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/27812 + = help: add `#![feature(rustc_private)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/pathless-extern-ok.rs b/src/test/ui/pathless-extern-ok.rs new file mode 100644 index 0000000000000..0ffa5eb894040 --- /dev/null +++ b/src/test/ui/pathless-extern-ok.rs @@ -0,0 +1,9 @@ +// edition:2018 +// compile-flags:--extern alloc +// build-pass + +// Test that `--extern alloc` will load from the sysroot without error. + +fn main() { + let _: Vec = alloc::vec::Vec::new(); +} From 8e62a016e4605e3e3aca77e04d21095a3812493c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 29 Sep 2019 18:17:48 -0700 Subject: [PATCH 03/14] Update built-in help for --extern. --- src/librustc/session/config.rs | 2 +- src/librustdoc/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 19e618e9fcac6..07fd71632d167 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1804,7 +1804,7 @@ pub fn rustc_optgroups() -> Vec { "", "extern", "Specify where an external rust library is located", - "NAME=PATH", + "NAME[=PATH]", ), opt::multi_s( "", diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 6bcb4a817d78e..c0b665dc64a20 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -139,7 +139,7 @@ fn opts() -> Vec { }), stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), stable("extern", |o| { - o.optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH") + o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]") }), unstable("extern-html-root-url", |o| { o.optmulti("", "extern-html-root-url", From 414d7cf4a28197d9ac622ce76a6e9ea085da0858 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 29 Sep 2019 18:20:03 -0700 Subject: [PATCH 04/14] Update extern linking documentation. --- src/doc/rustc/src/codegen-options/index.md | 6 ++++- src/doc/rustc/src/command-line-arguments.md | 29 ++++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index e73fd43f19a51..2026e36e34a05 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -119,7 +119,11 @@ in software. ## prefer-dynamic By default, `rustc` prefers to statically link dependencies. This option will -make it use dynamic linking instead. +indicate that dynamic linking should be used if possible if both a static and +dynamic versions of a library are available. There is an internal algorithm +for determining whether or not it is possible to statically or dynamically +link with a dependency. For example, `cdylib` crate types may only use static +linkage. ## no-integrated-as diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 8ff3b463ae2b9..7e9b4833ef0a4 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -16,9 +16,9 @@ For examples, `--cfg 'verbose'` or `--cfg 'feature="serde"'`. These correspond to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively. ## `-L`: add a directory to the library search path + -When looking for external crates or libraries, a directory passed to this flag -will be searched. +The `-L` flag adds a path to search for external crates and libraries. The kind of search path can optionally be specified with the form `-L KIND=PATH` where `KIND` may be one of: @@ -231,15 +231,32 @@ This flag, when combined with other flags, makes them produce extra output. ## `--extern`: specify where an external library is located -This flag allows you to pass the name and location of an external crate that -will be linked into the crate you are building. This flag may be specified -multiple times. This flag takes an argument with either of the following -formats: +This flag allows you to pass the name and location for an external crate of a +direct dependency. Indirect dependencies (dependencies of dependencies) are +located using the [`-L` flag](#option-l-search-path). The given crate name is +added to the [extern prelude], which is the same as specifying `extern crate` +within the root module. The given crate name does not need to match the name +the library was built with. + +This flag may be specified multiple times. This flag takes an argument with +either of the following formats: * `CRATENAME=PATH` — Indicates the given crate is found at the given path. * `CRATENAME` — Indicates the given crate may be found in the search path, such as within the sysroot or via the `-L` flag. +The same crate name may be specified multiple times for different crate types. +For loading metadata, `rlib` takes precedence over `rmeta`, which takes +precedence over `dylib`. If both an `rlib` and `dylib` are found, an internal +algorithm is used to decide which to use for linking. The [`-C prefer-dynamic` +flag][prefer-dynamic] may be used to influence which is used. + +If the same crate name is specified with and without a path, the one with the +path is used and the pathless flag has no effect. + +[extern prelude]: ../reference/items/extern-crates.html#extern-prelude +[prefer-dynamic]: codegen-options/index.md#prefer-dynamic + ## `--sysroot`: Override the system root The "sysroot" is where `rustc` looks for the crates that come with the Rust From 6d4776693d478c2f298139676b691bae9d50f899 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 7 Oct 2019 07:58:28 -0700 Subject: [PATCH 05/14] Update src/test/ui-fulldeps/pathless-extern-unstable.rs Add ERROR Co-Authored-By: Mazdak Farrokhzad --- src/test/ui-fulldeps/pathless-extern-unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui-fulldeps/pathless-extern-unstable.rs b/src/test/ui-fulldeps/pathless-extern-unstable.rs index a5a31816c9572..00b3ec5409ff0 100644 --- a/src/test/ui-fulldeps/pathless-extern-unstable.rs +++ b/src/test/ui-fulldeps/pathless-extern-unstable.rs @@ -5,6 +5,6 @@ // Test that `--extern rustc` fails with `rustc_private`. pub use rustc; -//~^ use of unstable library feature 'rustc_private' +//~^ ERROR use of unstable library feature 'rustc_private' fn main() {} From 5e678cfb2931ce04bc7d5b66308bdbf0a5d46db2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 8 Oct 2019 09:45:24 -0700 Subject: [PATCH 06/14] Add test for --extern alloc=librustc.rlib --- src/test/run-make-fulldeps/extern-flag-fun/Makefile | 3 +++ src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs | 3 +++ src/test/run-make-fulldeps/extern-flag-fun/rustc.rs | 1 + 3 files changed, 7 insertions(+) create mode 100644 src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs create mode 100644 src/test/run-make-fulldeps/extern-flag-fun/rustc.rs diff --git a/src/test/run-make-fulldeps/extern-flag-fun/Makefile b/src/test/run-make-fulldeps/extern-flag-fun/Makefile index 7f54d6ea3bc6c..38d1d5bb8488a 100644 --- a/src/test/run-make-fulldeps/extern-flag-fun/Makefile +++ b/src/test/run-make-fulldeps/extern-flag-fun/Makefile @@ -14,3 +14,6 @@ all: --extern bar=$(TMPDIR)/libbar.rlib \ --extern bar=$(TMPDIR)/libbar-a.rlib $(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib + # Try to be sneaky and load a private crate from with a non-private name. + $(RUSTC) rustc.rs -Zforce-unstable-if-unmarked --crate-type=rlib + $(RUSTC) gated_unstable.rs --extern alloc=$(TMPDIR)/librustc.rlib 2>&1 | $(CGREP) 'rustc_private' diff --git a/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs b/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs new file mode 100644 index 0000000000000..03600c830fff6 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/gated_unstable.rs @@ -0,0 +1,3 @@ +extern crate alloc; + +fn main() {} diff --git a/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs b/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs new file mode 100644 index 0000000000000..b76b4321d62aa --- /dev/null +++ b/src/test/run-make-fulldeps/extern-flag-fun/rustc.rs @@ -0,0 +1 @@ +pub fn foo() {} From 40282a19cd802fdaf952f4b469120df1d876f95b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 16 Oct 2019 07:37:53 -0700 Subject: [PATCH 07/14] Remove docs on --extern metadata precedence. --- src/doc/rustc/src/command-line-arguments.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7e9b4833ef0a4..c7e802ef156ad 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -246,9 +246,8 @@ either of the following formats: such as within the sysroot or via the `-L` flag. The same crate name may be specified multiple times for different crate types. -For loading metadata, `rlib` takes precedence over `rmeta`, which takes -precedence over `dylib`. If both an `rlib` and `dylib` are found, an internal -algorithm is used to decide which to use for linking. The [`-C prefer-dynamic` +If both an `rlib` and `dylib` are found, an internal algorithm is used to +decide which to use for linking. The [`-C prefer-dynamic` flag][prefer-dynamic] may be used to influence which is used. If the same crate name is specified with and without a path, the one with the From 098ffd9aa23638d2ccfc00c7574b8863ef3dd111 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 16 Oct 2019 09:55:40 -0700 Subject: [PATCH 08/14] Update for unstable option refactoring. --- src/librustc/session/config.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 07fd71632d167..259b24cac8b48 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2221,7 +2221,6 @@ fn collect_print_requests( cg: &mut CodegenOptions, dopts: &mut DebuggingOptions, matches: &getopts::Matches, - is_unstable_enabled: bool, error_format: ErrorOutputType, ) -> Vec { let mut prints = Vec::::new(); @@ -2263,7 +2262,7 @@ fn collect_print_requests( "tls-models" => PrintRequest::TlsModels, "native-static-libs" => PrintRequest::NativeStaticLibs, "target-spec-json" => { - if is_unstable_enabled { + if dopts.unstable_options { PrintRequest::TargetSpec } else { early_error( @@ -2427,7 +2426,6 @@ fn parse_externs( matches: &getopts::Matches, debugging_opts: &DebuggingOptions, error_format: ErrorOutputType, - is_unstable_enabled: bool, ) -> Externs { if matches.opt_present("extern-private") && !debugging_opts.unstable_options { early_error( @@ -2533,12 +2531,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } - let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); let prints = collect_print_requests( &mut cg, &mut debugging_opts, matches, - is_unstable_enabled, error_format, ); @@ -2571,7 +2567,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } - let externs = parse_externs(matches, &debugging_opts, error_format, is_unstable_enabled); + let externs = parse_externs(matches, &debugging_opts, error_format); let crate_name = matches.opt_str("crate-name"); From 79956b96e875e6ba2bfa551fabda6b7896f988ac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 23 Sep 2019 00:49:29 +0200 Subject: [PATCH 09/14] add sub settings in rustdoc --- src/librustdoc/html/render.rs | 99 ++++++++++++++++----- src/librustdoc/html/static/main.js | 32 ++++++- src/librustdoc/html/static/settings.css | 14 +++ src/librustdoc/html/static/themes/dark.css | 3 + src/librustdoc/html/static/themes/light.css | 3 + 5 files changed, 127 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 414c3137376a9..0ad4e2d6ccd9e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1230,18 +1230,87 @@ impl AllTypes { } } +#[derive(Debug)] +enum Setting { + Section { + description: &'static str, + sub_settings: Vec, + }, + Entry { + js_data_name: &'static str, + description: &'static str, + default_value: bool, + } +} + +impl Setting { + fn display(&self) -> String { + match *self { + Setting::Section { ref description, ref sub_settings } => { + format!( + "
\ +
{}
\ +
{}
+
", + description, + sub_settings.iter().map(|s| s.display()).collect::() + ) + } + Setting::Entry { ref js_data_name, ref description, ref default_value } => { + format!( + "
\ + \ +
{}
\ +
", + js_data_name, + if *default_value { " checked" } else { "" }, + description, + ) + } + } + } +} + +impl From<(&'static str, &'static str, bool)> for Setting { + fn from(values: (&'static str, &'static str, bool)) -> Setting { + Setting::Entry { + js_data_name: values.0, + description: values.1, + default_value: values.2, + } + } +} + +impl> From<(&'static str, Vec)> for Setting { + fn from(values: (&'static str, Vec)) -> Setting { + Setting::Section { + description: values.0, + sub_settings: values.1.into_iter().map(|v| v.into()).collect::>(), + } + } +} + fn settings(root_path: &str, suffix: &str) -> String { // (id, explanation, default value) - let settings = [ - ("item-declarations", "Auto-hide item declarations.", true), - ("item-attributes", "Auto-hide item attributes.", true), - ("trait-implementations", "Auto-hide trait implementations documentation", - true), - ("method-docs", "Auto-hide item methods' documentation", false), + let settings: &[Setting] = &[ + ("Auto-hide item declarations", vec![ + ("auto-hide-struct", "Auto-hide structs declaration", true), + ("auto-hide-enum", "Auto-hide enums declaration", false), + ("auto-hide-union", "Auto-hide unions declaration", true), + ("auto-hide-trait", "Auto-hide traits declaration", true), + ("auto-hide-macro", "Auto-hide macros declaration", false), + ]).into(), + ("auto-hide-attributes", "Auto-hide item attributes.", true).into(), + ("auto-hide-method-docs", "Auto-hide item methods' documentation", false).into(), + ("auto-hide-trait-implementations", "Auto-hide trait implementations documentation", + true).into(), ("go-to-only-result", "Directly go to item in search if there is only one result", - false), - ("line-numbers", "Show line numbers on code examples", false), - ("disable-shortcuts", "Disable keyboard shortcuts", false), + false).into(), + ("line-numbers", "Show line numbers on code examples", false).into(), + ("disable-shortcuts", "Disable keyboard shortcuts", false).into(), ]; format!( "

\ @@ -1249,17 +1318,7 @@ fn settings(root_path: &str, suffix: &str) -> String {

\
{}
\ ", - settings.iter() - .map(|(id, text, enabled)| { - format!("
\ - \ -
{}
\ -
", id, if *enabled { " checked" } else { "" }, text) - }) - .collect::(), + settings.iter().map(|s| s.display()).collect::(), root_path, suffix) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a0e07d58c9da9..65410a99e181e 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2102,7 +2102,7 @@ function getSearchElement() { function autoCollapse(pageId, collapse) { if (collapse) { toggleAllDocs(pageId, true); - } else if (getCurrentValue("rustdoc-trait-implementations") !== "false") { + } else if (getCurrentValue("rustdoc-auto-hide-trait-implementations") !== "false") { var impl_list = document.getElementById("implementations-list"); if (impl_list !== null) { @@ -2140,7 +2140,7 @@ function getSearchElement() { } var toggle = createSimpleToggle(false); - var hideMethodDocs = getCurrentValue("rustdoc-method-docs") === "true"; + var hideMethodDocs = getCurrentValue("rustdoc-auto-hide-method-docs") === "true"; var pageId = getPageId(); var func = function(e) { @@ -2270,7 +2270,31 @@ function getSearchElement() { return wrapper; } - var showItemDeclarations = getCurrentValue("rustdoc-item-declarations") === "false"; + var currentType = document.getElementsByClassName("type-decl")[0]; + var className = null; + if (currentType) { + currentType = currentType.getElementsByClassName("rust")[0]; + if (currentType) { + currentType.classList.forEach(function(item) { + if (item !== "main") { + className = item; + return true; + } + }); + } + } + var showItemDeclarations = getCurrentValue("rustdoc-auto-hide-" + className); + if (showItemDeclarations === null) { + if (className === "enum" || className === "macro") { + showItemDeclarations = "false"; + } else if (className === "struct" || className === "union" || className === "trait") { + showItemDeclarations = "true"; + } else { + // In case we found an unknown type, we just use the "parent" value. + showItemDeclarations = getCurrentValue("rustdoc-auto-hide-declarations"); + } + } + showItemDeclarations = showItemDeclarations === "false"; function buildToggleWrapper(e) { if (hasClass(e, "autohide")) { var wrap = e.previousElementSibling; @@ -2353,7 +2377,7 @@ function getSearchElement() { // To avoid checking on "rustdoc-item-attributes" value on every loop... var itemAttributesFunc = function() {}; - if (getCurrentValue("rustdoc-item-attributes") !== "false") { + if (getCurrentValue("rustdoc-auto-hide-attributes") !== "false") { itemAttributesFunc = function(x) { collapseDocs(x.previousSibling.childNodes[0], "toggle"); }; diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css index b31ad96fa545f..c66c5d3636052 100644 --- a/src/librustdoc/html/static/settings.css +++ b/src/librustdoc/html/static/settings.css @@ -1,5 +1,6 @@ .setting-line { padding: 5px; + position: relative; } .setting-line > div { @@ -10,6 +11,13 @@ padding-top: 2px; } +.setting-line > .title { + font-size: 19px; + width: 100%; + max-width: none; + border-bottom: 1px solid; +} + .toggle { position: relative; display: inline-block; @@ -59,3 +67,9 @@ input:checked + .slider:before { -ms-transform: translateX(19px); transform: translateX(19px); } + +.setting-line > .sub-setting { + padding-left: 42px; + width: 100%; + display: block; +} diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index c3116dbe7a242..a60d543a53936 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -425,3 +425,6 @@ div.files > a:hover, div.name:hover { div.files > .selected { background-color: #333; } +.setting-line > .title { + border-bottom-color: #ddd; +} diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index e2bf9f9d2f23a..351f027b942ff 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -419,3 +419,6 @@ div.files > a:hover, div.name:hover { div.files > .selected { background-color: #fff; } +.setting-line > .title { + border-bottom-color: #D5D5D5; +} From 8784b074e7ad741e1feed203b55ad9a204ad8cd3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 Nov 2019 11:39:00 +0100 Subject: [PATCH 10/14] Change sub-setting CSS class to sub-settings --- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/static/settings.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0ad4e2d6ccd9e..f521c057afe37 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1250,7 +1250,7 @@ impl Setting { format!( "
\
{}
\ -
{}
+
{}
", description, sub_settings.iter().map(|s| s.display()).collect::() diff --git a/src/librustdoc/html/static/settings.css b/src/librustdoc/html/static/settings.css index c66c5d3636052..d03cf7fcc459e 100644 --- a/src/librustdoc/html/static/settings.css +++ b/src/librustdoc/html/static/settings.css @@ -68,7 +68,7 @@ input:checked + .slider:before { transform: translateX(19px); } -.setting-line > .sub-setting { +.setting-line > .sub-settings { padding-left: 42px; width: 100%; display: block; From a5be03654cf412299d1dffc6f83544a5e5efe416 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Nov 2019 10:22:50 +0100 Subject: [PATCH 11/14] invalid_value lint: fix help text --- src/librustc_lint/builtin.rs | 3 +- src/test/ui/lint/uninitialized-zeroed.stderr | 70 ++++++++++---------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 867f5f76b59bc..c6fd1256a8e64 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -2052,7 +2052,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { ); err.span_label(expr.span, "this code causes undefined behavior when executed"); - err.span_label(expr.span, "help: use `MaybeUninit` instead"); + err.span_label(expr.span, "help: use `MaybeUninit` instead, \ + and only call `assume_init` after initialization is done"); if let Some(span) = span { err.span_note(span, &msg); } else { diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index e12b1897ade1b..bdb5959953f50 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -5,7 +5,7 @@ LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: lint level defined here --> $DIR/uninitialized-zeroed.rs:7:9 @@ -21,7 +21,7 @@ LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: References must be non-null @@ -32,7 +32,7 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:18:18 @@ -47,7 +47,7 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:18:18 @@ -62,7 +62,7 @@ LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The never type (`!`) has no valid value @@ -73,7 +73,7 @@ LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The never type (`!`) has no valid value @@ -84,7 +84,7 @@ LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The never type (`!`) has no valid value @@ -95,7 +95,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The never type (`!`) has no valid value @@ -106,7 +106,7 @@ LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: 0-variant enums have no valid value @@ -117,7 +117,7 @@ LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: 0-variant enums have no valid value @@ -128,7 +128,7 @@ LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: References must be non-null @@ -139,7 +139,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: References must be non-null @@ -150,7 +150,7 @@ LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:15:12 @@ -165,7 +165,7 @@ LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:15:12 @@ -180,7 +180,7 @@ LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: Function pointers must be non-null @@ -191,7 +191,7 @@ LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: Function pointers must be non-null @@ -202,7 +202,7 @@ LL | let _val: Wrap = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: Function pointers must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:18:18 @@ -217,7 +217,7 @@ LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: Function pointers must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:18:18 @@ -232,7 +232,7 @@ LL | let _val: WrapEnum = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: Function pointers must be non-null (in this enum field) --> $DIR/uninitialized-zeroed.rs:19:28 @@ -247,7 +247,7 @@ LL | let _val: WrapEnum = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: Function pointers must be non-null (in this enum field) --> $DIR/uninitialized-zeroed.rs:19:28 @@ -262,7 +262,7 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:16:16 @@ -277,7 +277,7 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: References must be non-null (in this struct field) --> $DIR/uninitialized-zeroed.rs:16:16 @@ -292,7 +292,7 @@ LL | let _val: NonNull = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: std::ptr::NonNull must be non-null @@ -303,7 +303,7 @@ LL | let _val: NonNull = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: std::ptr::NonNull must be non-null @@ -314,7 +314,7 @@ LL | let _val: *const dyn Send = mem::zeroed(); | ^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The vtable of a wide raw pointer must be non-null @@ -325,7 +325,7 @@ LL | let _val: *const dyn Send = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: The vtable of a wide raw pointer must be non-null @@ -336,7 +336,7 @@ LL | let _val: bool = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: Booleans must be `true` or `false` @@ -347,7 +347,7 @@ LL | let _val: Wrap = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | note: Characters must be a valid unicode codepoint (in this struct field) --> $DIR/uninitialized-zeroed.rs:18:18 @@ -362,7 +362,7 @@ LL | let _val: NonBig = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: NonBig must be initialized inside its custom valid range @@ -373,7 +373,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); | ^^^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: References must be non-null @@ -384,7 +384,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: References must be non-null @@ -395,7 +395,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0); | ^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: std::num::NonZeroU32 must be non-null @@ -406,7 +406,7 @@ LL | let _val: NonNull = MaybeUninit::zeroed().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: std::ptr::NonNull must be non-null @@ -417,7 +417,7 @@ LL | let _val: NonNull = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: std::ptr::NonNull must be non-null @@ -428,7 +428,7 @@ LL | let _val: bool = MaybeUninit::uninit().assume_init(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | this code causes undefined behavior when executed - | help: use `MaybeUninit` instead + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done | = note: Booleans must be `true` or `false` From 1906c6f714502b1a0de46b9c217dc02570c3fd3e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 19 Oct 2019 00:48:21 +0200 Subject: [PATCH 12/14] Add `MaybeUninit` methods `uninit_array`, `slice_get_ref`, `slice_get_mut` --- src/libcore/mem/maybe_uninit.rs | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 03093139bc2f9..46b0fd3c3cbaa 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -258,6 +258,37 @@ impl MaybeUninit { MaybeUninit { uninit: () } } + /// Create a new array of `MaybeUninit` items, in an uninitialized state. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// use std::mem::MaybeUninit; + /// + /// let input = b"Foo"; + /// let f = u8::to_ascii_uppercase; + /// + /// let mut buffer: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let vec; + /// let output = if let Some(buffer) = buffer.get_mut(..input.len()) { + /// buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); + /// unsafe { MaybeUninit::slice_get_ref(buffer) } + /// } else { + /// vec = input.iter().map(f).collect::>(); + /// &vec + /// }; + /// + /// assert_eq!(output, b"FOO"); + /// ``` + #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")] + #[inline(always)] + pub fn uninit_array() -> [Self; LEN] { + unsafe { + MaybeUninit::<[MaybeUninit; LEN]>::uninit().assume_init() + } + } + /// A promotable constant, equivalent to `uninit()`. #[unstable(feature = "internal_uninit_const", issue = "0", reason = "hack to work around promotability")] @@ -690,6 +721,32 @@ impl MaybeUninit { &mut *self.value } + /// Get a slice of assume-initialized items. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` items + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] { + &*(slice as *const [Self] as *const [T]) + } + + /// Get a mutable slice of assume-initialized items. + /// + /// # Safety + /// + /// It is up to the caller to guarantee that the `MaybeUninit` items + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized causes undefined behavior. + #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] + #[inline(always)] + pub unsafe fn slice_get_mut(slice: &mut [Self]) -> &mut [T] { + &mut *(slice as *mut [Self] as *mut [T]) + } + /// Gets a pointer to the first element of the array. #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] From 05c14bcc3180092ec4c03d59977abf96db7b4b7a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 26 Oct 2019 08:51:49 +0200 Subject: [PATCH 13/14] Apply docs suggestions from review Co-Authored-By: Mazdak Farrokhzad --- src/libcore/mem/maybe_uninit.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 46b0fd3c3cbaa..31f908e91f55e 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -721,11 +721,11 @@ impl MaybeUninit { &mut *self.value } - /// Get a slice of assume-initialized items. + /// Assuming all the elements are initialized, get a slice to them. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` items + /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] @@ -734,11 +734,11 @@ impl MaybeUninit { &*(slice as *const [Self] as *const [T]) } - /// Get a mutable slice of assume-initialized items. + /// Assuming all the elements are initialized, get a mutable slice to them. /// /// # Safety /// - /// It is up to the caller to guarantee that the `MaybeUninit` items + /// It is up to the caller to guarantee that the `MaybeUninit` elements /// really are in an initialized state. /// Calling this when the content is not yet fully initialized causes undefined behavior. #[unstable(feature = "maybe_uninit_slice_assume_init", issue = "0")] From 639c4f779c60119383dd8a49b44522f6a6958a53 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 26 Oct 2019 09:19:48 +0200 Subject: [PATCH 14/14] MaybeUninit::uninit_array docs: better example --- src/libcore/mem/maybe_uninit.rs | 34 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 31f908e91f55e..0c0a6d8a121b8 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -260,26 +260,32 @@ impl MaybeUninit { /// Create a new array of `MaybeUninit` items, in an uninitialized state. /// + /// Note: in a future Rust version this method may become unnecessary + /// when array literal syntax allows + /// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147). + /// The example below could then use `let mut buf = [MaybeUninit::::uninit(); 32];`. + /// /// # Examples /// - /// ``` + /// ```no_run /// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice_assume_init)] + /// /// use std::mem::MaybeUninit; /// - /// let input = b"Foo"; - /// let f = u8::to_ascii_uppercase; - /// - /// let mut buffer: [MaybeUninit; 32] = MaybeUninit::uninit_array(); - /// let vec; - /// let output = if let Some(buffer) = buffer.get_mut(..input.len()) { - /// buffer.iter_mut().zip(input).for_each(|(a, b)| { a.write(f(b)); }); - /// unsafe { MaybeUninit::slice_get_ref(buffer) } - /// } else { - /// vec = input.iter().map(f).collect::>(); - /// &vec - /// }; + /// extern "C" { + /// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize; + /// } + /// + /// /// Returns a (possibly smaller) slice of data that was actually read + /// fn read(buf: &mut [MaybeUninit]) -> &[u8] { + /// unsafe { + /// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len()); + /// MaybeUninit::slice_get_ref(&buf[..len]) + /// } + /// } /// - /// assert_eq!(output, b"FOO"); + /// let mut buf: [MaybeUninit; 32] = MaybeUninit::uninit_array(); + /// let data = read(&mut buf); /// ``` #[unstable(feature = "maybe_uninit_uninit_array", issue = "0")] #[inline(always)]