diff --git a/RELEASES.md b/RELEASES.md index 8adc450ac98..a49091373df 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -81,13 +81,6 @@ Stabilised APIs - [`Vec::extend_from_within`] - [`array::from_mut`] - [`array::from_ref`] -- [`char::MAX`] -- [`char::REPLACEMENT_CHARACTER`] -- [`char::UNICODE_VERSION`] -- [`char::decode_utf16`] -- [`char::from_digit`] -- [`char::from_u32_unchecked`] -- [`char::from_u32`] - [`cmp::max_by_key`] - [`cmp::max_by`] - [`cmp::min_by_key`] @@ -152,13 +145,6 @@ related tools. [cargo/9298]: https://github.com/rust-lang/cargo/pull/9298 [cargo/9282]: https://github.com/rust-lang/cargo/pull/9282 [cargo/9392]: https://github.com/rust-lang/cargo/pull/9392 -[`char::MAX`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.MAX -[`char::REPLACEMENT_CHARACTER`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.REPLACEMENT_CHARACTER -[`char::UNICODE_VERSION`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.UNICODE_VERSION -[`char::decode_utf16`]: https://doc.rust-lang.org/std/primitive.char.html#method.decode_utf16 -[`char::from_u32`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_u32 -[`char::from_u32_unchecked`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_u32_unchecked -[`char::from_digit`]: https://doc.rust-lang.org/std/primitive.char.html#method.from_digit [`AtomicBool::fetch_update`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.fetch_update [`AtomicPtr::fetch_update`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_update [`BTreeMap::retain`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.retain diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 51a2dc03de3..19faf9cddac 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -38,7 +38,7 @@ /// A common trait for the ability to explicitly duplicate an object. /// -/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while +/// Differs from [`Copy`] in that [`Copy`] is implicit and an inexpensive bit-wise copy, while /// `Clone` is always explicit and may or may not be expensive. In order to enforce /// these characteristics, Rust does not allow you to reimplement [`Copy`], but you /// may reimplement `Clone` and run arbitrary code. diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 4e7afca6a49..aedfe88f688 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -50,8 +50,8 @@ //! the optional owned box, [`Option`]`<`[`Box`]`>`. //! //! The following example uses [`Option`] to create an optional box of -//! [`i32`]. Notice that in order to use the inner [`i32`] value first, the -//! `check_optional` function needs to use pattern matching to +//! [`i32`]. Notice that in order to use the inner [`i32`] value, the +//! `check_optional` function first needs to use pattern matching to //! determine whether the box has a value (i.e., it is [`Some(...)`][`Some`]) or //! not ([`None`]). //! @@ -1350,7 +1350,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. /// The [`map`] method takes the `self` argument by value, consuming the original, - /// so this technique uses `as_ref` to first take an `Option` to a reference + /// so this technique uses `from` to first take an `Option` to a reference /// to the value inside the original. /// /// [`map`]: Option::map diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index fe4666effe6..0b7a0e25df1 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -805,7 +805,7 @@ impl Step for RustdocGUI { fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; - let run = run.path("src/test/rustdoc-gui"); + let run = run.suite_path("src/test/rustdoc-gui"); run.default_condition( builder.config.nodejs.is_some() && builder @@ -870,6 +870,13 @@ impl Step for RustdocGUI { .arg(out_dir) .arg("--tests-folder") .arg(builder.build.src.join("src/test/rustdoc-gui")); + for path in &builder.paths { + if let Some(name) = path.file_name().and_then(|f| f.to_str()) { + if name.ends_with(".goml") { + command.arg("--file").arg(name); + } + } + } builder.run(&mut command); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d1c18821ea6..bc04480ab7c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -26,6 +26,8 @@ use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn}; use rustc_span::hygiene::{AstPass, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, ExpnKind}; +use rustc_target::spec::abi::Abi; +use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety; use rustc_typeck::hir_ty_to_ty; use std::collections::hash_map::Entry; @@ -350,12 +352,12 @@ impl<'a> Clean> for ty::Predicate<'a> { ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx), ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx), ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)), + ty::PredicateKind::ConstEvaluatable(..) => None, ty::PredicateKind::Subtype(..) | ty::PredicateKind::WellFormed(..) | ty::PredicateKind::ObjectSafe(..) | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::ConstEvaluatable(..) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"), } @@ -2132,7 +2134,11 @@ impl Clean for (&hir::ForeignItem<'_>, Option) { decl, generics, header: hir::FnHeader { - unsafety: hir::Unsafety::Unsafe, + unsafety: if abi == Abi::RustIntrinsic { + intrinsic_operation_unsafety(item.ident.name) + } else { + hir::Unsafety::Unsafe + }, abi, constness: hir::Constness::NotConst, asyncness: hir::IsAsync::NotAsync, diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile index d3d398f1fac..78fbf811f12 100644 --- a/src/test/run-make-fulldeps/coverage-reports/Makefile +++ b/src/test/run-make-fulldeps/coverage-reports/Makefile @@ -87,7 +87,7 @@ endif # Run it in order to generate some profiling data, # with `LLVM_PROFILE_FILE=` environment variable set to # output the coverage stats for this run. - LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ + LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \ $(call RUN,$@) || \ ( \ status=$$?; \ @@ -97,8 +97,11 @@ endif ) \ ) - # Run it through rustdoc as well to cover doctests - LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p.profraw \ + # Run it through rustdoc as well to cover doctests. + # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone + # might result in overwritten files and failed tests, as rustdoc spawns each + # doctest as its own process, so make sure the filename is as unique as possible. + LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \ $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \ $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ -L "$(TMPDIR)" -Zinstrument-coverage \ @@ -106,7 +109,7 @@ endif # Postprocess the profiling data so it can be used by the llvm-cov tool "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \ - "$(TMPDIR)"/$@-*.profraw \ + "$(TMPDIR)"/$@*.profraw \ -o "$(TMPDIR)"/$@.profdata # Generate a coverage report using `llvm-cov show`. @@ -118,8 +121,7 @@ endif --instr-profile="$(TMPDIR)"/$@.profdata \ $(call BIN,"$(TMPDIR)"/$@) \ $$( \ - for file in $(TMPDIR)/rustdoc-$@/*/rust_out; \ - do \ + for file in $(TMPDIR)/rustdoc-$@/*/rust_out; do \ [ -x "$$file" ] && printf "%s %s " -object $$file; \ done \ ) \ diff --git a/src/test/rustdoc/const-generics/const-evaluatable-checked.rs b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs new file mode 100644 index 00000000000..1c074fdb3f8 --- /dev/null +++ b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs @@ -0,0 +1,7 @@ +#![crate_name = "foo"] +#![feature(const_evaluatable_checked, const_generics)] +#![allow(incomplete_features)] +// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647 +// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \ +// 'pub struct Ice where [(); N + 1]: ;' +pub struct Ice where [(); N + 1]:; diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs new file mode 100644 index 00000000000..d3bb8514b7e --- /dev/null +++ b/src/test/rustdoc/safe-intrinsic.rs @@ -0,0 +1,20 @@ +#![feature(intrinsics)] +#![feature(no_core)] + +#![no_core] +#![crate_name = "foo"] + +extern "rust-intrinsic" { + // @has 'foo/fn.abort.html' + // @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !' + pub fn abort() -> !; + // @has 'foo/fn.unreachable.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !' + pub fn unreachable() -> !; +} + +extern "C" { + // @has 'foo/fn.needs_drop.html' + // @has - '//pre[@class="rust fn"]' 'pub unsafe extern "C" fn needs_drop() -> !' + pub fn needs_drop() -> !; +} diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr new file mode 100644 index 00000000000..965bc67a381 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 4) { + ╾─alloc2──╼ 07 00 00 00 │ ╾──╼.... + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr new file mode 100644 index 00000000000..ac7d5993585 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -0,0 +1,36 @@ +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + +error[E0658]: mutation through a reference is not allowed in constants + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/issue-76510.rs:5:29 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^ cannot borrow as mutable + +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-76510.rs:5:1 + | +LL | const S: &'static mut str = &mut " hello "; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered mutable reference in a `const` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 16, align: 8) { + ╾───────alloc2────────╼ 07 00 00 00 00 00 00 00 │ ╾──────╼........ + } + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0596, E0658, E0764. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs new file mode 100644 index 00000000000..892f6c98116 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -0,0 +1,18 @@ +// stderr-per-bitwidth + +use std::mem::{transmute, ManuallyDrop}; + +const S: &'static mut str = &mut " hello "; +//~^ ERROR: mutable references are not allowed in the final value of constants +//~| ERROR: mutation through a reference is not allowed in constants +//~| ERROR: cannot borrow data in a `&` reference as mutable +//~| ERROR: it is undefined behavior to use this value + +const fn trigger() -> [(); unsafe { + let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + 0 + }] { + [(); 0] +} + +fn main() {} diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index c55e014e834..8c8d86d5e38 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -10,6 +10,7 @@ const {Options, runTest} = require('browser-ui-test'); function showHelp() { console.log("rustdoc-js options:"); console.log(" --doc-folder [PATH] : location of the generated doc folder"); + console.log(" --file [PATH] : file to run (can be repeated)"); console.log(" --help : show this message then quit"); console.log(" --tests-folder [PATH] : location of the .GOML tests folder"); } @@ -18,6 +19,7 @@ function parseOptions(args) { var opts = { "doc_folder": "", "tests_folder": "", + "files": [], }; var correspondances = { "--doc-folder": "doc_folder", @@ -26,13 +28,18 @@ function parseOptions(args) { for (var i = 0; i < args.length; ++i) { if (args[i] === "--doc-folder" - || args[i] === "--tests-folder") { + || args[i] === "--tests-folder" + || args[i] === "--file") { i += 1; if (i >= args.length) { console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } - opts[correspondances[args[i - 1]]] = args[i]; + if (args[i - 1] !== "--file") { + opts[correspondances[args[i - 1]]] = args[i]; + } else { + opts["files"].push(args[i]); + } } else if (args[i] === "--help") { showHelp(); process.exit(0); @@ -78,7 +85,12 @@ async function main(argv) { } let failed = false; - let files = fs.readdirSync(opts["tests_folder"]).filter(file => path.extname(file) == ".goml"); + let files; + if (opts["files"].length === 0) { + files = fs.readdirSync(opts["tests_folder"]).filter(file => path.extname(file) == ".goml"); + } else { + files = opts["files"].filter(file => path.extname(file) == ".goml"); + } files.sort(); for (var i = 0; i < files.length; ++i) {