]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #86424 - calebcartwright:rustfmt-mod-resolution, r=Mark-Simulacrum
authorYuki Okushi <jtitor@2k36.org>
Mon, 21 Jun 2021 15:00:41 +0000 (00:00 +0900)
committerGitHub <noreply@github.com>
Mon, 21 Jun 2021 15:00:41 +0000 (00:00 +0900)
rustfmt: load nested out-of-line mods correctly

This should address https://github.com/rust-lang/rustfmt/issues/4874

r? `@Mark-Simulacrum`

Decided to make the change directly in tree here for expediency/to minimize any potential backporting issues, and because there's some subtree sync items I need to get resolved before pulling from r-l/rustfmt

213 files changed:
.github/ISSUE_TEMPLATE/diagnostics.md
.github/ISSUE_TEMPLATE/library_tracking_issue.md
Cargo.lock
README.md
RELEASES.md
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast_pretty/src/pprust/tests.rs
compiler/rustc_builtin_macros/src/cfg_eval.rs
compiler/rustc_builtin_macros/src/derive.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_macros/src/hash_stable.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_middle/src/mir/interpret/error.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_mir/src/borrow_check/type_check/mod.rs
compiler/rustc_mir/src/transform/check_unsafety.rs
compiler/rustc_mir/src/transform/const_prop.rs
compiler/rustc_mir_build/src/build/block.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/thir/cx/block.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/visit.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_serialize/src/json.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_target/src/lib.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/tests/tests_impl.rs
compiler/rustc_target/src/tests.rs [new file with mode: 0644]
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/collect.rs
config.toml.example
library/alloc/benches/btree/map.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/navigate.rs
library/alloc/src/string.rs
library/alloc/tests/str.rs
library/alloc/tests/vec.rs
library/core/src/cell.rs
library/core/src/cmp.rs
library/core/src/iter/adapters/zip.rs
library/core/tests/iter/adapters/zip.rs
library/proc_macro/src/lib.rs
library/std/src/fs.rs
library/std/src/io/mod.rs
library/std/src/io/tests.rs
library/std/src/lib.rs
library/std/src/os/fortanix_sgx/ffi.rs
library/std/src/os/hermit/ffi.rs
library/std/src/os/unix/ffi.rs [deleted file]
library/std/src/os/unix/ffi/mod.rs [new file with mode: 0644]
library/std/src/os/unix/ffi/os_str.rs [new file with mode: 0644]
library/std/src/os/wasi/ffi.rs
library/std/src/path.rs
library/std/src/rt.rs
library/std/src/sys/hermit/args.rs
library/std/src/sys/hermit/fs.rs
library/std/src/sys/hermit/os.rs
library/std/src/sys_common/os_str_bytes.rs
library/std/src/sys_common/wtf8.rs
library/std/src/sys_common/wtf8/tests.rs
library/test/src/formatters/junit.rs
src/bootstrap/Cargo.toml
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
src/librustdoc/Cargo.toml
src/librustdoc/externalfiles.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/FiraSans-LICENSE.txt
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static_files.rs
src/librustdoc/html/templates/STYLE.md [new file with mode: 0644]
src/librustdoc/html/templates/page.html [new file with mode: 0644]
src/test/rustdoc-gui/basic-code.goml
src/test/rustdoc-gui/check_info_sign_position.goml
src/test/rustdoc-gui/code-sidebar-toggle.goml
src/test/rustdoc-gui/escape-key.goml
src/test/rustdoc-gui/font-weight.goml
src/test/rustdoc-gui/hash-item-expansion.goml
src/test/rustdoc-gui/impl-default-expansion.goml
src/test/rustdoc-gui/search-result-colors.goml
src/test/rustdoc-gui/search-result-description.goml
src/test/rustdoc-gui/search-result-display.goml
src/test/rustdoc-gui/search-result-keyword.goml
src/test/rustdoc-gui/search-tab-selection-if-current-is-empty.goml
src/test/rustdoc-gui/shortcuts.goml
src/test/rustdoc-gui/sidebar.goml
src/test/rustdoc-gui/source-code-page.goml
src/test/rustdoc-gui/theme-change.goml
src/test/rustdoc-gui/toggle-docs-mobile.goml
src/test/rustdoc-gui/toggle-docs.goml
src/test/rustdoc-gui/toggled-open-implementations.goml
src/test/rustdoc-gui/trait-sidebar-item-order.goml
src/test/rustdoc/recursive-deref-sidebar.rs [new file with mode: 0644]
src/test/rustdoc/recursive-deref.rs [new file with mode: 0644]
src/test/ui/array-slice-vec/slice-panic-1.rs
src/test/ui/array-slice-vec/slice-panic-2.rs
src/test/ui/array-slice-vec/slice.rs
src/test/ui/const-generics/issues/issue-61432.rs
src/test/ui/consts/const-eval/dangling.rs
src/test/ui/consts/const-eval/dangling.stderr
src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.rs
src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
src/test/ui/consts/const-eval/issue-49296.rs
src/test/ui/consts/const-eval/issue-49296.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.64bit.stderr
src/test/ui/consts/const-eval/ub-incorrect-vtable.rs
src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
src/test/ui/consts/const-eval/ub-nonnull.rs
src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
src/test/ui/consts/const-int-unchecked.rs
src/test/ui/consts/const-int-unchecked.stderr
src/test/ui/consts/const_unsafe_unreachable_ub.rs
src/test/ui/consts/const_unsafe_unreachable_ub.stderr
src/test/ui/consts/offset_from_ub.rs
src/test/ui/consts/offset_from_ub.stderr
src/test/ui/consts/offset_ub.stderr
src/test/ui/consts/ptr_comparisons.rs
src/test/ui/consts/ptr_comparisons.stderr
src/test/ui/dynamically-sized-types/dst-index.rs
src/test/ui/error-codes/E0121.rs
src/test/ui/generator/too-live-local-in-immovable-gen.rs
src/test/ui/generator/too-live-local-in-immovable-gen.stderr
src/test/ui/generator/yield-in-initializer.rs
src/test/ui/issues/issue-20644.rs
src/test/ui/issues/issue-27895.rs [deleted file]
src/test/ui/issues/issue-27895.stderr [deleted file]
src/test/ui/issues/issue-43205.rs
src/test/ui/issues/issue-5280.rs
src/test/ui/issues/issue-54696.rs
src/test/ui/limits/issue-69485-var-size-diffs-too-large.stderr
src/test/ui/lint/unused-borrows.rs [new file with mode: 0644]
src/test/ui/lint/unused-borrows.stderr [new file with mode: 0644]
src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs [new file with mode: 0644]
src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr [new file with mode: 0644]
src/test/ui/macros/macro-or-patterns-back-compat.fixed
src/test/ui/macros/macro-or-patterns-back-compat.rs
src/test/ui/macros/macro-or-patterns-back-compat.stderr
src/test/ui/non-constant-in-const-path.rs [deleted file]
src/test/ui/non-constant-in-const-path.stderr [deleted file]
src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs [deleted file]
src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr [deleted file]
src/test/ui/pattern/non-constant-in-const-path.rs [new file with mode: 0644]
src/test/ui/pattern/non-constant-in-const-path.stderr [new file with mode: 0644]
src/test/ui/repr/issue-83505-repr-simd.rs [new file with mode: 0644]
src/test/ui/repr/issue-83505-repr-simd.stderr [new file with mode: 0644]
src/test/ui/rt-explody-panic-payloads.rs [new file with mode: 0644]
src/test/ui/traits/issue-78632.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-85113.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-85113.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-75889.rs [new file with mode: 0644]
src/test/ui/typeck/issue-75889.stderr [new file with mode: 0644]
src/test/ui/variance/variance-btree-invariant-types.nll.stderr
src/test/ui/variance/variance-btree-invariant-types.rs
src/test/ui/variance/variance-btree-invariant-types.stderr
src/tools/clippy/CONTRIBUTING.md
src/tools/clippy/README.md
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/doc/basics.md
src/tools/clippy/lintcheck/README.md
src/tools/clippy/tests/ui/bytes_nth.fixed
src/tools/clippy/tests/ui/bytes_nth.rs
src/tools/clippy/tests/ui/bytes_nth.stderr
src/tools/clippy/tests/ui/iter_count.fixed
src/tools/clippy/tests/ui/iter_count.rs
src/tools/clippy/tests/ui/iter_count.stderr
src/tools/clippy/util/gh-pages/index.html
src/tools/linkchecker/main.rs
src/tools/linkchecker/tests/broken_redir/redir-bad.html
src/tools/linkchecker/tests/checks.rs
src/tools/linkchecker/tests/redirect_loop/redir-bad.html
src/tools/linkchecker/tests/valid/inner/redir-bad.html
src/tools/linkchecker/tests/valid/inner/redir.html
src/tools/miri
src/tools/rustfmt/CHANGELOG.md
src/tools/rustfmt/Configurations.md
src/tools/rustfmt/Contributing.md
src/tools/rustfmt/Design.md
src/tools/rustfmt/README.md
src/tools/rustfmt/ci/integration.sh
src/tools/rustfmt/docs/index.html
src/tools/rustfmt/src/types.rs

index 044979f3baec3b3f9eb8fb6bb5043ad7868643b3..a7b70cea927d0c3b41bbcb4b0cee906be469d192 100644 (file)
@@ -9,7 +9,7 @@ along with any information you feel relevant to replicating the bug.
 
 If you cannot produce a minimal reproduction case (something that would work in
 isolation), please provide the steps or even link to a repository that causes
-the problematic output to occur. 
+the problematic output to occur.
 -->
 
 Given the following code: <!-- Please provide a link to play.rust-lang.org -->
index cbc4465fcfe38a6d76d809a440c7097179f8dd41..e879594b87a100603670ffe688c8cf00dd4cc5df 100644 (file)
@@ -2,7 +2,7 @@
 name: Library Tracking Issue
 about: A tracking issue for an unstable library feature.
 title: Tracking Issue for XXX
-labels: C-tracking-issue, T-libs
+labels: C-tracking-issue, T-libs-api
 ---
 <!--
 Thank you for creating a tracking issue!
@@ -60,7 +60,7 @@ unresolved questions left, the feature might be ready for stabilization.
 If this feature didn't go through the RFC process, a final commenting period
 (FCP) is always needed before stabilization. This works as follows:
 
-A library team member can kick off the stabilization process, at which point
+A library API team member can kick off the stabilization process, at which point
 the rfcbot will ask all the team members to verify they agree with
 stabilization. Once enough members agree and there are no concerns, the final
 commenting period begins: this issue will be marked as such and will be listed
index 2f06506eaa458f64c271cdee3647aa4a091c4587..4a4f4d04c7743f0a14fbdc3df64157bf52a8bcf6 100644 (file)
@@ -179,6 +179,7 @@ dependencies = [
  "libc",
  "merge",
  "num_cpus",
+ "once_cell",
  "opener",
  "pretty_assertions",
  "serde",
@@ -1482,6 +1483,17 @@ dependencies = [
  "regex",
 ]
 
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
+dependencies = [
+ "bitflags",
+ "ignore",
+ "walkdir",
+]
+
 [[package]]
 name = "gsgdt"
 version = "0.1.2"
@@ -4518,6 +4530,7 @@ dependencies = [
  "serde_json",
  "smallvec",
  "tempfile",
+ "tera",
  "tracing",
  "tracing-subscriber",
  "tracing-tree",
@@ -4609,9 +4622,9 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
+checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
 
 [[package]]
 name = "ryu"
@@ -5099,6 +5112,21 @@ dependencies = [
  "utf-8",
 ]
 
+[[package]]
+name = "tera"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62"
+dependencies = [
+ "globwalk",
+ "lazy_static",
+ "pest",
+ "pest_derive",
+ "regex",
+ "serde",
+ "serde_json",
+]
+
 [[package]]
 name = "term"
 version = "0.0.0"
index af6a4090a27cb58c85b1ddd2adb6accdea2efa80..cf75f4184a1c96a0eab4def408ee84a76594759d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Read ["Installation"] from [The Book].
 The Rust build system uses a Python script called `x.py` to build the compiler,
 which manages the bootstrapping process. It lives in the root of the project.
 
-The `x.py` command can be run directly on most systems in the following format: 
+The `x.py` command can be run directly on most systems in the following format:
 
 ```sh
 ./x.py <subcommand> [flags]
index 4b753a2b32fff9bf3c29e0c5510678323dca411c..35e5627e61ff86f95f9547751ea938b656ccd1a5 100644 (file)
@@ -369,7 +369,7 @@ Language
 --------
 - [You can now parameterize items such as functions, traits, and `struct`s by constant
   values in addition to by types and lifetimes.][79135] Also known as "const generics"
-  E.g. you can now write the following. Note: Only values of primitive integers, 
+  E.g. you can now write the following. Note: Only values of primitive integers,
   `bool`, or `char` types are currently permitted.
   ```rust
   struct GenericArray<T, const LENGTH: usize> {
@@ -1749,6 +1749,7 @@ Language
 - [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
   that you can create an enum that has the exact layout and ABI of the type
   it contains.
+- [You can now use outer attribute procedural macros on inline modules.][64273]  
 - [There are some *syntax-only* changes:][67131]
    - `default` is syntactically allowed before items in `trait` definitions.
    - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
@@ -1810,6 +1811,7 @@ Compatibility Notes
 [67935]: https://github.com/rust-lang/rust/pull/67935/
 [68339]: https://github.com/rust-lang/rust/pull/68339/
 [68122]: https://github.com/rust-lang/rust/pull/68122/
+[64273]: https://github.com/rust-lang/rust/pull/64273/
 [67712]: https://github.com/rust-lang/rust/pull/67712/
 [67887]: https://github.com/rust-lang/rust/pull/67887/
 [67131]: https://github.com/rust-lang/rust/pull/67131/
index 93d7a597681339e3cfddea236667e67f4a371667..d3f5a37fd6e09729e51fe087d0be87037e7fdc9b 100644 (file)
@@ -1017,7 +1017,7 @@ pub struct Local {
 /// ```
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Arm {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
     pub pat: P<Pat>,
     /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
@@ -2293,7 +2293,7 @@ pub struct EnumDef {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Variant {
     /// Attributes of the variant.
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     /// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
     pub id: NodeId,
     /// Span
@@ -2474,7 +2474,7 @@ pub fn is_pub(&self) -> bool {
 /// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FieldDef {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
index 0b6099fd330dad615198553db46362b523bfe637..296766f80191c51ddacda724718e3ce7b89b2b85 100644 (file)
@@ -420,7 +420,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 
 pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
-    visit_attrs(attrs, vis);
+    visit_thin_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -504,7 +504,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     visitor.visit_id(id);
     visitor.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -918,7 +918,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
-    visit_attrs(attrs, visitor);
+    visit_thin_attrs(attrs, visitor);
     smallvec![fd]
 }
 
index b1a73a0bf02778ee001e706fec743a92834d91b6..8abd85a5a5214e9f9c20e429fc5ce0272e37560f 100644 (file)
@@ -49,7 +49,7 @@ fn test_variant_to_string() {
                 kind: ast::VisibilityKind::Inherited,
                 tokens: None,
             },
-            attrs: Vec::new(),
+            attrs: ast::AttrVec::new(),
             id: ast::DUMMY_NODE_ID,
             data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
index 79dc857074d5990ae1320deea5668f8db9c922eb..d7b46f282151fe32ac11e8dc1432d98f0ba58bb6 100644 (file)
     annotatable: Annotatable,
 ) -> Vec<Annotatable> {
     check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
-    cfg_eval(ecx, annotatable)
+    vec![cfg_eval(ecx, annotatable)]
 }
 
-crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
-    let mut visitor = CfgEval {
+crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
+    CfgEval {
         cfg: &mut StripUnconfigured {
             sess: ecx.sess,
             features: ecx.ecfg.features,
             config_tokens: true,
         },
-    };
-    let annotatable = visitor.configure_annotatable(annotatable);
-    vec![annotatable]
+    }
+    .configure_annotatable(annotatable)
+    // Since the item itself has already been configured by the `InvocationCollector`,
+    // we know that fold result vector will contain exactly one element.
+    .unwrap()
 }
 
 struct CfgEval<'a, 'b> {
     cfg: &'a mut StripUnconfigured<'b>,
 }
 
-fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable {
-    // Since the item itself has already been configured by the InvocationCollector,
-    // we know that fold result vector will contain exactly one element
+fn flat_map_annotatable(
+    vis: &mut impl MutVisitor,
+    annotatable: Annotatable,
+) -> Option<Annotatable> {
     match annotatable {
-        Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()),
+        Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
         Annotatable::TraitItem(item) => {
-            Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap())
+            vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
         }
         Annotatable::ImplItem(item) => {
-            Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap())
+            vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
         }
         Annotatable::ForeignItem(item) => {
-            Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap())
+            vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
         }
         Annotatable::Stmt(stmt) => {
-            Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap()))
+            vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt)
         }
-        Annotatable::Expr(mut expr) => Annotatable::Expr({
+        Annotatable::Expr(mut expr) => {
             vis.visit_expr(&mut expr);
-            expr
-        }),
-        Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()),
-        Annotatable::ExprField(field) => {
-            Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap())
+            Some(Annotatable::Expr(expr))
         }
-        Annotatable::PatField(fp) => {
-            Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap())
+        Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm),
+        Annotatable::ExprField(field) => {
+            vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField)
         }
+        Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField),
         Annotatable::GenericParam(param) => {
-            Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap())
-        }
-        Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()),
-        Annotatable::FieldDef(sf) => {
-            Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap())
+            vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam)
         }
-        Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()),
+        Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
+        Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
+        Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
     }
 }
 
@@ -123,11 +122,11 @@ fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
         self.cfg.configure(node)
     }
 
-    pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable {
+    fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
         // Tokenizing and re-parsing the `Annotatable` can have a significant
         // performance impact, so try to avoid it if possible
         if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) {
-            return annotatable;
+            return Some(annotatable);
         }
 
         // The majority of parsed attribute targets will never need to have early cfg-expansion
index 1bb050a40cee23c813d617f5d024bded7b38a3e6..60d6bae38b56c89c251913fd2eea4235611d87b6 100644 (file)
@@ -26,6 +26,8 @@ fn expand(
             return ExpandResult::Ready(vec![item]);
         }
 
+        let item = cfg_eval(ecx, item);
+
         let result =
             ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
                 let template =
@@ -54,12 +56,12 @@ fn expand(
                         report_path_args(sess, &meta);
                         meta.path
                     })
-                    .map(|path| (path, None))
+                    .map(|path| (path, item.clone(), None))
                     .collect()
             });
 
         match result {
-            Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
+            Ok(()) => ExpandResult::Ready(vec![item]),
             Err(Indeterminate) => ExpandResult::Retry(item),
         }
     }
index 49b5e8466bef2bd3d94324cad71750b785a57a31..b6def164fac631002bc920ed071bf2fb10eba5a2 100644 (file)
@@ -5,7 +5,7 @@
 use crate::traits::*;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
@@ -16,7 +16,29 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
 ) -> BitSet<mir::Local> {
     let mir = fx.mir;
-    let mut analyzer = LocalAnalyzer::new(fx);
+    let dominators = mir.dominators();
+    let locals = mir
+        .local_decls
+        .iter()
+        .map(|decl| {
+            let ty = fx.monomorphize(decl.ty);
+            let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
+            if layout.is_zst() {
+                LocalKind::ZST
+            } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
+                LocalKind::Unused
+            } else {
+                LocalKind::Memory
+            }
+        })
+        .collect();
+
+    let mut analyzer = LocalAnalyzer { fx, dominators, locals };
+
+    // Arguments get assigned to by means of the function being called
+    for arg in mir.args_iter() {
+        analyzer.assign(arg, mir::START_BLOCK.start_location());
+    }
 
     // If there exists a local definition that dominates all uses of that local,
     // the definition should be visited first. Traverse blocks in preorder which
@@ -25,76 +47,45 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         analyzer.visit_basic_block_data(bb, data);
     }
 
-    for (local, decl) in mir.local_decls.iter_enumerated() {
-        let ty = fx.monomorphize(decl.ty);
-        debug!("local {:?} has type `{}`", local, ty);
-        let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
-        if fx.cx.is_backend_immediate(layout) {
-            // These sorts of types are immediates that we can store
-            // in an Value without an alloca.
-        } else if fx.cx.is_backend_scalar_pair(layout) {
-            // We allow pairs and uses of any of their 2 fields.
-        } else {
-            // These sorts of types require an alloca. Note that
-            // is_llvm_immediate() may *still* be true, particularly
-            // for newtypes, but we currently force some types
-            // (e.g., structs) into an alloca unconditionally, just so
-            // that we don't have to deal with having two pathways
-            // (gep vs extractvalue etc).
-            analyzer.not_ssa(local);
+    let mut non_ssa_locals = BitSet::new_empty(analyzer.locals.len());
+    for (local, kind) in analyzer.locals.iter_enumerated() {
+        if matches!(kind, LocalKind::Memory) {
+            non_ssa_locals.insert(local);
         }
     }
 
-    analyzer.non_ssa_locals
+    non_ssa_locals
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum LocalKind {
+    ZST,
+    /// A local that requires an alloca.
+    Memory,
+    /// A scalar or a scalar pair local that is neither defined nor used.
+    Unused,
+    /// A scalar or a scalar pair local with a single definition that dominates all uses.
+    SSA(mir::Location),
 }
 
 struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     fx: &'mir FunctionCx<'a, 'tcx, Bx>,
     dominators: Dominators<mir::BasicBlock>,
-    non_ssa_locals: BitSet<mir::Local>,
-    // The location of the first visited direct assignment to each
-    // local, or an invalid location (out of bounds `block` index).
-    first_assignment: IndexVec<mir::Local, Location>,
+    locals: IndexVec<mir::Local, LocalKind>,
 }
 
 impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
-    fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self {
-        let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
-        let dominators = fx.mir.dominators();
-        let mut analyzer = LocalAnalyzer {
-            fx,
-            dominators,
-            non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
-            first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls),
-        };
-
-        // Arguments get assigned to by means of the function being called
-        for arg in fx.mir.args_iter() {
-            analyzer.first_assignment[arg] = mir::START_BLOCK.start_location();
-        }
-
-        analyzer
-    }
-
-    fn first_assignment(&self, local: mir::Local) -> Option<Location> {
-        let location = self.first_assignment[local];
-        if location.block.index() < self.fx.mir.basic_blocks().len() {
-            Some(location)
-        } else {
-            None
-        }
-    }
-
-    fn not_ssa(&mut self, local: mir::Local) {
-        debug!("marking {:?} as non-SSA", local);
-        self.non_ssa_locals.insert(local);
-    }
-
     fn assign(&mut self, local: mir::Local, location: Location) {
-        if self.first_assignment(local).is_some() {
-            self.not_ssa(local);
-        } else {
-            self.first_assignment[local] = location;
+        let kind = &mut self.locals[local];
+        match *kind {
+            LocalKind::ZST => {}
+            LocalKind::Memory => {}
+            LocalKind::Unused => {
+                *kind = LocalKind::SSA(location);
+            }
+            LocalKind::SSA(_) => {
+                *kind = LocalKind::Memory;
+            }
         }
     }
 
@@ -175,11 +166,13 @@ fn visit_assign(
     ) {
         debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
 
-        if let Some(index) = place.as_local() {
-            self.assign(index, location);
-            let decl_span = self.fx.mir.local_decls[index].source_info.span;
-            if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
-                self.not_ssa(index);
+        if let Some(local) = place.as_local() {
+            self.assign(local, location);
+            if self.locals[local] != LocalKind::Memory {
+                let decl_span = self.fx.mir.local_decls[local].source_info.span;
+                if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
+                    self.locals[local] = LocalKind::Memory;
+                }
             }
         } else {
             self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
@@ -204,32 +197,18 @@ fn visit_local(&mut self, &local: &mir::Local, context: PlaceContext, location:
 
             PlaceContext::NonMutatingUse(
                 NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
-            ) => {
+            ) => match &mut self.locals[local] {
+                LocalKind::ZST => {}
+                LocalKind::Memory => {}
+                LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {}
                 // Reads from uninitialized variables (e.g., in dead code, after
                 // optimizations) require locals to be in (uninitialized) memory.
                 // N.B., there can be uninitialized reads of a local visited after
                 // an assignment to that local, if they happen on disjoint paths.
-                let ssa_read = match self.first_assignment(local) {
-                    Some(assignment_location) => {
-                        assignment_location.dominates(location, &self.dominators)
-                    }
-                    None => {
-                        debug!("No first assignment found for {:?}", local);
-                        // We have not seen any assignment to the local yet,
-                        // but before marking not_ssa, check if it is a ZST,
-                        // in which case we don't need to initialize the local.
-                        let ty = self.fx.mir.local_decls[local].ty;
-                        let ty = self.fx.monomorphize(ty);
-
-                        let is_zst = self.fx.cx.layout_of(ty).is_zst();
-                        debug!("is_zst: {}", is_zst);
-                        is_zst
-                    }
-                };
-                if !ssa_read {
-                    self.not_ssa(local);
+                kind @ (LocalKind::Unused | LocalKind::SSA(_)) => {
+                    *kind = LocalKind::Memory;
                 }
-            }
+            },
 
             PlaceContext::MutatingUse(
                 MutatingUseContext::Store
@@ -246,16 +225,18 @@ fn visit_local(&mut self, &local: &mir::Local, context: PlaceContext, location:
                 | NonMutatingUseContext::AddressOf
                 | NonMutatingUseContext::Projection,
             ) => {
-                self.not_ssa(local);
+                self.locals[local] = LocalKind::Memory;
             }
 
             PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
-                let ty = self.fx.mir.local_decls[local].ty;
-                let ty = self.fx.monomorphize(ty);
-
-                // Only need the place if we're actually dropping it.
-                if self.fx.cx.type_needs_drop(ty) {
-                    self.not_ssa(local);
+                let kind = &mut self.locals[local];
+                if *kind != LocalKind::Memory {
+                    let ty = self.fx.mir.local_decls[local].ty;
+                    let ty = self.fx.monomorphize(ty);
+                    if self.fx.cx.type_needs_drop(ty) {
+                        // Only need the place if we're actually dropping it.
+                        *kind = LocalKind::Memory;
+                    }
                 }
             }
         }
index aab2741c85240c1b4d08ffa72a7ec5a998726702..96fd6cb68e8b93419cc6d9a40b9d02327fc9cba3 100644 (file)
@@ -835,7 +835,7 @@ pub fn expn_data(
 /// Error type that denotes indeterminacy.
 pub struct Indeterminate;
 
-pub type DeriveResolutions = Vec<(ast::Path, Option<Lrc<SyntaxExtension>>)>;
+pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
 
 pub trait ResolverExpand {
     fn next_node_id(&mut self) -> NodeId;
index ef5b97a946909707e20767b6be5921525451e85a..824df2757ea90eb2bc231a4483db31d5b695881a 100644 (file)
@@ -432,7 +432,7 @@ pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
 
     pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
         ast::Arm {
-            attrs: vec![],
+            attrs: AttrVec::new(),
             pat,
             guard: None,
             body: expr,
index 39c0447bd099eadc87a28c52c6804c623b0e396f..f8a12ef8a208197d381fc8c1d5989ad26c49f4e0 100644 (file)
@@ -427,7 +427,6 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
     pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
         let orig_expansion_data = self.cx.current_expansion.clone();
         let orig_force_mode = self.cx.force_mode;
-        self.cx.current_expansion.depth = 0;
 
         // Collect all macro invocations and replace them with placeholders.
         let (mut fragment_with_placeholders, mut invocations) =
@@ -488,6 +487,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
             };
 
             let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
+            let depth = depth - orig_expansion_data.depth;
             self.cx.current_expansion = invoc.expansion_data.clone();
             self.cx.force_mode = force;
 
@@ -500,42 +500,16 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
                         .resolver
                         .take_derive_resolutions(expn_id)
                         .map(|derives| {
-                            enum AnnotatableRef<'a> {
-                                Item(&'a P<ast::Item>),
-                                Stmt(&'a ast::Stmt),
-                            }
-                            let item = match &fragment {
-                                AstFragment::Items(items) => match &items[..] {
-                                    [item] => AnnotatableRef::Item(item),
-                                    _ => unreachable!(),
-                                },
-                                AstFragment::Stmts(stmts) => match &stmts[..] {
-                                    [stmt] => AnnotatableRef::Stmt(stmt),
-                                    _ => unreachable!(),
-                                },
-                                _ => unreachable!(),
-                            };
-
                             derive_invocations.reserve(derives.len());
                             derives
                                 .into_iter()
-                                .map(|(path, _exts)| {
+                                .map(|(path, item, _exts)| {
                                     // FIXME: Consider using the derive resolutions (`_exts`)
                                     // instead of enqueuing the derives to be resolved again later.
                                     let expn_id = ExpnId::fresh(None);
                                     derive_invocations.push((
                                         Invocation {
-                                            kind: InvocationKind::Derive {
-                                                path,
-                                                item: match item {
-                                                    AnnotatableRef::Item(item) => {
-                                                        Annotatable::Item(item.clone())
-                                                    }
-                                                    AnnotatableRef::Stmt(stmt) => {
-                                                        Annotatable::Stmt(P(stmt.clone()))
-                                                    }
-                                                },
-                                            },
+                                            kind: InvocationKind::Derive { path, item },
                                             fragment_kind,
                                             expansion_data: ExpansionData {
                                                 id: expn_id,
index 577d43b1c8e5e3c1f9c19671815f682deea0cdb5..bb8d6386d8a746ba81c0c9919db752374e6fa03a 100644 (file)
@@ -1205,8 +1205,6 @@ pub struct ExprField<'hir> {
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
-    PushUnsafeBlock(UnsafeSource),
-    PopUnsafeBlock(UnsafeSource),
 }
 
 #[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
index 2b932b7c9537ee51a7cb1d007719463707e98150..d11dca1cba47de1a01528caef1dbc3a2f27b81db 100644 (file)
@@ -1070,8 +1070,6 @@ pub fn print_block_maybe_unclosed(
     ) {
         match blk.rules {
             hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
-            hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
-            hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
             hir::BlockCheckMode::DefaultBlock => (),
         }
         self.maybe_print_comment(blk.span.lo());
index 5d8a6084f2e0b486809c8705314e423618cbeab3..f486a82ef953ef0d9c09a2742aa5d98c00a75f52 100644 (file)
@@ -715,7 +715,6 @@ macro_rules! tracked {
     tracked!(no_codegen, true);
     tracked!(no_generate_arange_section, true);
     tracked!(no_link, true);
-    tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
     tracked!(plt, Some(true));
@@ -724,6 +723,7 @@ macro_rules! tracked {
     tracked!(print_fuel, Some("abc".to_string()));
     tracked!(profile, true);
     tracked!(profile_emit, Some(PathBuf::from("abc")));
+    tracked!(profiler_runtime, None);
     tracked!(relax_elf_relocations, Some(true));
     tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
index 44c2a550c30e2d40af462a89bd4afda3f30c49d2..c431c048ca01c1179dbfdf976b4a982a4905de39 100644 (file)
@@ -154,6 +154,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
                 | hir::BinOpKind::Shl
                 | hir::BinOpKind::Shr => Some("bitwise operation"),
             },
+            hir::ExprKind::AddrOf(..) => Some("borrow"),
             hir::ExprKind::Unary(..) => Some("unary operation"),
             _ => None,
         };
index 352146d64635ad69f72e56cac4c6ac926174426a..f95d4a6ca54812b2efb33dce2d2ad6a46ae9dd72 100644 (file)
     pub OR_PATTERNS_BACK_COMPAT,
     Allow,
     "detects usage of old versions of or-patterns",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #84869 <https://github.com/rust-lang/rust/issues/84869>",
+        edition: Some(Edition::Edition2021),
+    };
 }
index 30569f20793fbae6431915bd63d0c43074690f39..b916113a0e551f8e50df375831751344139f0fdd 100644 (file)
@@ -54,7 +54,7 @@ pub fn hash_stable_generic_derive(mut s: synstructure::Structure<'_>) -> proc_ma
             quote! {}
         } else if let Some(project) = attrs.project {
             quote! {
-                &#bi.#project.hash_stable(__hcx, __hasher);
+                (&#bi.#project).hash_stable(__hcx, __hasher);
             }
         } else {
             quote! {
@@ -96,7 +96,7 @@ pub fn hash_stable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::To
             quote! {}
         } else if let Some(project) = attrs.project {
             quote! {
-                &#bi.#project.hash_stable(__hcx, __hasher);
+                (&#bi.#project).hash_stable(__hcx, __hasher);
             }
         } else {
             quote! {
index d73cfe35dc4a13cc9c2cdd84337411027a2166b5..03a46efec3c7c174bd8b56568fdddf495e8eb920 100644 (file)
@@ -769,28 +769,32 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
     }
 
     fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
-        if (self.sess.instrument_coverage()
-            || self.sess.opts.debugging_opts.profile
-            || self.sess.opts.cg.profile_generate.enabled())
-            && !self.sess.opts.debugging_opts.no_profiler_runtime
+        let profiler_runtime = &self.sess.opts.debugging_opts.profiler_runtime;
+
+        if !(profiler_runtime.is_some()
+            && (self.sess.instrument_coverage()
+                || self.sess.opts.debugging_opts.profile
+                || self.sess.opts.cg.profile_generate.enabled()))
         {
-            info!("loading profiler");
+            return;
+        }
 
-            if self.sess.contains_name(&krate.attrs, sym::no_core) {
-                self.sess.err(
-                    "`profiler_builtins` crate (required by compiler options) \
-                               is not compatible with crate attribute `#![no_core]`",
-                );
-            }
+        info!("loading profiler");
+
+        let name = Symbol::intern(profiler_runtime.as_ref().unwrap());
+        if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
+            self.sess.err(
+                "`profiler_builtins` crate (required by compiler options) \
+                        is not compatible with crate attribute `#![no_core]`",
+            );
+        }
 
-            let name = sym::profiler_builtins;
-            let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
-            let data = self.cstore.get_crate_data(cnum);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+        let data = self.cstore.get_crate_data(cnum);
 
-            // Sanity check the loaded crate to ensure it is indeed a profiler runtime
-            if !data.is_profiler_runtime() {
-                self.sess.err("the crate `profiler_builtins` is not a profiler runtime");
-            }
+        // Sanity check the loaded crate to ensure it is indeed a profiler runtime
+        if !data.is_profiler_runtime() {
+            self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
         }
     }
 
index 6e7360950908e9dbd164ff0c7f7ecfebb93f4b91..8570bf30f80787a7c2ac8bb0a3c13207438c8d40 100644 (file)
@@ -1100,7 +1100,9 @@ impl CrateError {
                         if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
                             err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
                         }
-                    } else if crate_name == sym::profiler_builtins {
+                    } else if Some(crate_name)
+                        == sess.opts.debugging_opts.profiler_runtime.as_deref().map(Symbol::intern)
+                    {
                         err.note(&"the compiler may have been built without the profiler runtime");
                     }
                     err.span_label(span, "can't find crate");
index 9d1b3e101a92ea654f14c527972d7c22337090bc..cb2a355697dd0e10e164c7b89fc6b3779a656161 100644 (file)
@@ -525,6 +525,7 @@ pub fn is_hard_err(&self) -> bool {
         use InterpError::*;
         match *self {
             MachineStop(ref err) => err.is_hard_err(),
+            InterpError::UndefinedBehavior(_) => true,
             _ => false,
         }
     }
index 7ae7eab6e5a315cda438adbea5f2007cc623b4b6..0daaec272fd902d9c6f97a10d34e4294c881176e 100644 (file)
@@ -494,8 +494,6 @@ pub fn generator_kind(&self) -> Option<GeneratorKind> {
 #[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum Safety {
     Safe,
-    /// Unsafe because of a PushUnsafeBlock
-    BuiltinUnsafe,
     /// Unsafe because of an unsafe fn
     FnUnsafe,
     /// Unsafe because of an `unsafe` block
index 436cd305a7fc2e08a201cfddfcc56dec2f1e44eb..2f107e7b96c5c2d781da6a050691bc11f378b7fc 100644 (file)
@@ -115,8 +115,6 @@ pub struct Adt<'tcx> {
 pub enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
-    PushUnsafe,
-    PopUnsafe,
 }
 
 #[derive(Debug, HashStable)]
index 73991436b7b6bd834309b91bb474ef4236e66939..a74070100f413131b1cb2e9b4e34b96654110200 100644 (file)
@@ -392,6 +392,34 @@ pub struct TypeckResults<'tcx> {
     /// (including late-bound regions) are replaced with free
     /// equivalents. This table is not used in codegen (since regions
     /// are erased there) and hence is not serialized to metadata.
+    ///
+    /// This table also contains the "revealed" values for any `impl Trait`
+    /// that appear in the signature and whose values are being inferred
+    /// by this function.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// fn foo(x: &u32) -> impl Debug { *x }
+    /// ```
+    ///
+    /// The function signature here would be:
+    ///
+    /// ```
+    /// for<'a> fn(&'a u32) -> Foo
+    /// ```
+    ///
+    /// where `Foo` is an opaque type created for this function.
+    ///
+    ///
+    /// The *liberated* form of this would be
+    ///
+    /// ```
+    /// fn(&'a u32) -> u32
+    /// ```
+    ///
+    /// Note that `'a` is not bound (it would be an `ReFree`) and
+    /// that the `Foo` opaque type is replaced by its hidden type.
     liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
 
     /// For each FRU expression, record the normalized types of the fields
index 28a44b09de2b112ce0e8a366ca541b3ef51329d6..6b1ec1b0646aec1354d6ade066bd2539fae58b32 100644 (file)
@@ -672,6 +672,15 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
 
             // SIMD vector types.
             ty::Adt(def, substs) if def.repr.simd() => {
+                if !def.is_struct() {
+                    // Should have yielded E0517 by now.
+                    tcx.sess.delay_span_bug(
+                        DUMMY_SP,
+                        "#[repr(simd)] was applied to an ADT that is not a struct",
+                    );
+                    return Err(LayoutError::Unknown(ty));
+                }
+
                 // Supported SIMD vectors are homogeneous ADTs with at least one field:
                 //
                 // * #[repr(simd)] struct S(T, T, T, T);
index 09cafddeeffde9213c4f1997e3f4fe69b6d5fdc7..bd951ef72b5c1fc3499e27974573a6f667e2524b 100644 (file)
@@ -1206,6 +1206,36 @@ fn relate_type_and_user_type(
         Ok(())
     }
 
+    /// Equates a type `anon_ty` that may contain opaque types whose
+    /// values are to be inferred by the MIR with def-id `anon_owner_def_id`.
+    ///
+    /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
+    /// hidden types for impl traits revealed.
+    ///
+    /// # Example
+    ///
+    /// Consider a piece of code like
+    ///
+    /// ```rust
+    /// type Foo<U> = impl Debug;
+    ///
+    /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
+    ///      Box::new((t, 22_u32))
+    /// }
+    /// ```
+    ///
+    /// Here, the function signature would be something like
+    /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
+    /// the type with the opaque type revealed, so `Box<(T, u32)>`.
+    ///
+    /// In terms of our function parameters:
+    ///
+    /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
+    ///   scoped to this function (note that it is parameterized by the
+    ///   generics of `foo`). Note that `anon_ty` is not just the opaque type,
+    ///   but the entire return type (which may contain opaque types within it).
+    /// * `revealed_ty` would be `Box<(T, u32)>`
+    /// * `anon_owner_def_id` would be the def-id of `foo`
     fn eq_opaque_type_and_type(
         &mut self,
         revealed_ty: Ty<'tcx>,
@@ -1240,6 +1270,8 @@ fn eq_opaque_type_and_type(
         let tcx = infcx.tcx;
         let param_env = self.param_env;
         let body = self.body;
+
+        // the "concrete opaque types" maps
         let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
         let mut opaque_type_values = VecMap::new();
 
@@ -1252,6 +1284,13 @@ fn eq_opaque_type_and_type(
                     let mut obligations = ObligationAccumulator::default();
 
                     let dummy_body_id = hir::CRATE_HIR_ID;
+
+                    // Replace the opaque types defined by this function with
+                    // inference variables, creating a map. In our example above,
+                    // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
+                    // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
+                    // (Note that the key of the map is both the def-id of `Foo` along with
+                    // any generic parameters.)
                     let (output_ty, opaque_type_map) =
                         obligations.add(infcx.instantiate_opaque_types(
                             anon_owner_def_id,
@@ -1267,6 +1306,7 @@ fn eq_opaque_type_and_type(
                          revealed_ty={:?}",
                         output_ty, opaque_type_map, revealed_ty
                     );
+
                     // Make sure that the inferred types are well-formed. I'm
                     // not entirely sure this is needed (the HIR type check
                     // didn't do this) but it seems sensible to prevent opaque
@@ -1282,6 +1322,9 @@ fn eq_opaque_type_and_type(
                             .eq(output_ty, revealed_ty)?,
                     );
 
+                    // For each opaque type `Foo<T>` inferred by this value, we want to equate
+                    // the inference variable `?T` with the revealed type that was computed
+                    // earlier by type check.
                     for &(opaque_type_key, opaque_decl) in &opaque_type_map {
                         let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
                         let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
@@ -1290,6 +1333,9 @@ fn eq_opaque_type_and_type(
                             false
                         };
 
+                        // The revealed type computed by the earlier phase of type check.
+                        // In our example, this would be `(U, u32)`. Note that this references
+                        // the type parameter `U` from the definition of `Foo`.
                         let concrete_ty = match concrete_opaque_types
                             .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
                         {
@@ -1308,7 +1354,13 @@ fn eq_opaque_type_and_type(
                             Some(concrete_ty) => concrete_ty,
                         };
                         debug!("concrete_ty = {:?}", concrete_ty);
+
+                        // Apply the substitution, in this case `[U -> T]`, so that the
+                        // concrete type becomes `Foo<(T, u32)>`
                         let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
+
+                        // "Renumber" this, meaning that we replace all the regions
+                        // with fresh inference variables. Not relevant to our example.
                         let renumbered_opaque_defn_ty =
                             renumber::renumber_regions(infcx, subst_opaque_defn_ty);
 
@@ -1318,8 +1370,9 @@ fn eq_opaque_type_and_type(
                         );
 
                         if !concrete_is_opaque {
-                            // Equate concrete_ty (an inference variable) with
-                            // the renumbered type from typeck.
+                            // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
+                            // in our example) with the renumbered version that we took from
+                            // the type check results (`Foo<(T, u32)>`).
                             obligations.add(
                                 infcx
                                     .at(&ObligationCause::dummy(), param_env)
index 103ddda1a1d262c45069da1fab78d78404a7776b..324a5257f5dfa446a261824b4a3870d03189a1c4 100644 (file)
@@ -321,7 +321,6 @@ fn register_violations(
                 }
                 false
             }
-            Safety::BuiltinUnsafe => true,
             Safety::ExplicitUnsafe(hir_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
                 if !violations.is_empty() {
index 73a0f5537c3b39739f298d322499db75138ce1af..b56c247127ce4734e465c7f191fc193d5163aa9f 100644 (file)
@@ -1205,12 +1205,9 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                         let mut eval_to_int = |op| {
                             // This can be `None` if the lhs wasn't const propagated and we just
                             // triggered the assert on the value of the rhs.
-                            match self.eval_operand(op, source_info) {
-                                Some(op) => DbgVal::Val(
-                                    self.ecx.read_immediate(&op).unwrap().to_const_int(),
-                                ),
-                                None => DbgVal::Underscore,
-                            }
+                            self.eval_operand(op, source_info).map_or(DbgVal::Underscore, |op| {
+                                DbgVal::Val(self.ecx.read_immediate(&op).unwrap().to_const_int())
+                            })
                         };
                         let msg = match msg {
                             AssertKind::DivisionByZero(op) => {
index 8426b24270d668ab1d1ef24501cdd03fea31d286..4e1983aca9443f7de6f70fe0ab51f92c8bc7d710 100644 (file)
@@ -74,8 +74,7 @@ fn ast_block_stmts(
         // First we build all the statements in the block.
         let mut let_scope_stack = Vec::with_capacity(8);
         let outer_source_scope = this.source_scope;
-        let outer_push_unsafe_count = this.push_unsafe_count;
-        let outer_unpushed_unsafe = this.unpushed_unsafe;
+        let outer_in_scope_unsafe = this.in_scope_unsafe;
         this.update_source_scope_for_safety_mode(span, safety_mode);
 
         let source_info = this.source_info(span);
@@ -206,8 +205,7 @@ fn ast_block_stmts(
         }
         // Restore the original source scope.
         this.source_scope = outer_source_scope;
-        this.push_unsafe_count = outer_push_unsafe_count;
-        this.unpushed_unsafe = outer_unpushed_unsafe;
+        this.in_scope_unsafe = outer_in_scope_unsafe;
         block.unit()
     }
 
@@ -217,8 +215,7 @@ fn update_source_scope_for_safety_mode(&mut self, span: Span, safety_mode: Block
         let new_unsafety = match safety_mode {
             BlockSafety::Safe => None,
             BlockSafety::ExplicitUnsafe(hir_id) => {
-                assert_eq!(self.push_unsafe_count, 0);
-                match self.unpushed_unsafe {
+                match self.in_scope_unsafe {
                     Safety::Safe => {}
                     // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
                     Safety::FnUnsafe
@@ -226,20 +223,9 @@ fn update_source_scope_for_safety_mode(&mut self, span: Span, safety_mode: Block
                             != Level::Allow => {}
                     _ => return,
                 }
-                self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);
+                self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id);
                 Some(Safety::ExplicitUnsafe(hir_id))
             }
-            BlockSafety::PushUnsafe => {
-                self.push_unsafe_count += 1;
-                Some(Safety::BuiltinUnsafe)
-            }
-            BlockSafety::PopUnsafe => {
-                self.push_unsafe_count = self
-                    .push_unsafe_count
-                    .checked_sub(1)
-                    .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
-                if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
-            }
         };
 
         if let Some(unsafety) = new_unsafety {
index 10d6521e7debaab8ebbd11b30ff7aaa623168a16..f5f6da3ec0bbac4cb4e79fa9155fe9404a422997 100644 (file)
@@ -367,12 +367,8 @@ struct Builder<'a, 'tcx> {
     /// `{ STMTS; EXPR1 } + EXPR2`.
     block_context: BlockContext,
 
-    /// The current unsafe block in scope, even if it is hidden by
-    /// a `PushUnsafeBlock`.
-    unpushed_unsafe: Safety,
-
-    /// The number of `push_unsafe_block` levels in scope.
-    push_unsafe_count: usize,
+    /// The current unsafe block in scope
+    in_scope_unsafe: Safety,
 
     /// The vector of all scopes that we have created thus far;
     /// we track this for debuginfo later.
@@ -877,8 +873,7 @@ fn new(
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             guard_context: vec![],
-            push_unsafe_count: 0,
-            unpushed_unsafe: safety,
+            in_scope_unsafe: safety,
             local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
             canonical_user_type_annotations: IndexVec::new(),
             upvar_mutbls: vec![],
index 77235fe9ab33b5f890244e5e1d55ffc79702dce5..4fe8cd8541aaeed9798aaac470bc4aaa3399ee06 100644 (file)
@@ -27,8 +27,6 @@ impl<'tcx> Cx<'tcx> {
             safety_mode: match block.rules {
                 hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
                 hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
-                hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe,
-                hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe,
             },
         }
     }
index 3225d302cb30c45e58440a2cdf11b21b4c10be10..3ea76fb99d53171ab2131427aa86a038aebe844f 100644 (file)
@@ -423,6 +423,7 @@ fn lower_variant_or_leaf(
             _ => {
                 let pattern_error = match res {
                     Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+                    Res::Def(DefKind::Static, _) => PatternError::StaticInPattern(span),
                     _ => PatternError::NonConstPath(span),
                 };
                 self.errors.push(pattern_error);
@@ -468,11 +469,10 @@ fn lower_path(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) ->
         let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
             Ok(Some(i)) => i,
             Ok(None) => {
-                self.errors.push(if is_associated_const {
-                    PatternError::AssocConstInPattern(span)
-                } else {
-                    PatternError::StaticInPattern(span)
-                });
+                // It should be assoc consts if there's no error but we cannot resolve it.
+                debug_assert!(is_associated_const);
+
+                self.errors.push(PatternError::AssocConstInPattern(span));
 
                 return pat_from_kind(PatKind::Wild);
             }
index 6e0229f38a574fc6240e9c73285f79f7211bc467..f611bb6eb43e9e52bddad01bbd7a41e6136b4840 100644 (file)
@@ -20,6 +20,10 @@ fn visit_arm(&mut self, arm: &Arm<'tcx>) {
         walk_arm(self, arm);
     }
 
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        walk_pat(self, pat);
+    }
+
     fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
 }
 
@@ -155,12 +159,13 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
             initializer,
             remainder_scope: _,
             init_scope: _,
-            pattern: _,
+            ref pattern,
             lint_level: _,
         } => {
             if let Some(init) = initializer {
                 visitor.visit_expr(&visitor.thir()[init]);
             }
+            visitor.visit_pat(pattern);
         }
     }
 }
@@ -177,10 +182,56 @@ pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &B
 pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
     match arm.guard {
         Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
-        Some(Guard::IfLet(ref _pat, expr)) => {
+        Some(Guard::IfLet(ref pat, expr)) => {
+            visitor.visit_pat(pat);
             visitor.visit_expr(&visitor.thir()[expr]);
         }
         None => {}
     }
+    visitor.visit_pat(&arm.pattern);
     visitor.visit_expr(&visitor.thir()[arm.body]);
 }
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+    use PatKind::*;
+    match pat.kind.as_ref() {
+        AscribeUserType { subpattern, ascription: _ }
+        | Deref { subpattern }
+        | Binding {
+            subpattern: Some(subpattern),
+            mutability: _,
+            mode: _,
+            var: _,
+            ty: _,
+            is_primary: _,
+            name: _,
+        } => visitor.visit_pat(&subpattern),
+        Binding { .. } | Wild => {}
+        Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+            for subpattern in subpatterns {
+                visitor.visit_pat(&subpattern.pattern);
+            }
+        }
+        Constant { value } => visitor.visit_const(value),
+        Range(range) => {
+            visitor.visit_const(range.lo);
+            visitor.visit_const(range.hi);
+        }
+        Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+            for subpattern in prefix {
+                visitor.visit_pat(&subpattern);
+            }
+            if let Some(pat) = slice {
+                visitor.visit_pat(pat);
+            }
+            for subpattern in suffix {
+                visitor.visit_pat(&subpattern);
+            }
+        }
+        Or { pats } => {
+            for pat in pats {
+                visitor.visit_pat(&pat);
+            }
+        }
+    };
+}
index c8789abc142d6cf1179a8f0bf712398656e58620..88ebf4aca23749ffc96759f71eed9847b83ba775 100644 (file)
@@ -2116,7 +2116,7 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
                     let span = body.span;
                     return Ok((
                         ast::Arm {
-                            attrs,
+                            attrs: attrs.into(),
                             pat,
                             guard,
                             body,
@@ -2170,7 +2170,7 @@ pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {
 
             Ok((
                 ast::Arm {
-                    attrs,
+                    attrs: attrs.into(),
                     pat,
                     guard,
                     body: expr,
index 54e6ff6272c0594cfca0861a3b827ba3505c1b82..2daa9e2485b1b7a02de77e9bb064ccdc8d068759 100644 (file)
@@ -1143,7 +1143,7 @@ fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
                     ident,
                     vis,
                     id: DUMMY_NODE_ID,
-                    attrs: variant_attrs,
+                    attrs: variant_attrs.into(),
                     data: struct_def,
                     disr_expr,
                     span: vlo.to(this.prev_token.span),
@@ -1286,7 +1286,7 @@ fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<FieldDef>> {
                         ident: None,
                         id: DUMMY_NODE_ID,
                         ty,
-                        attrs,
+                        attrs: attrs.into(),
                         is_placeholder: false,
                     },
                     TrailingToken::MaybeComma,
@@ -1460,7 +1460,7 @@ fn parse_name_and_ty(
             vis,
             id: DUMMY_NODE_ID,
             ty,
-            attrs,
+            attrs: attrs.into(),
             is_placeholder: false,
         })
     }
index 3f7db2b6962fa51bb50122e238e00c5d18795160..38d052f988c63fefa192da601a8ef0507bf09d2c 100644 (file)
@@ -380,7 +380,7 @@ fn resolve_derives(
             has_derive_copy: false,
         });
         let parent_scope = self.invocation_parent_scopes[&expn_id];
-        for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
+        for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
             if opt_ext.is_none() {
                 *opt_ext = Some(
                     match self.resolve_macro_path(
index b79adb6f7bcd92a5d2bb4287c018c3bfa84e2638..4d213207fb625265a54ea107e23eefa8bda01b80 100644 (file)
@@ -1114,6 +1114,15 @@ pub fn find(&self, key: &str) -> Option<&Json> {
         }
     }
 
+    /// If the Json value is an Object, deletes the value associated with the
+    /// provided key from the Object and returns it. Otherwise, returns None.
+    pub fn remove_key(&mut self, key: &str) -> Option<Json> {
+        match *self {
+            Json::Object(ref mut map) => map.remove(key),
+            _ => None,
+        }
+    }
+
     /// Attempts to get a nested Json Object for each key in `keys`.
     /// If any key is found not to exist, `find_path` will return `None`.
     /// Otherwise, it will return the Json value associated with the final key.
index af24358fe645ff001fd542ece07c618b59cf9156..5afa8e6a09a69d62508ce278749b6c471163115c 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_data_structures::impl_stable_hash_via_hash;
 
 use rustc_target::abi::{Align, TargetDataLayout};
-use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
+use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TargetWarnings};
 
 use rustc_serialize::json;
 
@@ -899,9 +899,11 @@ pub(super) fn build_target_config(
     target_override: Option<Target>,
     sysroot: &PathBuf,
 ) -> Target {
-    let target_result =
-        target_override.map_or_else(|| Target::search(&opts.target_triple, sysroot), Ok);
-    let target = target_result.unwrap_or_else(|e| {
+    let target_result = target_override.map_or_else(
+        || Target::search(&opts.target_triple, sysroot),
+        |t| Ok((t, TargetWarnings::empty())),
+    );
+    let (target, target_warnings) = target_result.unwrap_or_else(|e| {
         early_error(
             opts.error_format,
             &format!(
@@ -911,6 +913,9 @@ pub(super) fn build_target_config(
             ),
         )
     });
+    for warning in target_warnings.warning_messages() {
+        early_warn(opts.error_format, &warning)
+    }
 
     if !matches!(target.pointer_width, 16 | 32 | 64) {
         early_error(
index 1946bfd78cc38ebab2b757616d79c7dacfe1be18..ebf59bb4cc6795e499cf05c1527bfeb229222ecf 100644 (file)
@@ -1160,8 +1160,6 @@ mod parse {
         "compile without linking"),
     no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
-    no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
-        "prevent automatic injection of the profiler_builtins crate"),
     normalize_docs: bool = (false, parse_bool, [TRACKED],
         "normalize associated items in rustdoc when generating documentation"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
@@ -1205,6 +1203,8 @@ mod parse {
     profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "file path to emit profiling data at runtime when using 'profile' \
         (default based on relative source path)"),
+    profiler_runtime: Option<String> = (Some(String::from("profiler_builtins")), parse_opt_string, [TRACKED],
+        "name of the profiler runtime crate to automatically inject, or None to disable"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
         "enable queries of the dependency graph for regression testing (default: no)"),
     query_stats: bool = (false, parse_bool, [UNTRACKED],
index 86b8389a670e624e5b51d3b495ea91d87199ab74..d8a58ee18cd8eec70762adfde30d4a353e5660d5 100644 (file)
@@ -1284,9 +1284,12 @@ pub fn build_session(
 
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
-    let host = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
+    let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
         early_error(sopts.error_format, &format!("Error loading host specification: {}", e))
     });
+    for warning in target_warnings.warning_messages() {
+        early_warn(sopts.error_format, &warning)
+    }
 
     let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
     let hash_kind = sopts.debugging_opts.src_hash_algorithm.unwrap_or_else(|| {
index cb8f6b9656c6834fd620a2bb02c1bbb035bdb3eb..d39e5a5aa2c3f4bed54ec4272d7e50a94e808000 100644 (file)
@@ -27,6 +27,9 @@
 pub mod asm;
 pub mod spec;
 
+#[cfg(test)]
+mod tests;
+
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
 /// instead of implementing everything in `rustc_middle`.
index 437517989ab2bedd38e39c74d5a1bfab80421bcf..0736ffb52f77aebb5a36bfffad523cb48af3bd3f 100644 (file)
@@ -906,6 +906,38 @@ fn $module() {
     ("bpfel-unknown-none", bpfel_unknown_none),
 }
 
+/// Warnings encountered when parsing the target `json`.
+///
+/// Includes fields that weren't recognized and fields that don't have the expected type.
+#[derive(Debug, PartialEq)]
+pub struct TargetWarnings {
+    unused_fields: Vec<String>,
+    incorrect_type: Vec<String>,
+}
+
+impl TargetWarnings {
+    pub fn empty() -> Self {
+        Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
+    }
+
+    pub fn warning_messages(&self) -> Vec<String> {
+        let mut warnings = vec![];
+        if !self.unused_fields.is_empty() {
+            warnings.push(format!(
+                "target json file contains unused fields: {}",
+                self.unused_fields.join(", ")
+            ));
+        }
+        if !self.incorrect_type.is_empty() {
+            warnings.push(format!(
+                "target json file contains fields whose value doesn't have the correct json type: {}",
+                self.incorrect_type.join(", ")
+            ));
+        }
+        warnings
+    }
+}
+
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
@@ -1448,7 +1480,7 @@ pub fn is_abi_supported(&self, abi: Abi) -> bool {
     }
 
     /// Loads a target descriptor from a JSON object.
-    pub fn from_json(obj: Json) -> Result<Target, String> {
+    pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> {
         // While ugly, this code must remain this way to retain
         // compatibility with existing JSON fields and the internal
         // expected naming of the Target and TargetOptions structs.
@@ -1456,10 +1488,9 @@ pub fn from_json(obj: Json) -> Result<Target, String> {
         // are round-tripped through this code to catch cases where
         // the JSON parser is not updated to match the structs.
 
-        let get_req_field = |name: &str| {
-            obj.find(name)
-                .and_then(Json::as_string)
-                .map(str::to_string)
+        let mut get_req_field = |name: &str| {
+            obj.remove_key(name)
+                .and_then(|j| Json::as_string(&j).map(str::to_string))
                 .ok_or_else(|| format!("Field {} in target specification is required", name))
         };
 
@@ -1473,28 +1504,30 @@ pub fn from_json(obj: Json) -> Result<Target, String> {
             options: Default::default(),
         };
 
+        let mut incorrect_type = vec![];
+
         macro_rules! key {
             ($key_name:ident) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_string) {
-                    base.$key_name = s.to_string();
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                    base.$key_name = s;
                 }
             } );
             ($key_name:ident = $json_name:expr) => ( {
                 let name = $json_name;
-                if let Some(s) = obj.find(&name).and_then(Json::as_string) {
-                    base.$key_name = s.to_string();
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+                    base.$key_name = s;
                 }
             } );
             ($key_name:ident, bool) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_boolean(&j)) {
                     base.$key_name = s;
                 }
             } );
             ($key_name:ident, Option<u32>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
                     if s < 1 || s > 5 {
                         return Err("Not a valid DWARF version number".to_string());
                     }
@@ -1503,13 +1536,13 @@ macro_rules! key {
             } );
             ($key_name:ident, Option<u64>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
                     base.$key_name = Some(s);
                 }
             } );
             ($key_name:ident, MergeFunctions) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<MergeFunctions>() {
                         Ok(mergefunc) => base.$key_name = mergefunc,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1522,7 +1555,7 @@ macro_rules! key {
             } );
             ($key_name:ident, RelocModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<RelocModel>() {
                         Ok(relocation_model) => base.$key_name = relocation_model,
                         _ => return Some(Err(format!("'{}' is not a valid relocation model. \
@@ -1534,7 +1567,7 @@ macro_rules! key {
             } );
             ($key_name:ident, CodeModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<CodeModel>() {
                         Ok(code_model) => base.$key_name = Some(code_model),
                         _ => return Some(Err(format!("'{}' is not a valid code model. \
@@ -1546,7 +1579,7 @@ macro_rules! key {
             } );
             ($key_name:ident, TlsModel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<TlsModel>() {
                         Ok(tls_model) => base.$key_name = tls_model,
                         _ => return Some(Err(format!("'{}' is not a valid TLS model. \
@@ -1558,7 +1591,7 @@ macro_rules! key {
             } );
             ($key_name:ident, PanicStrategy) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s {
                         "unwind" => base.$key_name = PanicStrategy::Unwind,
                         "abort" => base.$key_name = PanicStrategy::Abort,
@@ -1571,7 +1604,7 @@ macro_rules! key {
             } );
             ($key_name:ident, RelroLevel) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<RelroLevel>() {
                         Ok(level) => base.$key_name = level,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1583,7 +1616,7 @@ macro_rules! key {
             } );
             ($key_name:ident, SplitDebuginfo) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<SplitDebuginfo>() {
                         Ok(level) => base.$key_name = level,
                         _ => return Some(Err(format!("'{}' is not a valid value for \
@@ -1595,23 +1628,31 @@ macro_rules! key {
             } );
             ($key_name:ident, list) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(v) = obj.find(&name).and_then(Json::as_array) {
-                    base.$key_name = v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect();
+                if let Some(j) = obj.remove_key(&name){
+                    if let Some(v) = Json::as_array(&j) {
+                        base.$key_name = v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect();
+                    } else {
+                        incorrect_type.push(name)
+                    }
                 }
             } );
             ($key_name:ident, opt_list) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(v) = obj.find(&name).and_then(Json::as_array) {
-                    base.$key_name = Some(v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect());
+                if let Some(j) = obj.remove_key(&name) {
+                    if let Some(v) = Json::as_array(&j) {
+                        base.$key_name = Some(v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect());
+                    } else {
+                        incorrect_type.push(name)
+                    }
                 }
             } );
             ($key_name:ident, optional) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(o) = obj.find(&name[..]) {
+                if let Some(o) = obj.remove_key(&name[..]) {
                     base.$key_name = o
                         .as_string()
                         .map(|s| s.to_string() );
@@ -1619,7 +1660,7 @@ macro_rules! key {
             } );
             ($key_name:ident, LldFlavor) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     if let Some(flavor) = LldFlavor::from_str(&s) {
                         base.$key_name = flavor;
                     } else {
@@ -1633,7 +1674,7 @@ macro_rules! key {
             } );
             ($key_name:ident, LinkerFlavor) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match LinkerFlavor::from_str(s) {
                         Some(linker_flavor) => base.$key_name = linker_flavor,
                         _ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
@@ -1644,7 +1685,7 @@ macro_rules! key {
             } );
             ($key_name:ident, StackProbeType) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| match StackProbeType::from_json(o) {
+                obj.remove_key(&name[..]).and_then(|o| match StackProbeType::from_json(&o) {
                     Ok(v) => {
                         base.$key_name = v;
                         Some(Ok(()))
@@ -1656,25 +1697,29 @@ macro_rules! key {
             } );
             ($key_name:ident, SanitizerSet) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| {
-                    for s in a {
-                        base.$key_name |= match s.as_string() {
-                            Some("address") => SanitizerSet::ADDRESS,
-                            Some("leak") => SanitizerSet::LEAK,
-                            Some("memory") => SanitizerSet::MEMORY,
-                            Some("thread") => SanitizerSet::THREAD,
-                            Some("hwaddress") => SanitizerSet::HWADDRESS,
-                            Some(s) => return Some(Err(format!("unknown sanitizer {}", s))),
-                            _ => return Some(Err(format!("not a string: {:?}", s))),
-                        };
+                if let Some(o) = obj.remove_key(&name[..]) {
+                    if let Some(a) = o.as_array() {
+                        for s in a {
+                            base.$key_name |= match s.as_string() {
+                                Some("address") => SanitizerSet::ADDRESS,
+                                Some("leak") => SanitizerSet::LEAK,
+                                Some("memory") => SanitizerSet::MEMORY,
+                                Some("thread") => SanitizerSet::THREAD,
+                                Some("hwaddress") => SanitizerSet::HWADDRESS,
+                                Some(s) => return Err(format!("unknown sanitizer {}", s)),
+                                _ => return Err(format!("not a string: {:?}", s)),
+                            };
+                        }
+                    } else {
+                        incorrect_type.push(name)
                     }
-                    Some(Ok(()))
-                }).unwrap_or(Ok(()))
+                }
+                Ok::<(), String>(())
             } );
 
             ($key_name:ident, crt_objects_fallback) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match s.parse::<CrtObjectsFallback>() {
                         Ok(fallback) => base.$key_name = Some(fallback),
                         _ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
@@ -1685,7 +1730,7 @@ macro_rules! key {
             } );
             ($key_name:ident, link_objects) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(val) = obj.find(&name[..]) {
+                if let Some(val) = obj.remove_key(&name[..]) {
                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
                         JSON object with fields per CRT object kind.", name))?;
                     let mut args = CrtObjects::new();
@@ -1713,7 +1758,7 @@ macro_rules! key {
             } );
             ($key_name:ident, link_args) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(val) = obj.find(&name[..]) {
+                if let Some(val) = obj.remove_key(&name[..]) {
                     let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
                         JSON object with fields per linker-flavor.", name))?;
                     let mut args = LinkArgs::new();
@@ -1740,22 +1785,26 @@ macro_rules! key {
             } );
             ($key_name:ident, env) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) {
-                    for o in a {
-                        if let Some(s) = o.as_string() {
-                            let p = s.split('=').collect::<Vec<_>>();
-                            if p.len() == 2 {
-                                let k = p[0].to_string();
-                                let v = p[1].to_string();
-                                base.$key_name.push((k, v));
+                if let Some(o) = obj.remove_key(&name[..]) {
+                    if let Some(a) = o.as_array() {
+                        for o in a {
+                            if let Some(s) = o.as_string() {
+                                let p = s.split('=').collect::<Vec<_>>();
+                                if p.len() == 2 {
+                                    let k = p[0].to_string();
+                                    let v = p[1].to_string();
+                                    base.$key_name.push((k, v));
+                                }
                             }
                         }
+                    } else {
+                        incorrect_type.push(name)
                     }
                 }
             } );
             ($key_name:ident, Option<Abi>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
-                obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+                obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
                     match lookup_abi(s) {
                         Some(abi) => base.$key_name = Some(abi),
                         _ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
@@ -1764,20 +1813,26 @@ macro_rules! key {
                 })).unwrap_or(Ok(()))
             } );
             ($key_name:ident, TargetFamilies) => ( {
-                let value = obj.find("target-family");
-                if let Some(v) = value.and_then(Json::as_array) {
-                    base.$key_name = v.iter()
-                        .map(|a| a.as_string().unwrap().to_string())
-                        .collect();
-                } else if let Some(v) = value.and_then(Json::as_string) {
-                    base.$key_name = vec![v.to_string()];
+                if let Some(value) = obj.remove_key("target-family") {
+                    if let Some(v) = Json::as_array(&value) {
+                        base.$key_name = v.iter()
+                            .map(|a| a.as_string().unwrap().to_string())
+                            .collect();
+                    } else if let Some(v) = Json::as_string(&value) {
+                        base.$key_name = vec![v.to_string()];
+                    }
                 }
             } );
         }
 
-        if let Some(s) = obj.find("target-endian").and_then(Json::as_string) {
-            base.endian = s.parse()?;
+        if let Some(j) = obj.remove_key("target-endian") {
+            if let Some(s) = Json::as_string(&j) {
+                base.endian = s.parse()?;
+            } else {
+                incorrect_type.push("target-endian".to_string())
+            }
         }
+
         key!(is_builtin, bool);
         key!(c_int_width = "target-c-int-width");
         key!(os);
@@ -1877,32 +1932,39 @@ macro_rules! key {
         // NB: The old name is deprecated, but support for it is retained for
         // compatibility.
         for name in ["abi-blacklist", "unsupported-abis"].iter() {
-            if let Some(array) = obj.find(name).and_then(Json::as_array) {
-                for name in array.iter().filter_map(|abi| abi.as_string()) {
-                    match lookup_abi(name) {
-                        Some(abi) => {
-                            if abi.generic() {
+            if let Some(j) = obj.remove_key(name) {
+                if let Some(array) = Json::as_array(&j) {
+                    for name in array.iter().filter_map(|abi| abi.as_string()) {
+                        match lookup_abi(name) {
+                            Some(abi) => {
+                                if abi.generic() {
+                                    return Err(format!(
+                                        "The ABI \"{}\" is considered to be supported on all \
+                                        targets and cannot be marked unsupported",
+                                        abi
+                                    ));
+                                }
+
+                                base.unsupported_abis.push(abi)
+                            }
+                            None => {
                                 return Err(format!(
-                                    "The ABI \"{}\" is considered to be supported on all \
-                                    targets and cannot be marked unsupported",
-                                    abi
+                                    "Unknown ABI \"{}\" in target specification",
+                                    name
                                 ));
                             }
-
-                            base.unsupported_abis.push(abi)
-                        }
-                        None => {
-                            return Err(format!(
-                                "Unknown ABI \"{}\" in target specification",
-                                name
-                            ));
                         }
                     }
                 }
             }
         }
 
-        Ok(base)
+        // Each field should have been read using `Json::remove_key` so any keys remaining are unused.
+        let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys();
+        Ok((
+            base,
+            TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type },
+        ))
     }
 
     /// Search for a JSON file specifying the given target triple.
@@ -1914,12 +1976,15 @@ macro_rules! key {
     ///
     /// The error string could come from any of the APIs called, including filesystem access and
     /// JSON decoding.
-    pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result<Target, String> {
+    pub fn search(
+        target_triple: &TargetTriple,
+        sysroot: &PathBuf,
+    ) -> Result<(Target, TargetWarnings), String> {
         use rustc_serialize::json;
         use std::env;
         use std::fs;
 
-        fn load_file(path: &Path) -> Result<Target, String> {
+        fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
             let contents = fs::read(path).map_err(|e| e.to_string())?;
             let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
             Target::from_json(obj)
@@ -1929,7 +1994,7 @@ fn load_file(path: &Path) -> Result<Target, String> {
             TargetTriple::TargetTriple(ref target_triple) => {
                 // check if triple is in list of built-in targets
                 if let Some(t) = load_builtin(target_triple) {
-                    return Ok(t);
+                    return Ok((t, TargetWarnings::empty()));
                 }
 
                 // search for a file named `target_triple`.json in RUST_TARGET_PATH
index f4de8bc0a5803ba9596a532a47373ea09d65e4c6..6730319dcfae24bdffee5968fc43c36bebd8bd60 100644 (file)
@@ -3,7 +3,7 @@
 // Test target self-consistency and JSON encoding/decoding roundtrip.
 pub(super) fn test_target(target: Target) {
     target.check_consistency();
-    assert_eq!(Target::from_json(target.to_json()), Ok(target));
+    assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
 }
 
 impl Target {
diff --git a/compiler/rustc_target/src/tests.rs b/compiler/rustc_target/src/tests.rs
new file mode 100644 (file)
index 0000000..3a737b3
--- /dev/null
@@ -0,0 +1,59 @@
+use crate::spec::Target;
+use rustc_serialize::json::Json;
+use std::str::FromStr;
+
+#[test]
+fn report_unused_fields() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "code-mode": "foo"
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 1);
+    assert!(warnings.warning_messages().join("\n").contains("code-mode"));
+}
+
+#[test]
+fn report_incorrect_json_type() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "link-env-remove": "foo"
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 1);
+    assert!(warnings.warning_messages().join("\n").contains("link-env-remove"));
+}
+
+#[test]
+fn no_warnings_for_valid_target() {
+    let json = Json::from_str(
+        r#"
+    {
+        "arch": "powerpc64",
+        "data-layout": "e-m:e-i64:64-n32:64",
+        "llvm-target": "powerpc64le-elf",
+        "target-pointer-width": "64",
+        "link-env-remove": ["foo"]
+    }
+    "#,
+    )
+    .unwrap();
+    let warnings = Target::from_json(json).unwrap().1;
+    assert_eq!(warnings.warning_messages().len(), 0);
+}
index 89ec211f2627bcadf4ec47f8eb14e5095e71aa2b..0061ce4ed370959383c5880c719844d20b2dbd1d 100644 (file)
@@ -5,7 +5,6 @@
 use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::Node;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
 use rustc_infer::infer::free_regions::FreeRegionRelations;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -982,8 +981,8 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
                             parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
                         };
-                        let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
-                            Some(Node::Item(item)) => match item.kind {
+                        let (in_definition_scope, origin) =
+                            match tcx.hir().expect_item(opaque_hir_id).kind {
                                 // Anonymous `impl Trait`
                                 hir::ItemKind::OpaqueTy(hir::OpaqueTy {
                                     impl_trait_fn: Some(parent),
@@ -1000,12 +999,7 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -
                                     origin,
                                 ),
                                 _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
-                            },
-                            _ => bug!(
-                                "expected item, found {}",
-                                tcx.hir().node_to_string(opaque_hir_id),
-                            ),
-                        };
+                            };
                         if in_definition_scope {
                             let opaque_type_key =
                                 OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
index 5741b6824b5d70662efa746791b3f043a05aae0b..a259fc6a488fc7ce881926a5cb8a3fa279e6d5f7 100644 (file)
@@ -53,7 +53,7 @@ fn equate_intrinsic_type<'tcx>(
     require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
 }
 
-/// Returns `true` if the given intrinsic is unsafe to call or not.
+/// Returns the unsafety of the given intrinsic.
 pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
     match intrinsic {
         sym::abort
index ad7853b7cd0f10282626d5a4d087ca37f6ccd822..8703949f4886aef2664cb53672bd9f35603135c5 100644 (file)
@@ -174,13 +174,12 @@ fn maybe_mut_place(m: hir::Mutability) -> Self {
 pub struct UnsafetyState {
     pub def: hir::HirId,
     pub unsafety: hir::Unsafety,
-    pub unsafe_push_count: u32,
     from_fn: bool,
 }
 
 impl UnsafetyState {
     pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
+        UnsafetyState { def, unsafety, from_fn: true }
     }
 
     pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
@@ -193,19 +192,11 @@ pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
             hir::Unsafety::Unsafe if self.from_fn => self,
 
             unsafety => {
-                let (unsafety, def, count) = match blk.rules {
-                    BlockCheckMode::PushUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap())
-                    }
-                    BlockCheckMode::PopUnsafeBlock(..) => {
-                        (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap())
-                    }
-                    BlockCheckMode::UnsafeBlock(..) => {
-                        (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count)
-                    }
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
+                let (unsafety, def) = match blk.rules {
+                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
+                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
                 };
-                UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false }
+                UnsafetyState { def, unsafety, from_fn: false }
             }
         }
     }
@@ -858,7 +849,7 @@ fn missing_items_err(
     // Obtain the level of indentation ending in `sugg_sp`.
     let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0);
     // Make the whitespace that will make the suggestion have the right indentation.
-    let padding: String = std::iter::repeat(" ").take(indentation).collect();
+    let padding: String = " ".repeat(indentation);
 
     for trait_item in missing_items {
         let snippet = suggestion_signature(&trait_item, tcx);
index 248669a2c0cb8cbc9502e2e6977bd87ee18a71d2..ae61dd1cfce4abd44a22350b4e890749d0b577d0 100644 (file)
@@ -813,6 +813,14 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             match it.kind {
                 hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
                 hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
+                hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
+                    // (#75889): Account for `const C: dyn Fn() -> _ = "";`
+                    if let hir::TyKind::TraitObject(..) = ty.kind {
+                        let mut visitor = PlaceholderHirTyCollector::default();
+                        visitor.visit_item(it);
+                        placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+                    }
+                }
                 _ => (),
             }
         }
index 7fa5353d09b899e7af4872bdb3ee522b41a4788c..9a820f0803f0ade766ea8578cd536443c3cacf2b 100644 (file)
@@ -567,8 +567,8 @@ changelog-seen = 2
 # On Linux target, if crt-static is not enabled, 'no' means dynamic link to
 # `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
 # and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
-# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both 
-# means static link to the in-tree build of llvm libunwind, and 'system' means 
+# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
+# means static link to the in-tree build of llvm libunwind, and 'system' means
 # static link to `libunwind.a` provided by system. Due to the limitation of glibc,
 # it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
 #llvm-libunwind = 'no'
index 21a0fb844e8c4ebff14a42ccc8351d28487b99dc..920a5ca7db067891c871adc1173f2b56254cf7ff 100644 (file)
@@ -177,7 +177,7 @@ pub fn iteration_mut_100000(b: &mut Bencher) {
     bench_iteration_mut(b, 100000);
 }
 
-fn bench_first_and_last(b: &mut Bencher, size: i32) {
+fn bench_first_and_last_nightly(b: &mut Bencher, size: i32) {
     let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
     b.iter(|| {
         for _ in 0..10 {
@@ -187,19 +187,44 @@ fn bench_first_and_last(b: &mut Bencher, size: i32) {
     });
 }
 
+fn bench_first_and_last_stable(b: &mut Bencher, size: i32) {
+    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+    b.iter(|| {
+        for _ in 0..10 {
+            black_box(map.iter().next());
+            black_box(map.iter().next_back());
+        }
+    });
+}
+
+#[bench]
+pub fn first_and_last_0_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_0_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_100_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 100);
+}
+
 #[bench]
-pub fn first_and_last_0(b: &mut Bencher) {
-    bench_first_and_last(b, 0);
+pub fn first_and_last_100_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 100);
 }
 
 #[bench]
-pub fn first_and_last_100(b: &mut Bencher) {
-    bench_first_and_last(b, 100);
+pub fn first_and_last_10k_nightly(b: &mut Bencher) {
+    bench_first_and_last_nightly(b, 10_000);
 }
 
 #[bench]
-pub fn first_and_last_10k(b: &mut Bencher) {
-    bench_first_and_last(b, 10_000);
+pub fn first_and_last_10k_stable(b: &mut Bencher) {
+    bench_first_and_last_stable(b, 10_000);
 }
 
 const BENCH_RANGE_SIZE: i32 = 145;
index 30194aa446f4b43f089c8e61a443f5adc0d68f68..d7519c6d0936c186490cc0ba43f3f81e8c78d590 100644 (file)
@@ -1299,7 +1299,7 @@ fn next(&mut self) -> Option<(&'a K, &'a V)> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_unchecked() })
+            Some(unsafe { self.range.inner.next_unchecked() })
         }
     }
 
@@ -1330,7 +1330,7 @@ fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_back_unchecked() })
+            Some(unsafe { self.range.inner.next_back_unchecked() })
         }
     }
 }
@@ -1368,7 +1368,7 @@ fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_unchecked() })
+            Some(unsafe { self.range.inner.next_unchecked() })
         }
     }
 
@@ -1396,7 +1396,7 @@ fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
             None
         } else {
             self.length -= 1;
-            Some(unsafe { self.range.next_back_unchecked() })
+            Some(unsafe { self.range.inner.next_back_unchecked() })
         }
     }
 }
@@ -1475,7 +1475,7 @@ fn drop(&mut self) {
 #[stable(feature = "btree_drop", since = "1.7.0")]
 impl<K, V> Drop for IntoIter<K, V> {
     fn drop(&mut self) {
-        if let Some(front) = self.range.front.take() {
+        if let Some(front) = self.range.take_front() {
             Dropper { front, remaining_length: self.length };
         }
     }
@@ -1490,8 +1490,7 @@ fn next(&mut self) -> Option<(K, V)> {
             None
         } else {
             self.length -= 1;
-            let front = self.range.front.as_mut().unwrap();
-            let kv = unsafe { front.deallocating_next_unchecked() };
+            let kv = unsafe { self.range.deallocating_next_unchecked() };
             Some(kv.into_key_val())
         }
     }
@@ -1508,8 +1507,7 @@ fn next_back(&mut self) -> Option<(K, V)> {
             None
         } else {
             self.length -= 1;
-            let back = self.range.back.as_mut().unwrap();
-            let kv = unsafe { back.deallocating_next_back_unchecked() };
+            let kv = unsafe { self.range.deallocating_next_back_unchecked() };
             Some(kv.into_key_val())
         }
     }
@@ -1727,7 +1725,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+        self.inner.next_checked()
     }
 
     fn last(mut self) -> Option<(&'a K, &'a V)> {
@@ -1777,12 +1775,6 @@ fn len(&self) -> usize {
 #[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
 
-impl<'a, K, V> Range<'a, K, V> {
-    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
-        unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
-    }
-}
-
 #[stable(feature = "map_into_keys_values", since = "1.54.0")]
 impl<K, V> Iterator for IntoKeys<K, V> {
     type Item = K;
@@ -1862,13 +1854,7 @@ impl<K, V> FusedIterator for IntoValues<K, V> {}
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
-    }
-}
-
-impl<'a, K, V> Range<'a, K, V> {
-    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
-        unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+        self.inner.next_back_checked()
     }
 }
 
@@ -1878,7 +1864,7 @@ impl<K, V> FusedIterator for Range<'_, K, V> {}
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<K, V> Clone for Range<'_, K, V> {
     fn clone(&self) -> Self {
-        Range { inner: LeafRange { front: self.inner.front, back: self.inner.back } }
+        Range { inner: self.inner.clone() }
     }
 }
 
@@ -1887,7 +1873,7 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+        self.inner.next_checked()
     }
 
     fn last(mut self) -> Option<(&'a K, &'a mut V)> {
@@ -1904,10 +1890,6 @@ fn max(mut self) -> Option<(&'a K, &'a mut V)> {
 }
 
 impl<'a, K, V> RangeMut<'a, K, V> {
-    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
-    }
-
     /// Returns an iterator of references over the remaining items.
     #[inline]
     pub(super) fn iter(&self) -> Range<'_, K, V> {
@@ -1918,19 +1900,13 @@ pub(super) fn iter(&self) -> Range<'_, K, V> {
 #[stable(feature = "btree_range", since = "1.17.0")]
 impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
-        if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+        self.inner.next_back_checked()
     }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
 
-impl<'a, K, V> RangeMut<'a, K, V> {
-    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
-        unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
index 563c070dd0f1f81cc0c38b72bbc6a3fdcbfc2cc7..17568f7b005ba64d5b28e503027d0068d2ee68bf 100644 (file)
@@ -4,9 +4,16 @@
 
 use super::node::{marker, ForceResult::*, Handle, NodeRef};
 
+// `front` and `back` are always both `None` or both `Some`.
 pub struct LeafRange<BorrowType, K, V> {
-    pub front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
-    pub back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+    front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+    back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+}
+
+impl<'a, K: 'a, V: 'a> Clone for LeafRange<marker::Immut<'a>, K, V> {
+    fn clone(&self) -> Self {
+        LeafRange { front: self.front.clone(), back: self.back.clone() }
+    }
 }
 
 impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
@@ -14,7 +21,7 @@ pub fn none() -> Self {
         LeafRange { front: None, back: None }
     }
 
-    pub fn is_empty(&self) -> bool {
+    fn is_empty(&self) -> bool {
         self.front == self.back
     }
 
@@ -27,6 +34,81 @@ pub fn reborrow(&self) -> LeafRange<marker::Immut<'_>, K, V> {
     }
 }
 
+impl<'a, K, V> LeafRange<marker::Immut<'a>, K, V> {
+    #[inline]
+    pub fn next_checked(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+    }
+
+    #[inline]
+    pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+    }
+
+    #[inline]
+    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+        debug_assert!(self.front.is_some());
+        unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+        debug_assert!(self.back.is_some());
+        unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+    }
+}
+
+impl<'a, K, V> LeafRange<marker::ValMut<'a>, K, V> {
+    #[inline]
+    pub fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+    }
+
+    #[inline]
+    pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+        if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+    }
+
+    #[inline]
+    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+        debug_assert!(self.front.is_some());
+        unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+        debug_assert!(self.back.is_some());
+        unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+    }
+}
+
+impl<K, V> LeafRange<marker::Dying, K, V> {
+    #[inline]
+    pub fn take_front(
+        &mut self,
+    ) -> Option<Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>> {
+        self.front.take()
+    }
+
+    #[inline]
+    pub unsafe fn deallocating_next_unchecked(
+        &mut self,
+    ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+        debug_assert!(self.front.is_some());
+        let front = self.front.as_mut().unwrap();
+        unsafe { front.deallocating_next_unchecked() }
+    }
+
+    #[inline]
+    pub unsafe fn deallocating_next_back_unchecked(
+        &mut self,
+    ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+        debug_assert!(self.back.is_some());
+        let back = self.back.as_mut().unwrap();
+        unsafe { back.deallocating_next_back_unchecked() }
+    }
+}
+
 impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
     /// Finds the distinct leaf edges delimiting a specified range in a tree.
     ///
@@ -36,7 +118,7 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
     /// result will eventually reach the same edge.
     ///
     /// If there are no such edges, i.e., if the tree contains no key within
-    /// the range, returns a pair of empty options.
+    /// the range, returns an empty `front` and `back`.
     ///
     /// # Safety
     /// Unless `BorrowType` is `Immut`, do not use the handles to visit the same
@@ -191,7 +273,7 @@ pub fn next_kv(
     /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
     /// on the left side, which is either in the same leaf node or in an ancestor node.
     /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
-    pub fn next_back_kv(
+    fn next_back_kv(
         self,
     ) -> Result<
         Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
@@ -216,7 +298,7 @@ impl<BorrowType: marker::BorrowType, K, V>
     /// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
     /// on the right side, which is either in the same internal node or in an ancestor node.
     /// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node.
-    pub fn next_kv(
+    fn next_kv(
         self,
     ) -> Result<
         Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::KV>,
@@ -250,7 +332,7 @@ impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
     /// - The returned KV handle is only valid to access the key and value,
     ///   and only valid until the next call to this method or counterpart
     ///   `deallocating_next_back`.
-    pub unsafe fn deallocating_next(
+    unsafe fn deallocating_next(
         self,
     ) -> Option<(Self, Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV>)>
     {
@@ -316,9 +398,10 @@ impl<'a, K, V> Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Ed
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
             let kv = leaf_edge.next_kv();
+            debug_assert!(kv.is_ok());
             let kv = unsafe { kv.ok().unwrap_unchecked() };
             (kv.next_leaf_edge(), kv.into_kv())
         })
@@ -329,9 +412,10 @@ pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
         super::mem::replace(self, |leaf_edge| {
             let kv = leaf_edge.next_back_kv();
+            debug_assert!(kv.is_ok());
             let kv = unsafe { kv.ok().unwrap_unchecked() };
             (kv.next_back_leaf_edge(), kv.into_kv())
         })
@@ -344,9 +428,10 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+    unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
         let kv = super::mem::replace(self, |leaf_edge| {
             let kv = leaf_edge.next_kv();
+            debug_assert!(kv.is_ok());
             let kv = unsafe { kv.ok().unwrap_unchecked() };
             (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
         });
@@ -359,9 +444,10 @@ pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
     ///
     /// # Safety
     /// There must be another KV in the direction travelled.
-    pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+    unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
         let kv = super::mem::replace(self, |leaf_edge| {
             let kv = leaf_edge.next_back_kv();
+            debug_assert!(kv.is_ok());
             let kv = unsafe { kv.ok().unwrap_unchecked() };
             (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
         });
@@ -403,7 +489,7 @@ pub unsafe fn deallocating_next_unchecked(
     ///
     /// The only safe way to proceed with the updated handle is to compare it, drop it,
     /// or call this method or counterpart `deallocating_next_unchecked` again.
-    pub unsafe fn deallocating_next_back_unchecked(
+    unsafe fn deallocating_next_back_unchecked(
         &mut self,
     ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
         super::mem::replace(self, |leaf_edge| unsafe {
@@ -508,9 +594,7 @@ pub fn next_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, m
     }
 
     /// Returns the leaf edge closest to a KV for backward navigation.
-    pub fn next_back_leaf_edge(
-        self,
-    ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
+    fn next_back_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
         match self.force() {
             Leaf(leaf_kv) => leaf_kv.left_edge(),
             Internal(internal_kv) => {
index 93f5fe45cd6aa28de9313f4ca0da20410800a1b1..a34f530762d52fefa3b9ef6e3eba32111217e644 100644 (file)
@@ -1451,7 +1451,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
 
         unsafe {
             ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx);
-            ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
+            ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
             self.vec.set_len(len + amt);
         }
     }
index 6df8d8c2f354f9a6256bde30bc4e97fa9bfd68d4..a1e819cf8f9e44b1cdfb53905b3dcf92212c4661 100644 (file)
@@ -534,7 +534,7 @@ fn half_a_million_letter_x() -> String {
     #[test]
     #[should_panic]
     fn test_slice_fail() {
-        &"中华Việt Nam"[0..2];
+        let _ = &"中华Việt Nam"[0..2];
     }
 
     panic_cases! {
@@ -714,13 +714,13 @@ mod boundary {
     #[test]
     #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
     fn test_slice_fail_truncated_1() {
-        &LOREM_PARAGRAPH[..1024];
+        let _ = &LOREM_PARAGRAPH[..1024];
     }
     // check the truncation in the panic message
     #[test]
     #[should_panic(expected = "luctus, im`[...]")]
     fn test_slice_fail_truncated_2() {
-        &LOREM_PARAGRAPH[..1024];
+        let _ = &LOREM_PARAGRAPH[..1024];
     }
 }
 
@@ -735,7 +735,7 @@ fn test_str_slice_rangetoinclusive_ok() {
 #[should_panic]
 fn test_str_slice_rangetoinclusive_notok() {
     let s = "abcαβγ";
-    &s[..=3];
+    let _ = &s[..=3];
 }
 
 #[test]
@@ -751,7 +751,7 @@ fn test_str_slicemut_rangetoinclusive_ok() {
 fn test_str_slicemut_rangetoinclusive_notok() {
     let mut s = "abcαβγ".to_owned();
     let s: &mut str = &mut s;
-    &mut s[..=3];
+    let _ = &mut s[..=3];
 }
 
 #[test]
index c203cdafecb03dd27be6f502965adffb715b6491..3b7237016800fac107de9030ec87d79089c279b0 100644 (file)
@@ -542,35 +542,35 @@ fn test_index_out_of_bounds() {
 #[should_panic]
 fn test_slice_out_of_bounds_1() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[!0..];
+    let _ = &x[!0..];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_2() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[..6];
+    let _ = &x[..6];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_3() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[!0..4];
+    let _ = &x[!0..4];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_4() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[1..6];
+    let _ = &x[1..6];
 }
 
 #[test]
 #[should_panic]
 fn test_slice_out_of_bounds_5() {
     let x = vec![1, 2, 3, 4, 5];
-    &x[3..2];
+    let _ = &x[3..2];
 }
 
 #[test]
index f88a6e418c7c819313e069ad44a69a41f9bb2bc9..6af010e796d67bb45564cd2db6eb38228235e240 100644 (file)
@@ -488,6 +488,13 @@ pub const fn as_ptr(&self) -> *mut T {
     /// This call borrows `Cell` mutably (at compile-time) which guarantees
     /// that we possess the only reference.
     ///
+    /// However be cautious: this method expects `self` to be mutable, which is
+    /// generally not the case when using a `Cell`. If you require interior
+    /// mutability by reference, consider using `RefCell` which provides
+    /// run-time checked mutable borrows through its [`borrow_mut`] method.
+    ///
+    /// [`borrow_mut`]: RefCell::borrow_mut()
+    ///
     /// # Examples
     ///
     /// ```
@@ -578,7 +585,7 @@ pub struct RefCell<T: ?Sized> {
     // Stores the location of the earliest currently active borrow.
     // This gets updated whenver we go from having zero borrows
     // to having a single borrow. When a borrow occurs, this gets included
-    // in the generated `BorroeError/`BorrowMutError`
+    // in the generated `BorrowError/`BorrowMutError`
     #[cfg(feature = "debug_refcell")]
     borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
     value: UnsafeCell<T>,
index ecea898504dc70a7784e7b2d52db991d70d908d7..6c2f09514a611a38e978daeb9144e7cfd6468832 100644 (file)
 /// Trait for equality comparisons which are [partial equivalence
 /// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
+/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
+/// We use the easier-to-read infix notation in the remainder of this documentation.
+///
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
 /// so floating point types implement `PartialEq` but not [`trait@Eq`].
 ///
-/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
-/// `C`):
+/// Implementations must ensure that `eq` and `ne` are consistent with each other:
+///
+/// - `a != b` if and only if `!(a == b)`
+///   (ensured by the default implementation).
+///
+/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
+/// be consistent with `PartialEq` (see the documentation of those traits for the exact
+/// requirememts). It's easy to accidentally make them disagree by deriving some of the traits and
+/// manually implementing others.
+///
+/// The equality relation `==` must satisfy the following conditions
+/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
 ///
 /// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
 ///   implies `b == a`**; and
 ///
 /// ## How can I implement `PartialEq`?
 ///
-/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
-/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
-/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
-/// only if `a != b`.
-///
-/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
-/// each other. It's easy to accidentally make them disagree by deriving some
-/// of the traits and manually implementing others.
-///
 /// An example implementation for a domain in which two books are considered
 /// the same book if their ISBN matches, even if the formats differ:
 ///
@@ -631,10 +635,25 @@ fn clone_from(&mut self, other: &Self) {
 
 /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
 ///
-/// An order is a total order if it is (for all `a`, `b` and `c`):
+/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
+/// `max`, `min`, and `clamp` are consistent with `cmp`:
+///
+/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
+/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
+/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
+/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
+///   (ensured by the default implementation).
+///
+/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
+/// deriving some of the traits and manually implementing others.
+///
+/// ## Corollaries
+///
+/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
+/// This means that for all `a`, `b` and `c`:
 ///
-/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
-/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
+/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
 ///
 /// ## Derivable
 ///
@@ -659,12 +678,6 @@ fn clone_from(&mut self, other: &Self) {
 /// Then you must define an implementation for [`cmp`]. You may find it useful to use
 /// [`cmp`] on your type's fields.
 ///
-/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
-/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
-/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
-/// all `a` and `b`. It's easy to accidentally make them disagree by
-/// deriving some of the traits and manually implementing others.
-///
 /// Here's an example where you want to sort people by height only, disregarding `id`
 /// and `name`:
 ///
@@ -824,15 +837,45 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 
 /// Trait for values that can be compared for a sort-order.
 ///
+/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
+/// the `<`, `<=`, `>`, and `>=` operators, respectively.
+///
+/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
+/// the following sense:
+///
+/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
+/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
+///   (ensured by the default implementation).
+/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
+///   (ensured by the default implementation).
+/// - `a <= b` if and only if `a < b || a == b`
+///   (ensured by the default implementation).
+/// - `a >= b` if and only if `a > b || a == b`
+///   (ensured by the default implementation).
+/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
+///
+/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
+/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
+/// easy to accidentally make them disagree by deriving some of the traits and manually
+/// implementing others.
+///
 /// The comparison must satisfy, for all `a`, `b` and `c`:
 ///
-/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
 /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - duality: `a < b` if and only if `b > a`.
 ///
 /// Note that these requirements mean that the trait itself must be implemented symmetrically and
 /// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
 /// PartialOrd<V>`.
 ///
+/// ## Corollaries
+///
+/// The following corollaries follow from the above requirements:
+///
+/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
+/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
+/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
+///
 /// ## Derivable
 ///
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
@@ -850,10 +893,6 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 ///
 /// `PartialOrd` requires your type to be [`PartialEq`].
 ///
-/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
-/// easy to accidentally make them disagree by deriving some of the traits and manually
-/// implementing others.
-///
 /// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
 ///
 /// ```
index 8a6955060e82fd2e8322e63df5f55de592a23647..46bf93dcc01e2b5a130b5ad2621fbf93b1967d99 100644 (file)
@@ -295,9 +295,10 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
                 let sz_a = self.a.size();
                 if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
                     for _ in 0..sz_a - self.len {
+                        self.a_len -= 1;
                         self.a.next_back();
                     }
-                    self.a_len = self.len;
+                    debug_assert_eq!(self.a_len, self.len);
                 }
                 let sz_b = self.b.size();
                 if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
index 797bfd957f906ec2cc4c28632cc621e0b3f1fcc2..585cfbb90e40c1d3cfcd5d1718b0f77d7765d1c3 100644 (file)
@@ -232,6 +232,33 @@ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
     assert_eq!(z2.next().unwrap(), ((1, 1), 1));
 }
 
+#[test]
+#[cfg(panic = "unwind")]
+fn test_zip_trusted_random_access_next_back_drop() {
+    use std::panic::catch_unwind;
+    use std::panic::AssertUnwindSafe;
+
+    let mut counter = 0;
+
+    let it = [42].iter().map(|e| {
+        let c = counter;
+        counter += 1;
+        if c == 0 {
+            panic!("bomb");
+        }
+
+        e
+    });
+    let it2 = [(); 0].iter();
+    let mut zip = it.zip(it2);
+    catch_unwind(AssertUnwindSafe(|| {
+        zip.next_back();
+    }))
+    .unwrap_err();
+    assert!(zip.next().is_none());
+    assert_eq!(counter, 1);
+}
+
 #[test]
 fn test_double_ended_zip() {
     let xs = [1, 2, 3, 4, 5, 6];
index 26fbf50e2dfdf903f940495dc28a30d3adddc774..53f172717f0a55fe41a39af8684de3afc7192118 100644 (file)
@@ -708,7 +708,7 @@ pub fn span(&self) -> Span {
     /// pub fn span_open(&self) -> Span {
     ///                 ^
     /// ```
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
     pub fn span_open(&self) -> Span {
         Span(self.0.span_open())
     }
@@ -719,7 +719,7 @@ pub fn span_open(&self) -> Span {
     /// pub fn span_close(&self) -> Span {
     ///                        ^
     /// ```
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
     pub fn span_close(&self) -> Span {
         Span(self.0.span_close())
     }
index a1636e2f604cf772a547048a2f3ac7903de09031..9076656f64e9fc250d38d78f7c81428657fa81fc 100644 (file)
@@ -1007,6 +1007,32 @@ pub fn is_file(&self) -> bool {
         self.file_type().is_file()
     }
 
+    /// Returns `true` if this metadata is for a symbolic link.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(unix, doc = "```no_run")]
+    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// #![feature(is_symlink)]
+    /// use std::fs;
+    /// use std::path::Path;
+    /// use std::os::unix::fs::symlink;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let link_path = Path::new("link");
+    ///     symlink("/origin_does_not_exists/", link_path)?;
+    ///
+    ///     let metadata = fs::symlink_metadata(link_path)?;
+    ///
+    ///     assert!(metadata.is_symlink());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "is_symlink", issue = "85748")]
+    pub fn is_symlink(&self) -> bool {
+        self.file_type().is_symlink()
+    }
+
     /// Returns the size of the file, in bytes, this metadata is for.
     ///
     /// # Examples
index a25ef8c87a5d23e5eeda8674241957799984e645..00b85604a3f67bd5bd4dbd00b4f8313eb56aa5de 100644 (file)
@@ -2005,6 +2005,37 @@ pub trait BufRead: Read {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn consume(&mut self, amt: usize);
 
+    /// Check if the underlying `Read` has any data left to be read.
+    ///
+    /// This function may fill the buffer to check for data,
+    /// so this functions returns `Result<bool>`, not `bool`.
+    ///
+    /// Default implementation calls `fill_buf` and checks that
+    /// returned slice is empty (which means that there is no data left,
+    /// since EOF is reached).
+    ///
+    /// Examples
+    ///
+    /// ```
+    /// #![feature(buf_read_has_data_left)]
+    /// use std::io;
+    /// use std::io::prelude::*;
+    ///
+    /// let stdin = io::stdin();
+    /// let mut stdin = stdin.lock();
+    ///
+    /// while stdin.has_data_left().unwrap() {
+    ///     let mut line = String::new();
+    ///     stdin.read_line(&mut line).unwrap();
+    ///     // work with line
+    ///     println!("{:?}", line);
+    /// }
+    /// ```
+    #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")]
+    fn has_data_left(&mut self) -> Result<bool> {
+        self.fill_buf().map(|b| !b.is_empty())
+    }
+
     /// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
     ///
     /// This function will read bytes from the underlying stream until the
index 2ee30f5fb4f08cbd7e9f98d3beb61d3dd6327345..b73bcf85fbee25cdddb446bd3dbe37e27f6c26f7 100644 (file)
@@ -71,6 +71,16 @@ fn lines() {
     assert!(s.next().is_none());
 }
 
+#[test]
+fn buf_read_has_data_left() {
+    let mut buf = Cursor::new(&b"abcd"[..]);
+    assert!(buf.has_data_left().unwrap());
+    buf.read_exact(&mut [0; 2]).unwrap();
+    assert!(buf.has_data_left().unwrap());
+    buf.read_exact(&mut [0; 2]).unwrap();
+    assert!(!buf.has_data_left().unwrap());
+}
+
 #[test]
 fn read_to_end() {
     let mut c = Cursor::new(&b""[..]);
index 664cc748ca6db6f28fff2ee5beeec903880e1166..1c66dc3648f59af01ae0f79b00e23479d70e1283 100644 (file)
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
-#![feature(async_stream)]
 #![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(asm)]
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
+#![feature(async_stream)]
 #![feature(atomic_mut_ptr)]
+#![feature(auto_traits)]
 #![feature(bench_black_box)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
-#![feature(const_fn_transmute)]
 #![feature(const_fn_fn_ptr_basics)]
+#![feature(const_fn_transmute)]
 #![feature(const_io_structs)]
 #![feature(const_ip)]
+#![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_socketaddr)]
-#![feature(const_ipv4)]
 #![feature(container_error_extra)]
 #![feature(core_intrinsics)]
 #![feature(custom_test_frameworks)]
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(once_cell)]
-#![feature(auto_traits)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
 #![feature(unboxed_closures)]
 #![feature(unsafe_cell_raw_get)]
 #![feature(unwind_attributes)]
+#![feature(unwrap_infallible)]
 #![feature(vec_into_raw_parts)]
 #![feature(vec_spare_capacity)]
 // NB: the above list is sorted to minimize merge conflicts.
index 63fc5ff2866a81c1b7f3e0de1d0c4d259199ef25..ac1db0e5e39cc2edb181fb70fc5bcadfe7ec532a 100644 (file)
@@ -34,5 +34,8 @@
 
 #![unstable(feature = "sgx_platform", issue = "56975")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
index 07b59a02556d9f3e8ea80c4b941c593219c5b2af..19761fd99b400f3cee75b55c855bc5b5e567757f 100644 (file)
@@ -34,5 +34,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
diff --git a/library/std/src/os/unix/ffi.rs b/library/std/src/os/unix/ffi.rs
deleted file mode 100644 (file)
index 123f85d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-//! Unix-specific extension to the primitives in the `std::ffi` module.
-//!
-//! # Examples
-//!
-//! ```
-//! use std::ffi::OsString;
-//! use std::os::unix::ffi::OsStringExt;
-//!
-//! let bytes = b"foo".to_vec();
-//!
-//! // OsStringExt::from_vec
-//! let os_string = OsString::from_vec(bytes);
-//! assert_eq!(os_string.to_str(), Some("foo"));
-//!
-//! // OsStringExt::into_vec
-//! let bytes = os_string.into_vec();
-//! assert_eq!(bytes, b"foo");
-//! ```
-//!
-//! ```
-//! use std::ffi::OsStr;
-//! use std::os::unix::ffi::OsStrExt;
-//!
-//! let bytes = b"foo";
-//!
-//! // OsStrExt::from_bytes
-//! let os_str = OsStr::from_bytes(bytes);
-//! assert_eq!(os_str.to_str(), Some("foo"));
-//!
-//! // OsStrExt::as_bytes
-//! let bytes = os_str.as_bytes();
-//! assert_eq!(bytes, b"foo");
-//! ```
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
diff --git a/library/std/src/os/unix/ffi/mod.rs b/library/std/src/os/unix/ffi/mod.rs
new file mode 100644 (file)
index 0000000..c29df65
--- /dev/null
@@ -0,0 +1,40 @@
+//! Unix-specific extension to the primitives in the `std::ffi` module.
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::unix::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::unix::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod os_str;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::os_str::{OsStrExt, OsStringExt};
diff --git a/library/std/src/os/unix/ffi/os_str.rs b/library/std/src/os/unix/ffi/os_str.rs
new file mode 100644 (file)
index 0000000..54c9a93
--- /dev/null
@@ -0,0 +1,68 @@
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sealed::Sealed;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+// Note: this file is currently reused in other `std::os::{platform}::ffi` modules to reduce duplication.
+// Keep this in mind when applying changes to this file that only apply to `unix`.
+
+/// Platform-specific extensions to [`OsString`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt: Sealed {
+    /// Creates an [`OsString`] from a byte vector.
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this [`OsString`].
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// Platform-specific extensions to [`OsStr`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt: Sealed {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    /// Creates an [`OsStr`] from a byte slice.
+    ///
+    /// See the module documentation for an example.
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the [`OsStr`] slice.
+    ///
+    /// See the module documentation for an example.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    #[inline]
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    #[inline]
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
index f71f316d1ba1088b8667d495bfe401f674badde7..17e12a395a67047529abcaafb412c76fa556911c 100644 (file)
@@ -2,5 +2,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
index 6ccf4c9656e087b52f96314e4e56bfce4755880c..c71751efb9f9aa3a9e421b3163e8c36195bf6103 100644 (file)
@@ -2592,6 +2592,32 @@ pub fn is_dir(&self) -> bool {
         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
     }
 
+    /// Returns true if the path exists on disk and is pointing at a symbolic link.
+    ///
+    /// This function will not traverse symbolic links.
+    /// In case of a broken symbolic link this will also return true.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return false.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(unix, doc = "```no_run")]
+    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// #![feature(is_symlink)]
+    /// use std::path::Path;
+    /// use std::os::unix::fs::symlink;
+    ///
+    /// let link_path = Path::new("link");
+    /// symlink("/origin_does_not_exists/", link_path).unwrap();
+    /// assert_eq!(link_path.is_symlink(), true);
+    /// assert_eq!(link_path.exists(), false);
+    /// ```
+    #[unstable(feature = "is_symlink", issue = "85748")]
+    pub fn is_symlink(&self) -> bool {
+        fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
+    }
+
     /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
index 1e19aff51f8d6bb8054298096333b013590490f1..72e6c23ee49907a5b1b760577518ead2d7680ffb 100644 (file)
@@ -24,18 +24,32 @@ fn lang_start_internal(
     main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
     argc: isize,
     argv: *const *const u8,
-) -> isize {
-    use crate::panic;
-    use crate::sys_common;
-
+) -> Result<isize, !> {
+    use crate::{mem, panic, sys, sys_common};
+    let rt_abort = move |e| {
+        mem::forget(e);
+        rtabort!("initialization or cleanup bug");
+    };
+    // Guard against the code called by this function from unwinding outside of the Rust-controlled
+    // code, which is UB. This is a requirement imposed by a combination of how the
+    // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
+    // mechanism itself.
+    //
+    // There are a couple of instances where unwinding can begin. First is inside of the
+    // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a
+    // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to
+    // prevent libstd from accidentally introducing a panic to these functions. Another is from
+    // user code from `main` or, more nefariously, as described in e.g. issue #86030.
     // SAFETY: Only called once during runtime initialization.
-    unsafe { sys_common::rt::init(argc, argv) };
-
-    let exit_code = panic::catch_unwind(main);
-
-    sys_common::rt::cleanup();
-
-    exit_code.unwrap_or(101) as isize
+    panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?;
+    let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
+        .map_err(move |e| {
+            mem::forget(e);
+            rtprintpanic!("drop of the panic payload panicked");
+            sys::abort_internal()
+        });
+    panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?;
+    ret_code
 }
 
 #[cfg(not(test))]
@@ -50,4 +64,5 @@ fn lang_start<T: crate::process::Termination + 'static>(
         argc,
         argv,
     )
+    .into_ok()
 }
index 4eb0d8437ba5f5f7ef8ab050689853d5d5738fdb..1c7e1dd8d57787f53747468b8277e7047f522ce3 100644 (file)
@@ -55,8 +55,8 @@ fn next_back(&mut self) -> Option<OsString> {
 mod imp {
     use super::Args;
     use crate::ffi::{CStr, OsString};
+    use crate::os::unix::ffi::OsStringExt;
     use crate::ptr;
-    use crate::sys_common::os_str_bytes::*;
 
     use crate::sys_common::mutex::StaticMutex;
 
index 76ea70d997f5d7044ed0479354142d45def9b956..be019d4435db59a28e57369d650056818816587f 100644 (file)
@@ -3,6 +3,7 @@
 use crate::hash::{Hash, Hasher};
 use crate::io::{self, Error, ErrorKind};
 use crate::io::{IoSlice, IoSliceMut, SeekFrom};
+use crate::os::unix::ffi::OsStrExt;
 use crate::path::{Path, PathBuf};
 use crate::sys::cvt;
 use crate::sys::hermit::abi;
@@ -10,7 +11,6 @@
 use crate::sys::hermit::fd::FileDesc;
 use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::OsStrExt;
 
 pub use crate::sys_common::fs::{copy, try_exists};
 //pub use crate::sys_common::fs::remove_dir_all;
index 40bd393098f5731d37db8127529f36883105d884..eeb30a578c05be476216eec5147af764c10253c9 100644 (file)
@@ -4,13 +4,13 @@
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
+use crate::os::unix::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::Mutex;
 use crate::sys::hermit::abi;
 use crate::sys::memchr;
 use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::*;
 use crate::vec;
 
 pub fn errno() -> i32 {
index 32705c432fa8a2d5e6f1b518ecd8624b035d71f8..470f401a6d254ef954c65f9cf5e5e6f04fb3093f 100644 (file)
@@ -2,30 +2,25 @@
 //! systems: just a `Vec<u8>`/`[u8]`.
 
 use crate::borrow::Cow;
-use crate::ffi::{OsStr, OsString};
+
 use crate::fmt;
 use crate::mem;
 use crate::rc::Rc;
-use crate::sealed::Sealed;
 use crate::str;
 use crate::sync::Arc;
 use crate::sys_common::bytestring::debug_fmt_bytestring;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{AsInner, IntoInner};
 
 use core::str::lossy::Utf8Lossy;
 
 #[derive(Hash)]
-pub(crate) struct Buf {
+#[repr(transparent)]
+pub struct Buf {
     pub inner: Vec<u8>,
 }
 
-// FIXME:
-// `Buf::as_slice` current implementation relies
-// on `Slice` being layout-compatible with `[u8]`.
-// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`.
-// Anyway, `Slice` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
-pub(crate) struct Slice {
+#[repr(transparent)]
+pub struct Slice {
     pub inner: [u8],
 }
 
@@ -243,63 +238,3 @@ pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
         self.inner.eq_ignore_ascii_case(&other.inner)
     }
 }
-
-/// Platform-specific extensions to [`OsString`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt: Sealed {
-    /// Creates an [`OsString`] from a byte vector.
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_vec(vec: Vec<u8>) -> Self;
-
-    /// Yields the underlying byte vector of this [`OsString`].
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
-    fn from_vec(vec: Vec<u8>) -> OsString {
-        FromInner::from_inner(Buf { inner: vec })
-    }
-    fn into_vec(self) -> Vec<u8> {
-        self.into_inner().inner
-    }
-}
-
-/// Platform-specific extensions to [`OsStr`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt: Sealed {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    /// Creates an [`OsStr`] from a byte slice.
-    ///
-    /// See the module documentation for an example.
-    fn from_bytes(slice: &[u8]) -> &Self;
-
-    /// Gets the underlying byte view of the [`OsStr`] slice.
-    ///
-    /// See the module documentation for an example.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn as_bytes(&self) -> &[u8];
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
-    #[inline]
-    fn from_bytes(slice: &[u8]) -> &OsStr {
-        unsafe { mem::transmute(slice) }
-    }
-    #[inline]
-    fn as_bytes(&self) -> &[u8] {
-        &self.as_inner().inner
-    }
-}
index 7d4b0d5283199012a23425cd3afd50d7591e0ba7..1bd3cfd2200ffb2935882acbe213c4d298aced38 100644 (file)
@@ -853,10 +853,11 @@ fn next(&mut self) -> Option<u16> {
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (low, high) = self.code_points.size_hint();
+        let ext = (self.extra != 0) as usize;
         // every code point gets either one u16 or two u16,
         // so this iterator is between 1 or 2 times as
         // long as the underlying iterator.
-        (low, high.and_then(|n| n.checked_mul(2)))
+        (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
     }
 }
 
index 385e01f92fa14388af2a3f874dd015b28d20c49b..1bafbaa69392222d97666bf7b0ff5973ea350543 100644 (file)
@@ -301,7 +301,7 @@ fn wtf8_slice() {
 #[test]
 #[should_panic]
 fn wtf8_slice_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[2..4];
+    let _ = &Wtf8::from_str("aé 💩")[2..4];
 }
 
 #[test]
@@ -312,7 +312,7 @@ fn wtf8_slice_from() {
 #[test]
 #[should_panic]
 fn wtf8_slice_from_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[2..];
+    let _ = &Wtf8::from_str("aé 💩")[2..];
 }
 
 #[test]
@@ -323,7 +323,7 @@ fn wtf8_slice_to() {
 #[test]
 #[should_panic]
 fn wtf8_slice_to_not_code_point_boundary() {
-    &Wtf8::from_str("aé 💩")[5..];
+    let _ = &Wtf8::from_str("aé 💩")[5..];
 }
 
 #[test]
@@ -395,3 +395,15 @@ fn wtf8_encode_wide() {
         vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]
     );
 }
+
+#[test]
+fn wtf8_encode_wide_size_hint() {
+    let string = Wtf8Buf::from_str("\u{12345}");
+    let mut iter = string.encode_wide();
+    assert_eq!((1, Some(8)), iter.size_hint());
+    iter.next().unwrap();
+    assert_eq!((1, Some(1)), iter.size_hint());
+    iter.next().unwrap();
+    assert_eq!((0, Some(0)), iter.size_hint());
+    assert!(iter.next().is_none());
+}
index ec66fc1219ff7fd4df997f8209432f658abb882b..c4b0e1e5c23392f00a4eaada6a288fb53a03df11 100644 (file)
@@ -79,7 +79,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message("<failure type=\"assert\"/>")?;
                     self.write_message("</testcase>")?;
@@ -91,7 +91,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message(&*format!("<failure message=\"{}\" type=\"assert\"/>", m))?;
                     self.write_message("</testcase>")?;
@@ -103,7 +103,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
                          name=\"{}\" time=\"{}\">",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                     self.write_message("<failure type=\"timeout\"/>")?;
                     self.write_message("</testcase>")?;
@@ -123,7 +123,7 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result<bool> {
                          name=\"{}\" time=\"{}\"/>",
                         class_name,
                         test_name,
-                        duration.as_secs()
+                        duration.as_secs_f64()
                     ))?;
                 }
             }
index 8445d811e0f393f2f26d7a7757968cbbb10ae842..d1e666936f88a3b778bbd33574c38061a3297cd7 100644 (file)
@@ -50,6 +50,7 @@ time = "0.1"
 ignore = "0.4.10"
 opener = "0.4"
 merge = "0.1.0"
+once_cell = "1.7.2"
 
 [target.'cfg(windows)'.dependencies.winapi]
 version = "0.3"
index bc499fdba5996379d74b4926102d371705d77684..e2f605257bd9548235776640c268f435708d3851 100644 (file)
@@ -29,6 +29,8 @@
 use crate::{Build, DocTests, GitRepo, Mode};
 
 pub use crate::Compiler;
+// FIXME: replace with std::lazy after it gets stabilized and reaches beta
+use once_cell::sync::Lazy;
 
 pub struct Builder<'a> {
     pub build: &'a Build,
@@ -195,7 +197,7 @@ fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
 
         if paths.is_empty() || builder.config.include_default_paths {
             for (desc, should_run) in v.iter().zip(&should_runs) {
-                if desc.default && should_run.is_really_default {
+                if desc.default && should_run.is_really_default() {
                     for pathset in &should_run.paths {
                         desc.maybe_run(builder, pathset);
                     }
@@ -228,7 +230,11 @@ fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
     }
 }
 
-#[derive(Clone)]
+enum ReallyDefault<'a> {
+    Bool(bool),
+    Lazy(Lazy<bool, Box<dyn Fn() -> bool + 'a>>),
+}
+
 pub struct ShouldRun<'a> {
     pub builder: &'a Builder<'a>,
     // use a BTreeSet to maintain sort order
@@ -236,7 +242,7 @@ pub struct ShouldRun<'a> {
 
     // If this is a default rule, this is an additional constraint placed on
     // its run. Generally something like compiler docs being enabled.
-    is_really_default: bool,
+    is_really_default: ReallyDefault<'a>,
 }
 
 impl<'a> ShouldRun<'a> {
@@ -244,15 +250,27 @@ fn new(builder: &'a Builder<'_>) -> ShouldRun<'a> {
         ShouldRun {
             builder,
             paths: BTreeSet::new(),
-            is_really_default: true, // by default no additional conditions
+            is_really_default: ReallyDefault::Bool(true), // by default no additional conditions
         }
     }
 
     pub fn default_condition(mut self, cond: bool) -> Self {
-        self.is_really_default = cond;
+        self.is_really_default = ReallyDefault::Bool(cond);
+        self
+    }
+
+    pub fn lazy_default_condition(mut self, lazy_cond: Box<dyn Fn() -> bool + 'a>) -> Self {
+        self.is_really_default = ReallyDefault::Lazy(Lazy::new(lazy_cond));
         self
     }
 
+    pub fn is_really_default(&self) -> bool {
+        match &self.is_really_default {
+            ReallyDefault::Bool(val) => *val,
+            ReallyDefault::Lazy(lazy) => *lazy.deref(),
+        }
+    }
+
     /// Indicates it should run if the command-line selects the given crate or
     /// any of its (local) dependencies.
     ///
index 4d7c207e3ab8b3cfe60b8c33b52e8e1c3101531b..e7fb8c0d4d5d20357d85afdb462ad3dbc69c7d39 100644 (file)
@@ -613,9 +613,14 @@ fn test_docs() {
         // Note that the stages here are +1 than what they actually are because
         // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
         // not 0.
+        //
+        // The stage 0 copy is the one downloaded for bootstrapping. It is
+        // (currently) needed to run "cargo test" on the linkchecker, and
+        // should be relatively "free".
         assert_eq!(
             first(builder.cache.all::<tool::Rustdoc>()),
             &[
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },
                 tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
                 tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
             ]
index 0b7a0e25df1ac10c06d87f99f0d637392094d88b..93ba8b07f5b3a108a28ca2dc6e17a97454f27523 100644 (file)
@@ -124,8 +124,25 @@ fn run(self, builder: &Builder<'_>) {
 
         builder.info(&format!("Linkcheck ({})", host));
 
+        // Test the linkchecker itself.
+        let bootstrap_host = builder.config.build;
+        let compiler = builder.compiler(0, bootstrap_host);
+        let cargo = tool::prepare_tool_cargo(
+            builder,
+            compiler,
+            Mode::ToolBootstrap,
+            bootstrap_host,
+            "test",
+            "src/tools/linkchecker",
+            SourceType::InTree,
+            &[],
+        );
+        try_run(builder, &mut cargo.into());
+
+        // Build all the default documentation.
         builder.default_doc(&[]);
 
+        // Run the linkchecker.
         let _time = util::timeit(&builder);
         try_run(
             builder,
@@ -806,15 +823,15 @@ impl Step for RustdocGUI {
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
         let run = run.suite_path("src/test/rustdoc-gui");
-        run.default_condition(
+        run.lazy_default_condition(Box::new(move || {
             builder.config.nodejs.is_some()
                 && builder
                     .config
                     .npm
                     .as_ref()
                     .map(|p| check_if_browser_ui_test_is_installed(p))
-                    .unwrap_or(false),
-        )
+                    .unwrap_or(false)
+        }))
     }
 
     fn make_run(run: RunConfig<'_>) {
index e2c064ee75d233994fd7041722d97564af4f52b4..c33d5b4e4dc72255b409ee3843f4a8fa8d5893c2 100644 (file)
@@ -71,7 +71,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
 # https://github.com/puppeteer/puppeteer/issues/375
 #
 # We also specify the version in case we need to update it to go around cache limitations.
-RUN npm install -g browser-ui-test@0.2.14 --unsafe-perm=true
+RUN npm install -g browser-ui-test@0.3.0 --unsafe-perm=true
 
 ENV RUST_CONFIGURE_ARGS \
   --build=x86_64-unknown-linux-gnu \
index 5ce75949457f582bea9a74979091b40267c87d72..d5957b632dc167abad3f01877c79333cbabcc4e4 100644 (file)
@@ -21,6 +21,7 @@ regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
 tracing = "0.1"
 tracing-tree = "0.1.9"
+tera = { version = "1.10.0", default-features = false }
 
 [dependencies.tracing-subscriber]
 version = "0.2.13"
index 6c86baa36ac7de8dbf9e1f10e3d1c0306756c290..56d2ca57218c55be305c1f1b64c44a9c28199882 100644 (file)
@@ -4,7 +4,9 @@
 use std::path::Path;
 use std::str;
 
-#[derive(Clone, Debug)]
+use serde::Serialize;
+
+#[derive(Clone, Debug, Serialize)]
 crate struct ExternalHtml {
     /// Content that will be included inline in the <head> section of a
     /// rendered Markdown file or generated documentation
index d2d1757b9009ada499bcbb2bf75b9ee23b9f6bbe..6ed603c96bbf2820a5bf2c43d807e0086ddb569f 100644 (file)
@@ -7,7 +7,9 @@
 use crate::html::format::{Buffer, Print};
 use crate::html::render::{ensure_trailing_slash, StylePath};
 
-#[derive(Clone)]
+use serde::Serialize;
+
+#[derive(Clone, Serialize)]
 crate struct Layout {
     crate logo: String,
     crate favicon: String,
@@ -22,6 +24,7 @@
     crate generate_search_filter: bool,
 }
 
+#[derive(Serialize)]
 crate struct Page<'a> {
     crate title: &'a str,
     crate css_class: &'a str,
@@ -40,7 +43,19 @@ impl<'a> Page<'a> {
     }
 }
 
+#[derive(Serialize)]
+struct PageLayout<'a> {
+    static_root_path: &'a str,
+    page: &'a Page<'a>,
+    layout: &'a Layout,
+    style_files: String,
+    sidebar: String,
+    content: String,
+    krate_with_trailing_slash: String,
+}
+
 crate fn render<T: Print, S: Print>(
+    templates: &tera::Tera,
     layout: &Layout,
     page: &Page<'_>,
     sidebar: S,
@@ -48,184 +63,35 @@ impl<'a> Page<'a> {
     style_files: &[StylePath],
 ) -> String {
     let static_root_path = page.get_static_root_path();
-    format!(
-        "<!DOCTYPE html>\
-<html lang=\"en\">\
-<head>\
-    <meta charset=\"utf-8\">\
-    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
-    <meta name=\"generator\" content=\"rustdoc\">\
-    <meta name=\"description\" content=\"{description}\">\
-    <meta name=\"keywords\" content=\"{keywords}\">\
-    <title>{title}</title>\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
-    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
-          id=\"mainThemeStyle\">\
-    {style_files}\
-    <script id=\"default-settings\"{default_settings}></script>\
-    <script src=\"{static_root_path}storage{suffix}.js\"></script>\
-    <script src=\"{root_path}crates{suffix}.js\"></script>\
-    <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
-    {css_extension}\
-    {favicon}\
-    {in_header}\
-    <style type=\"text/css\">\
-    #crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
-    </style>\
-</head>\
-<body class=\"rustdoc {css_class}\">\
-    <!--[if lte IE 11]>\
-    <div class=\"warning\">\
-        This old browser is unsupported and will most likely display funky \
-        things.\
-    </div>\
-    <![endif]-->\
-    {before_content}\
-    <nav class=\"sidebar\">\
-        <div class=\"sidebar-menu\" role=\"button\">&#9776;</div>\
-        {logo}\
-        {sidebar}\
-    </nav>\
-    <div class=\"theme-picker\">\
-        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\" title=\"themes\">\
-            <img src=\"{static_root_path}brush{suffix}.svg\" \
-                 width=\"18\" height=\"18\" \
-                 alt=\"Pick another theme!\">\
-        </button>\
-        <div id=\"theme-choices\" role=\"menu\"></div>\
-    </div>\
-    <nav class=\"sub\">\
-        <form class=\"search-form\">\
-            <div class=\"search-container\">\
-                <div>{filter_crates}\
-                    <input class=\"search-input\" name=\"search\" \
-                           disabled \
-                           autocomplete=\"off\" \
-                           spellcheck=\"false\" \
-                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
-                           type=\"search\">\
-                </div>\
-                <button type=\"button\" id=\"help-button\" title=\"help\">?</button>\
-                <a id=\"settings-menu\" href=\"{root_path}settings.html\" title=\"settings\">\
-                    <img src=\"{static_root_path}wheel{suffix}.svg\" \
-                         width=\"18\" height=\"18\" \
-                         alt=\"Change settings\">\
-                </a>\
-            </div>\
-        </form>\
-    </nav>\
-    <section id=\"main\" class=\"content\">{content}</section>\
-    <section id=\"search\" class=\"content hidden\"></section>\
-    {after_content}\
-    <div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \
-       data-search-index-js=\"{root_path}search-index{suffix}.js\" \
-       data-search-js=\"{static_root_path}search{suffix}.js\"></div>\
-    <script src=\"{static_root_path}main{suffix}.js\"></script>\
-    {extra_scripts}\
-</body>\
-</html>",
-        css_extension = if layout.css_file_extension.is_some() {
+    let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
+    let style_files = style_files
+        .iter()
+        .filter_map(|t| {
+            if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
+        })
+        .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None })
+        .map(|t| {
             format!(
-                "<link rel=\"stylesheet\" \
-                       type=\"text/css\" \
-                       href=\"{static_root_path}theme{suffix}.css\">",
-                static_root_path = static_root_path,
-                suffix = page.resource_suffix
-            )
-        } else {
-            String::new()
-        },
-        content = Buffer::html().to_display(t),
-        static_root_path = static_root_path,
-        root_path = page.root_path,
-        css_class = page.css_class,
-        logo = {
-            if layout.logo.is_empty() {
-                format!(
-                    "<a href='{root}{path}index.html'>\
-                     <div class='logo-container rust-logo'>\
-                     <img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
-                    root = page.root_path,
-                    path = ensure_trailing_slash(&layout.krate),
-                    static_root_path = static_root_path,
-                    suffix = page.resource_suffix
-                )
-            } else {
-                format!(
-                    "<a href='{root}{path}index.html'>\
-                     <div class='logo-container'><img src='{logo}' alt='logo'></div></a>",
-                    root = page.root_path,
-                    path = ensure_trailing_slash(&layout.krate),
-                    logo = layout.logo
-                )
-            }
-        },
-        title = page.title,
-        description = Escape(page.description),
-        keywords = page.keywords,
-        favicon = if layout.favicon.is_empty() {
-            format!(
-                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
-                static_root_path = static_root_path,
-                suffix = page.resource_suffix
-            )
-        } else {
-            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
-        },
-        in_header = layout.external_html.in_header,
-        before_content = layout.external_html.before_content,
-        after_content = layout.external_html.after_content,
-        sidebar = Buffer::html().to_display(sidebar),
-        krate = layout.krate,
-        default_settings = layout
-            .default_settings
-            .iter()
-            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
-            .collect::<String>(),
-        style_files = style_files
-            .iter()
-            .filter_map(|t| {
-                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
-            })
-            .filter_map(|t| {
-                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
-            })
-            .map(|t| format!(
                 r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                 Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                 if t.1 { "disabled" } else { "" },
                 if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
-            ))
-            .collect::<String>(),
-        suffix = page.resource_suffix,
-        extra_scripts = page
-            .static_extra_scripts
-            .iter()
-            .map(|e| {
-                format!(
-                    "<script src=\"{static_root_path}{extra_script}.js\"></script>",
-                    static_root_path = static_root_path,
-                    extra_script = e
-                )
-            })
-            .chain(page.extra_scripts.iter().map(|e| {
-                format!(
-                    "<script src=\"{root_path}{extra_script}.js\"></script>",
-                    root_path = page.root_path,
-                    extra_script = e
-                )
-            }))
-            .collect::<String>(),
-        filter_crates = if layout.generate_search_filter {
-            "<select id=\"crate-search\">\
-                 <option value=\"All crates\">All crates</option>\
-             </select>"
-        } else {
-            ""
-        },
-    )
+            )
+        })
+        .collect::<String>();
+    let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
+    let sidebar = Buffer::html().to_display(sidebar);
+    let teractx = tera::Context::from_serialize(PageLayout {
+        static_root_path,
+        page,
+        layout,
+        style_files,
+        sidebar,
+        content,
+        krate_with_trailing_slash,
+    })
+    .unwrap();
+    templates.render("page.html", &teractx).unwrap()
 }
 
 crate fn redirect(url: &str) -> String {
index 1898f5feed2cd13dc55ce3b4e16bf810c337cb0e..2085739fc46ec68e4ef80ea13878a399f59828d2 100644 (file)
@@ -1,5 +1,6 @@
 use std::cell::RefCell;
 use std::collections::BTreeMap;
+use std::error::Error as StdError;
 use std::io;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -29,6 +30,7 @@
 use crate::html::escape::Escape;
 use crate::html::format::Buffer;
 use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
+use crate::html::static_files::PAGE;
 use crate::html::{layout, sources};
 
 /// Major driving force in all rustdoc rendering. This contains information
     /// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
     /// the crate.
     redirections: Option<RefCell<FxHashMap<String, String>>>,
+
+    pub(crate) templates: tera::Tera,
 }
 
 impl SharedContext<'_> {
@@ -218,6 +222,7 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
 
         if !self.render_redirect_pages {
             layout::render(
+                &self.shared.templates,
                 &self.shared.layout,
                 &page,
                 |buf: &mut _| print_sidebar(self, it, buf),
@@ -408,6 +413,12 @@ fn init(
         let mut issue_tracker_base_url = None;
         let mut include_sources = true;
 
+        let mut templates = tera::Tera::default();
+        templates.add_raw_template("page.html", PAGE).map_err(|e| Error {
+            file: "page.html".into(),
+            error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()),
+        })?;
+
         // Crawl the crate attributes looking for attributes which control how we're
         // going to emit HTML
         for attr in krate.module.attrs.lists(sym::doc) {
@@ -454,6 +465,7 @@ fn init(
             errors: receiver,
             redirections: if generate_redirect_map { Some(Default::default()) } else { None },
             show_type_layout,
+            templates,
         };
 
         // Add the default themes to the `Vec` of stylepaths
@@ -540,6 +552,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
         };
         let all = self.shared.all.replace(AllTypes::new());
         let v = layout::render(
+            &self.shared.templates,
             &self.shared.layout,
             &page,
             sidebar,
@@ -557,6 +570,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
         let sidebar = "<p class=\"location\">Settings</p><div class=\"sidebar-elems\"></div>";
         style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
         let v = layout::render(
+            &self.shared.templates,
             &self.shared.layout,
             &page,
             sidebar,
index 499f33f14f56296d45cfd3ff685c39a119838ba9..62d3c142eeb52962c65147814abbe82811085008 100644 (file)
@@ -1997,19 +1997,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 out.push_str("</div>");
             }
         }
-
-        // Recurse into any further impls that might exist for `target`
-        if let Some(target_did) = target.def_id_full(c) {
-            if let Some(target_impls) = c.impls.get(&target_did) {
-                if let Some(target_deref_impl) = target_impls
-                    .iter()
-                    .filter(|i| i.inner_impl().trait_.is_some())
-                    .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did)
-                {
-                    sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
-                }
-            }
-        }
     }
 }
 
index 8fd5353891221c27519036334f1b42fc3532f7b2..48cbd94ccabfbebebc14ac67144b1bf1b5ba012c 100644 (file)
@@ -981,7 +981,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 }
                 w.write_str(")");
             }
-            w.write_str("</code></div>");
+            w.write_str("</code>");
+            render_stability_since(w, variant, it, cx.tcx());
+            w.write_str("</div>");
             document(w, cx, variant, Some(it));
             document_non_exhaustive(w, variant);
 
@@ -1023,7 +1025,6 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 w.write_str("</div></div>");
                 toggle_close(w);
             }
-            render_stability_since(w, variant, it, cx.tcx());
         }
     }
     let def_id = it.def_id.expect_real();
index a4188e6b203bb2ff5649cc7af62141b1a9037011..840566731d78db51fad00712ce5e14f8e60c1d9b 100644 (file)
@@ -460,7 +460,14 @@ fn to_json_string(&self) -> String {
                     })
                     .collect::<String>()
             );
-            let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
+            let v = layout::render(
+                &cx.shared.templates,
+                &cx.shared.layout,
+                &page,
+                "",
+                content,
+                &cx.shared.style_files,
+            );
             cx.shared.fs.write(&dst, v.as_bytes())?;
         }
     }
index 5e2a94fe6845ff3026e12f7462702398ada8b53d..80dd7a7a952f0071fd6501cb29053b6894a7b9fc 100644 (file)
@@ -136,6 +136,7 @@ fn emit_source(&mut self, filename: &FileName) -> Result<(), Error> {
             static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
         };
         let v = layout::render(
+            &self.scx.templates,
             &self.scx.layout,
             &page,
             "",
index d444ea92b6f123b901c30ab7e988cb31ae1bc2bc..ff9afab064a281140f6971a6529c245a9a6ef7e3 100644 (file)
@@ -1,5 +1,5 @@
 Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
-with Reserved Font Name < Fira >, 
+with Reserved Font Name < Fira >,
 
 This Font Software is licensed under the SIL Open Font License, Version 1.1.
 This license is copied below, and is also available with a FAQ at:
@@ -19,7 +19,7 @@ with others.
 
 The OFL allows the licensed fonts to be used, studied, modified and
 redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded, 
+fonts, including any derivative works, can be bundled, embedded,
 redistributed and/or sold with any software provided that any reserved
 names are not used by derivative works. The fonts and derivatives,
 however, cannot be released under any other type of license. The
index 9a59ee528a0c9e90fe3a4e5e1126418fe9f33972..89f5d59224164040d037d9c828a86b1c2684dea4 100644 (file)
@@ -653,6 +653,12 @@ a {
        background: transparent;
 }
 
+.small-section-header {
+       display: flex;
+       justify-content: space-between;
+       position: relative;
+}
+
 .small-section-header:hover > .anchor {
        display: initial;
 }
index ca7e5ef8150809a95cf9b0d169c07b6f4f727e38..00e13d4ec1aa8847a0aec16f154667023fa9eea9 100644 (file)
@@ -64,6 +64,8 @@
 crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
 crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");
 
+crate static PAGE: &str = include_str!("templates/page.html");
+
 /// The built-in themes given to every documentation site.
 crate mod themes {
     /// The "light" theme, selected by default when no setting is available. Used as the basis for
diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md
new file mode 100644 (file)
index 0000000..fff65e3
--- /dev/null
@@ -0,0 +1,37 @@
+# Style for Templates
+
+This directory has templates in the [Tera templating language](teradoc), which is very
+similar to [Jinja2](jinjadoc) and [Django](djangodoc) templates, and also to [Askama](askamadoc).
+
+[teradoc]: https://tera.netlify.app/docs/#templates
+[jinjadoc]: https://jinja.palletsprojects.com/en/3.0.x/templates/
+[djangodoc]: https://docs.djangoproject.com/en/3.2/topics/templates/
+[askamadoc]: https://docs.rs/askama/0.10.5/askama/
+
+We want our rendered output to have as little unnecessary whitespace as
+possible, so that pages load quickly. To achieve that we use Tera's
+[whitespace control] features. At the end of most lines, we put an empty comment
+tag with the whitespace control characters: `{#- -#}`. This causes all
+whitespace between the end of the line and the beginning of the next, including
+indentation, to be omitted on render. Sometimes we want to preserve a single
+space. In those cases we put the space at the end of the line, followed by
+`{# -#}`, which is a directive to remove following whitespace but not preceding.
+We also use the whitespace control characters in most instances of tags with
+control flow, for example `{%- if foo -%}`.
+
+[whitespace control]: https://tera.netlify.app/docs/#whitespace-control
+
+We want our templates to be readable, so we use indentation and newlines
+liberally. We indent by four spaces after opening an HTML tag _or_ a Tera
+tag. In most cases an HTML tag should be followed by a newline, but if the
+tag has simple contents and fits with its close tag on a single line, the
+contents don't necessarily need a new line.
+
+Tera templates support quite sophisticated control flow. To keep our templates
+simple and understandable, we use only a subset: `if` and `for`. In particular
+we avoid [assignments in the template logic](assignments) and [Tera
+macros](macros). This also may make things easier if we switch to a different
+Jinja-style template system, like Askama, in the future.
+
+[assignments]: https://tera.netlify.app/docs/#assignments
+[macros]: https://tera.netlify.app/docs/#macros
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
new file mode 100644 (file)
index 0000000..9b1bef5
--- /dev/null
@@ -0,0 +1,119 @@
+<!DOCTYPE html> {#- -#}
+<html lang="en"> {#- -#}
+<head> {#- -#}
+    <meta charset="utf-8"> {#- -#}
+    <meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
+    <meta name="generator" content="rustdoc"> {#- -#}
+    <meta name="description" content="{{page.description}}"> {#- -#}
+    <meta name="keywords" content="{{page.keywords}}"> {#- -#}
+    <title>{{page.title}}</title> {#- -#}
+    <link rel="stylesheet" type="text/css" {# -#}
+          href="{{static_root_path | safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
+    <link rel="stylesheet" type="text/css" {# -#}
+          href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
+          id="mainThemeStyle"> {#- -#}
+    {{- style_files | safe -}}
+    <script id="default-settings" {# -#}
+      {% for k, v in layout.default_settings %}
+        data-{{k}}="{{v}}"
+      {%- endfor -%}
+    ></script> {#- -#}
+    <script src="{{static_root_path | safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
+    <script src="{{page.root_path | safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
+    <noscript> {#- -#}
+        <link rel="stylesheet" {# -#}
+           href="{{static_root_path | safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
+    </noscript> {#- -#}
+    {%- if layout.css_file_extension -%}
+        <link rel="stylesheet" type="text/css" {# -#}
+            href="{{static_root_path | safe}}theme{{page.resource_suffix}}.css"> {#- -#}
+    {%- endif -%}
+    {%- if layout.favicon -%}
+        <link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
+    {%- else -%}
+        <link rel="icon" type="image/svg+xml" {# -#}
+            href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
+        <link rel="alternate icon" type="image/png" {# -#}
+            href="{{static_root_path | safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
+        <link rel="alternate icon" type="image/png" {# -#}
+            href="{{static_root_path | safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
+    {%- endif -%}
+    {{- layout.external_html.in_header | safe -}}
+    <style type="text/css"> {#- -#}
+    #crate-search{ {#- -#}
+        background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
+    } {#- -#}
+    </style> {#- -#}
+</head> {#- -#}
+<body class="rustdoc {{page.css_class}}"> {#- -#}
+    <!--[if lte IE 11]> {#- -#}
+    <div class="warning"> {#- -#}
+        This old browser is unsupported and will most likely display funky things. {#- -#}
+    </div> {#- -#}
+    <![endif]--> {#- -#}
+    {{- layout.external_html.before_content | safe -}}
+    <nav class="sidebar"> {#- -#}
+        <div class="sidebar-menu" role="button">&#9776;</div> {#- -#}
+        <a href='{{page.root_path | safe}}{{krate_with_trailing_slash | safe}}index.html'> {#- -#}
+            <div class='logo-container rust-logo'> {#- -#}
+            <img src='
+                {%- if layout.logo -%}
+                {{layout.logo}}
+                {%- else -%}
+                {{static_root_path | safe}}rust-logo{{page.resource_suffix}}.png
+                {%- endif -%}
+                ' alt='logo'> {#- -#}
+            </div> {#- -#}
+        </a> {#- -#}
+        {{- sidebar | safe -}}
+    </nav> {#- -#}
+    <div class="theme-picker"> {#- -#}
+        <button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"> {#- -#}
+            <img width="18" height="18" alt="Pick another theme!" {# -#}
+             src="{{static_root_path | safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
+        </button> {#- -#}
+        <div id="theme-choices" role="menu"></div> {#- -#}
+    </div> {#- -#}
+    <nav class="sub"> {#- -#}
+        <form class="search-form"> {#- -#}
+            <div class="search-container"> {#- -#}
+                <div>{%- if layout.generate_search_filter -%}
+                    <select id="crate-search"> {#- -#}
+                        <option value="All crates">All crates</option> {#- -#}
+                    </select> {#- -#}
+                    {%- endif -%}
+                    <input {# -#}
+                        class="search-input"{# -#}
+                        name="search" {# -#}
+                        disabled {# -#}
+                        autocomplete="off" {# -#}
+                        spellcheck="false" {# -#}
+                        placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
+                        type="search"> {#- -#}
+                </div> {#- -#}
+                <button type="button" id="help-button" title="help">?</button> {#- -#}
+                <a id="settings-menu" href="{{page.root_path | safe}}settings.html" title="settings"> {#- -#}
+                    <img width="18" height="18" alt="Change settings" {# -#}
+                         src="{{static_root_path | safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
+                </a> {#- -#}
+            </div> {#- -#}
+        </form> {#- -#}
+    </nav> {#- -#}
+    <section id="main" class="content">{{- content | safe -}}</section> {#- -#}
+    <section id="search" class="content hidden"></section> {#- -#}
+    {{- layout.external_html.after_content | safe -}}
+    <div id="rustdoc-vars" {# -#}
+         data-root-path="{{page.root_path | safe}}" {# -#}
+         data-current-crate="{{layout.krate}}" {# -#}
+         data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#}
+         data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
+    </div>
+    <script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
+    {%- for script in page.static_extra_scripts -%}
+    <script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
+    {% endfor %}
+    {%- for script in page.extra_scripts -%}
+    <script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
+    {% endfor %}
+</body> {#- -#}
+</html> {#- -#}
index d014ed60eb039e737b36b93ed819e25b0b235425..27deb2c989c8bde5f0ccc7a5864d45d1615d5c26 100644 (file)
@@ -1,3 +1,3 @@
 goto: file://|DOC_PATH|/test_docs/index.html
 click: ".srclink"
-assert: (".line-numbers", 1)
+assert-count: (".line-numbers", 1)
index d64ee0261370c9bc327c8c315c8e5df25858f7fb..94e3fe79c945180e779422dfc42e01aae7ebcb48 100644 (file)
@@ -2,8 +2,8 @@ goto: file://|DOC_PATH|/test_docs/index.html
 goto: ./fn.check_list_code_block.html
 // If the codeblock is the first element of the docblock, the information tooltip must have
 // have some top margin to avoid going over the toggle (the "[+]").
-assert: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
+assert-css: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
 // Checks that the other codeblocks don't have this top margin.
-assert: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
-assert: ("ol > li > .information > .ignore", { "margin-top": "0px" })
-assert: (".docblock > .information > .ignore", { "margin-top": "0px" })
+assert-css: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
+assert-css: ("ol > li > .information > .ignore", { "margin-top": "0px" })
+assert-css: (".docblock > .information > .ignore", { "margin-top": "0px" })
index 7e7003d4340a3ef281913cdea9563417219b54ca..00326e9bbc4ccfd5d8cae0ea5182ba5958cf1fc1 100644 (file)
@@ -3,4 +3,4 @@ click: ".srclink"
 click: "#sidebar-toggle"
 wait-for: 500
 fail: true
-assert: ("#source-sidebar", { "left": "-300px" })
+assert-css: ("#source-sidebar", { "left": "-300px" })
index ec034f52c972c07be40e7b0f4159da6930242fd3..a81bd9a4c03904882405dfd0c312e8f1e164e996 100644 (file)
@@ -2,25 +2,25 @@ goto: file://|DOC_PATH|/test_docs/index.html
 // First, we check that the search results are hidden when the Escape key is pressed.
 write: (".search-input", "test")
 wait-for: "#search > h1" // The search element is empty before the first search 
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
 press-key: "Escape"
-assert: ("#search", "class", "content hidden")
-assert: ("#main", "class", "content")
+assert-attr: ("#search", {"class": "content hidden"})
+assert-attr: ("#main", {"class": "content"})
 
 // Check that focusing the search input brings back the search results
 focus: ".search-input"
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
 
 // Now let's check that when the help popup is displayed and we press Escape, it doesn't
 // hide the search results too.
 click: "#help-button"
-assert: ("#help", "class", "")
+assert-attr: ("#help", {"class": ""})
 press-key: "Escape"
-assert: ("#help", "class", "hidden")
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#help", {"class": "hidden"})
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
 
 // Check that Escape hides the search results when a search result is focused.
 focus: ".search-input"
@@ -29,6 +29,6 @@ press-key: "ArrowDown"
 assert-false: ".search-input:focus"
 assert: "#results a:focus"
 press-key: "Escape"
-assert: ("#help", "class", "hidden")
-assert: ("#search", "class", "content hidden")
-assert: ("#main", "class", "content")
+assert-attr: ("#help", {"class": "hidden"})
+assert-attr: ("#search", {"class": "content hidden"})
+assert-attr: ("#main", {"class": "content"})
index d8ad6c2e3f5be5ce41ab859c6b20e6229a143118..806181121033035dee597a2751bff0a9fe2da915 100644 (file)
@@ -1,7 +1,7 @@
 goto: file://|DOC_PATH|/lib2/struct.Foo.html
 // This test checks that the font weight is correctly applied.
-assert: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
-assert: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
-assert: ("#method\.a_method > code", {"font-weight": "600"})
-assert: ("#associatedtype\.X > code", {"font-weight": "600"})
-assert: ("#associatedconstant\.Y > code", {"font-weight": "600"})
+assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("#method\.a_method > code", {"font-weight": "600"})
+assert-css: ("#associatedtype\.X > code", {"font-weight": "600"})
+assert-css: ("#associatedconstant\.Y > code", {"font-weight": "600"})
index d5f9d4fc58b8c3e76fbed31eb2bc8cb34edc5a9b..62c1f200123460b7493fd7fb544b2ba232d0f495 100644 (file)
@@ -1,15 +1,15 @@
 // This test ensures that the element corresponding to the hash is displayed.
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
 // In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
-assert: ("#blanket-implementations-list > details:nth-child(2)", "open", "")
+assert-attr: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
 // We first check that the impl block is open by default.
-assert: ("#implementations + details", "open", "")
+assert-attr: ("#implementations + details", {"open": ""})
 // We collapse it.
 click: "#implementations + details > summary"
 // We check that it was collapsed as expected.
-assert-false: ("#implementations + details", "open", "")
+assert-attr-false: ("#implementations + details", {"open": ""})
 // To ensure that we will click on the currently hidden method.
-assert: (".sidebar-links > a", "must_use")
+assert-text: (".sidebar-links > a", "must_use")
 click: ".sidebar-links > a"
 // We check that the impl block was opened as expected so that we can see the method.
-assert: ("#implementations + details", "open", "")
+assert-attr: ("#implementations + details", {"open": ""})
index 3f1e7ec4a789c17db69cd05b2a84b6cfa6f5e6da..266b66d586fe0685f49e974d24ed2afdef57398a 100644 (file)
@@ -1,3 +1,3 @@
 // This test ensures that the impl blocks are open by default.
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert: ("#main > details.implementors-toggle", "open", "")
+assert-attr: ("#main > details.implementors-toggle", {"open": ""})
index 25a015121592c3c0b003d560f3e5126c56c5d32b..6ed62006151a216fad74811d036f436e530f2efc 100644 (file)
@@ -10,5 +10,5 @@ write: (".search-input", "thisisanalias")
 // Waiting for the search results to appear...
 wait-for: "#titles"
 // Checking that the colors for the alias element are the ones expected.
-assert: (".result-name > .alias", {"color": "rgb(255, 255, 255)"})
-assert: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"})
+assert-css: (".result-name > .alias", {"color": "rgb(255, 255, 255)"})
+assert-css: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"})
index a50d03cf4891248c607b3a906426b08a3195e525..d8cb6ee5731b9724060bb8cfeb52a64a03b2d4b7 100644 (file)
@@ -2,4 +2,4 @@
 goto: file://|DOC_PATH|/test_docs/index.html?search=some_more_function
 // Waiting for the search results to appear...
 wait-for: "#titles"
-assert: (".search-results .desc code", "format!")
+assert-text: (".search-results .desc code", "format!")
index 96d15c624f115e771b10dd6cd568b19ca795a1f0..ea94e5640fbd1bcb5ccbe09ee28ea00318440f0b 100644 (file)
@@ -5,8 +5,8 @@ write: (".search-input", "test")
 wait-for: "#titles"
 // The width is returned by "getComputedStyle" which returns the exact number instead of the
 // CSS rule which is "50%"...
-assert: (".search-results div.desc", {"width": "320px"})
+assert-css: (".search-results div.desc", {"width": "320px"})
 size: (600, 100)
 // As counter-intuitive as it may seem, in this width, the width is "100%", which is why
 // when computed it's larger.
-assert: (".search-results div.desc", {"width": "570px"})
+assert-css: (".search-results div.desc", {"width": "570px"})
index e7612d663717ad41cb2f335ad39d75cb01633afa..5342d431d992f3ebcdf7fb66feae780417cee66b 100644 (file)
@@ -6,5 +6,5 @@ wait-for: "#titles"
 // less good.
 //
 // Checking that the CSS is displaying " (keyword)" in italic.
-assert: (".result-name span.keyword > i", "(keyword)")
-assert: (".result-name span.keyword", "CookieMonster (keyword)")
+assert-text: (".result-name span.keyword > i", "(keyword)")
+assert-text: (".result-name span.keyword", "CookieMonster (keyword)")
index c828c72e910d592e104e7a1c4b408dbde90f4114..88a0b340415b2b8259bfc9c474db2704dbb02f78 100644 (file)
@@ -2,7 +2,7 @@ goto: file://|DOC_PATH|/test_docs/index.html
 write: (".search-input", "Foo")
 // Waiting for the search results to appear...
 wait-for: "#titles"
-assert: ("#titles > button:nth-of-type(1)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(1)", {"class": "selected"})
 
 // To go back to the original "state"
 goto: file://|DOC_PATH|/test_docs/index.html
@@ -10,7 +10,7 @@ write: (".search-input", "-> String")
 // Waiting for the search results to appear...
 wait-for: "#titles"
 // With this search, only the last tab shouldn't be empty so it should be selected.
-assert: ("#titles > button:nth-of-type(3)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(3)", {"class": "selected"})
 
 // To go back to the original "state"
 goto: file://|DOC_PATH|/test_docs/index.html
@@ -18,4 +18,4 @@ write: (".search-input", "-> Something")
 // Waiting for the search results to appear...
 wait-for: "#titles"
 // With this search, all the tabs are empty so the first one should remain selected.
-assert: ("#titles > button:nth-of-type(1)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(1)", {"class": "selected"})
index 884c38d85fbdba6bf6a6f829332d2cfbd039d386..42d945d0eb81700a5c9d09771cc637ff3454ced6 100644 (file)
@@ -8,19 +8,19 @@ press-key: "Escape"
 assert-false: "input.search-input:focus"
 // We now check for the help popup.
 press-key: "?"
-assert: ("#help", {"display": "flex"})
+assert-css: ("#help", {"display": "flex"})
 assert-false: "#help.hidden"
 press-key: "Escape"
-assert: ("#help.hidden", {"display": "none"})
+assert-css: ("#help.hidden", {"display": "none"})
 // Check for the themes list.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
 press-key: "t"
-assert: ("#theme-choices", {"display": "block"})
+assert-css: ("#theme-choices", {"display": "block"})
 press-key: "t"
 // We ensure that 't' hides back the menu.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
 press-key: "t"
-assert: ("#theme-choices", {"display": "block"})
+assert-css: ("#theme-choices", {"display": "block"})
 press-key: "Escape"
 // We ensure that 'Escape' hides the menu too.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
index e0e6d19cace36608c0100298ae5c2a98986bfca7..4f6b3aded18163f61be573c1b1cee5db6091665a 100644 (file)
@@ -1,23 +1,23 @@
 goto: file://|DOC_PATH|/test_docs/index.html
-assert: (".sidebar > .location", "Crate test_docs")
+assert-text: (".sidebar > .location", "Crate test_docs")
 // In modules, we only have one "location" element.
-assert: (".sidebar .location", 1)
-assert: (".sidebar-elems > #all-types", "See all test_docs's items")
+assert-count: (".sidebar .location", 1)
+assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
 // We check that we have the crates list and that the "current" on is "test_docs".
-assert: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
-assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
-assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
-assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
-assert: ("#structs + table td > a", "Foo")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
+assert-text: ("#structs + table td > a", "Foo")
 click: "#structs + table td > a"
 
 // PAGE: struct.Foo.html
-assert: (".sidebar .location", 2)
+assert-count: (".sidebar .location", 2)
 // We check that there is no crate listed outside of the top level.
 assert-false: ".sidebar-elems > .crate"
 // We now go back to the crate page to click on the "lib2" crate link.
@@ -26,35 +26,35 @@ click: ".sidebar-elems > .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
 goto: file://|DOC_PATH|/lib2/index.html
-assert: (".sidebar > .location", "Crate lib2")
+assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
-assert: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
 // We now go to the "foobar" function page.
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
-assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
-assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
-assert:        ("#functions + table td > a", "foobar")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
+assert-text: ("#functions + table td > a", "foobar")
 click: "#functions + table td > a"
 
 // PAGE: fn.foobar.html
 // In items containing no items (like functions or constants) and in modules, we have one
 // "location" elements.
-assert: (".sidebar .location", 1)
+assert-count: (".sidebar .location", 1)
 // There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
-assert: (".sidebar .sidebar-elems .location", "Other items inlib2")
+assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
 goto: ./module/index.html
-assert: (".sidebar > .location", "Module module")
+assert-text: (".sidebar > .location", "Module module")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
 goto: ./sub_module/sub_sub_module/index.html
-assert: (".sidebar > .location", "Module sub_sub_module")
+assert-text: (".sidebar > .location", "Module sub_sub_module")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
-assert: ("#functions + table td > a", "foo")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-text: ("#functions + table td > a", "foo")
index ff33a541a1801642dd1164f84d2623e58c16a611..20396e268958a9c39806f5be860c5d9eaadccfb8 100644 (file)
@@ -3,11 +3,11 @@ goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
 click: (40, 224) // This is the position of the span for line 4.
 // Unfortunately, "#4" isn't a valid query selector, so we have to go around that limitation
 // by instead getting the nth span.
-assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted")
+assert-attr: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
 // We now check that the good spans are highlighted
 goto: file://|DOC_PATH|/src/test_docs/lib.rs.html#4-6
-assert-false: (".line-numbers > span:nth-child(3)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(5)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(6)", "class", "line-highlighted")
-assert-false: (".line-numbers > span:nth-child(7)", "class", "line-highlighted")
+assert-attr-false: (".line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
+assert-attr-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
index bc9063edd1e7a460b3d0d6d615395e0627457b41..5221cda2f1fb6bb96f7a699e508646ae053dea0a 100644 (file)
@@ -3,8 +3,8 @@ click: "#theme-picker"
 click: "#theme-choices > button:first-child"
 wait-for: 500
 // should be the ayu theme so let's check the color
-assert: ("body", { "background-color": "rgb(15, 20, 25)" })
+assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
 click: "#theme-choices > button:last-child"
 wait-for: 500
 // should be the light theme so let's check the color
-assert: ("body", { "background-color": "rgb(255, 255, 255)" })
+assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
index fcdfc0344db809db9fb41e38a45642e6b639a763..9ec91aba881cbe34dc2445b8418d7075b11e9112 100644 (file)
@@ -1,21 +1,21 @@
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 size: (433, 600)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
 click: (4, 280) // This is the position of the top doc comment toggle
-assert-false: (".top-doc", "open", "")
+assert-attr-false: (".top-doc", {"open": ""})
 click: (4, 280)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
 // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
 click: (3, 280)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
 
 // Now we do the same but with a little bigger width
 size: (600, 600)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
 click: (4, 240) // New Y position since all search elements are back on one line.
-assert-false: (".top-doc", "open", "")
+assert-attr-false: (".top-doc", {"open": ""})
 click: (4, 240)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
 // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
 click: (3, 240)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
index 062bc7d51e54263993f9cda0068d24c200b93f38..601998b7bd28ac26dc9b2f5a5a8eb84da4e67d52 100644 (file)
@@ -1,10 +1,10 @@
 goto: file://|DOC_PATH|/test_docs/index.html
-assert: ("#main > details.top-doc", "open", "")
+assert-attr: ("#main > details.top-doc", {"open": ""})
 click: "#toggle-all-docs"
 wait-for: 1000
 // This is now collapsed so there shouldn't be the "open" attribute on details.
-assert-false: ("#main > details.top-doc", "open", "")
+assert-attr-false: ("#main > details.top-doc", {"open": ""})
 click: "#toggle-all-docs"
 wait-for: 1000
 // Not collapsed anymore so the "open" attribute should be back.
-assert: ("#main > details.top-doc", "open", "")
+assert-attr: ("#main > details.top-doc", {"open": ""})
index 96a5492edefcbf745a4e44e8bdcd3763afaa52cf..d8615c207b2faef043c4cdae3946fd7875afc8ee 100644 (file)
@@ -2,4 +2,4 @@
 // has all the implementations toggled open by default, so users can
 // find method names in those implementations with Ctrl-F.
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert: (".rustdoc-toggle.implementors-toggle", "open", "")
+assert-attr: (".rustdoc-toggle.implementors-toggle", {"open": ""})
index 2e9f85336ecd8f4960a3098501d74318db23f2c6..739745792c2a193ab08d053b506335b38299e343 100644 (file)
@@ -1,7 +1,7 @@
 goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
-assert: (".sidebar-links a:nth-of-type(1)", "another")
-assert: (".sidebar-links a:nth-of-type(2)", "func1")
-assert: (".sidebar-links a:nth-of-type(3)", "func2")
-assert: (".sidebar-links a:nth-of-type(4)", "func3")
-assert: (".sidebar-links a:nth-of-type(5)", "hello")
-assert: (".sidebar-links a:nth-of-type(6)", "why_not")
+assert-text: (".sidebar-links a:nth-of-type(1)", "another")
+assert-text: (".sidebar-links a:nth-of-type(2)", "func1")
+assert-text: (".sidebar-links a:nth-of-type(3)", "func2")
+assert-text: (".sidebar-links a:nth-of-type(4)", "func3")
+assert-text: (".sidebar-links a:nth-of-type(5)", "hello")
+assert-text: (".sidebar-links a:nth-of-type(6)", "why_not")
diff --git a/src/test/rustdoc/recursive-deref-sidebar.rs b/src/test/rustdoc/recursive-deref-sidebar.rs
new file mode 100644 (file)
index 0000000..fcb636a
--- /dev/null
@@ -0,0 +1,22 @@
+use std::ops::Deref;
+
+pub struct A {}
+impl A { pub fn foo_a(&self) {} }
+
+pub struct B {}
+impl B { pub fn foo_b(&self) {} }
+
+pub struct C {}
+impl C { pub fn foo_c(&self) {} }
+
+// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b'
+impl Deref for A {
+    type Target = B;
+    fn deref(&self) -> &B { todo!() }
+}
+
+// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
+impl Deref for B {
+    type Target = C;
+    fn deref(&self) -> &C { todo!() }
+}
diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs
new file mode 100644 (file)
index 0000000..91db011
--- /dev/null
@@ -0,0 +1,22 @@
+use std::ops::Deref;
+
+pub struct A;
+pub struct B;
+
+// @has recursive_deref/struct.A.html '//code' 'impl Deref for A'
+impl Deref for A {
+    type Target = B;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
+
+// @has recursive_deref/struct.B.html '//code' 'impl Deref for B'
+impl Deref for B {
+    type Target = A;
+
+    fn deref(&self) -> &Self::Target {
+        panic!()
+    }
+}
index 8b27d055e2be317ab50152db891513450c76c569..4134c62377835003796144bce8079c00204c7a7a 100644 (file)
@@ -17,7 +17,7 @@ impl Drop for Foo {
 
 fn foo() {
     let x: &[_] = &[Foo, Foo];
-    &x[3..4];
+    let _ = &x[3..4];
 }
 
 fn main() {
index 2ee564cadb3442d1d5e2f3e1940a29002303519f..2f7178fb3e1326a74816db0af2142288a289d733 100644 (file)
@@ -21,7 +21,7 @@ fn bar() -> usize {
 
 fn foo() {
     let x: &[_] = &[Foo, Foo];
-    &x[3..bar()];
+    let _ = &x[3..bar()];
 }
 
 fn main() {
index 14e1ddf52eb7b4f28b2f8db93cb22fc0a8697c3c..a514e20277365e43e798ff7553fef84adcc1ebd1 100644 (file)
@@ -67,14 +67,14 @@ fn index_mut(&mut self, _index: RangeFull) -> &mut Foo {
 
 fn main() {
     let mut x = Foo;
-    &x[..];
-    &x[Foo..];
-    &x[..Foo];
-    &x[Foo..Foo];
-    &mut x[..];
-    &mut x[Foo..];
-    &mut x[..Foo];
-    &mut x[Foo..Foo];
+    let _ = &x[..];
+    let _ = &x[Foo..];
+    let _ = &x[..Foo];
+    let _ = &x[Foo..Foo];
+    let _ = &mut x[..];
+    let _ = &mut x[Foo..];
+    let _ = &mut x[..Foo];
+    let _ = &mut x[Foo..Foo];
     unsafe {
         assert_eq!(COUNT, 8);
     }
index 0e228126d77896c9f2359c05383c2019557184a9..97ab07daccefb94843eac8d33c3ebd3dceca98ad 100644 (file)
@@ -6,9 +6,9 @@ fn promote<const N: i32>() {
     // works:
     //
     // let n = N;
-    // &n;
+    // let _ = &n;
 
-    &N;
+    let _ = &N;
 }
 
 fn main() {
index 45c429c7eb0d50831381a5e4312707e2ae2c2a9c..610531c7b4c9e8fad03dcd8703b3fbe66565b542 100644 (file)
@@ -5,9 +5,8 @@
 // Make sure we error with the right kind of error on a too large slice.
 const TEST: () = { unsafe {
     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
-    let _val = &*slice; //~ ERROR: any use of this value will cause an error
+    let _val = &*slice; //~ ERROR: evaluation of constant value failed
     //~| slice is bigger than largest supported object
-    //~| WARN this was previously accepted by the compiler but is being phased out
 } };
 
 fn main() {}
index 224fbb62a46492d89d1d376e69b4e5e450fc26b3..5665a9c3e05239c853efb8059e19c40a4d189f60 100644 (file)
@@ -1,18 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/dangling.rs:8:16
    |
-LL | / const TEST: () = { unsafe {
-LL | |     let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
-LL | |     let _val = &*slice;
-   | |                ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
-LL | |
-LL | |
-LL | | } };
-   | |____-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     let _val = &*slice;
+   |                ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index 43d79badd72826e8d177523e8b285af8ef7c5f45..4df541eeeb4e9ae14e6da37f044e831a73db56ee 100644 (file)
@@ -8,8 +8,7 @@
 const fn foo() -> i32 {
     unsafe {
         let _ = intrinsics::const_allocate(4, 3) as * mut i32;
-        //~^ error: any use of this value will cause an error [const_err]
-        //~| WARN this was previously accepted by the compiler but is being phased out
+        //~^ error: evaluation of constant value failed
     }
     1
 
index 3d529ab4ca6e599aa04bcc50b884376a76a1c813..327e2911205a3f465aa5d407b612893d2a84585e 100644 (file)
@@ -1,19 +1,15 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/alloc_intrinsic_errors.rs:10:17
    |
 LL | const FOO: i32 = foo();
-   | -----------------------
+   |                  ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
 ...
 LL |         let _ = intrinsics::const_allocate(4, 3) as * mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                 |
    |                 align has to be a power of 2, `3` is not a power of 2
    |                 inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17
-   |                 inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index f2d9758b8dc08cee390edb4d8483e8c0824508ff..baa1848e9c31ac264ca8595c41b81b58e4a36c03 100644 (file)
@@ -17,8 +17,7 @@ const fn wat(x: u64) -> &'static u64 {
     unsafe { transmute(&x) }
 }
 const X: u64 = *wat(42);
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
     println!("{}", X);
index 0389471edb57ce84efaf6d9ec01d879c2a99394d..49ec9eb047be441413a62dc0154abb96d95706aa 100644 (file)
@@ -1,14 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/issue-49296.rs:19:16
    |
 LL | const X: u64 = *wat(42);
-   | ---------------^^^^^^^^-
-   |                |
-   |                pointer to alloc1 was dereferenced after this allocation got freed
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                ^^^^^^^^ pointer to alloc1 was dereferenced after this allocation got freed
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index 941f08bfd8d5a04222f0e6aef662773f647dd990..ffde14f894e65ab2b5fae9c4939c0b0e1efbe66d 100644 (file)
@@ -1,30 +1,17 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:19:14
    |
-LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: alignment `1000` is not a power of 2
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
 
-error: any use of this value will cause an error
-  --> $DIR/ub-incorrect-vtable.rs:25:14
-   |
-LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: size is bigger than largest supported object
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:36:1
+  --> $DIR/ub-incorrect-vtable.rs:34:1
    |
 LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
 LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
@@ -36,7 +23,7 @@ LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:41:1
+  --> $DIR/ub-incorrect-vtable.rs:39:1
    |
 LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
 LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
index ceed6f8268d6dde3d39a78bd31c0122f0bb821d9..2ad164a8c35f759c6fd6ddf2ae3c8d6b2c5eea9f 100644 (file)
@@ -1,30 +1,17 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-incorrect-vtable.rs:19:14
    |
-LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: alignment `1000` is not a power of 2
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
 
-error: any use of this value will cause an error
-  --> $DIR/ub-incorrect-vtable.rs:25:14
-   |
-LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
-LL | |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-   | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
-   |                |
-   |                invalid vtable: size is bigger than largest supported object
+error[E0080]: evaluation of constant value failed
+  --> $DIR/ub-incorrect-vtable.rs:24:14
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:36:1
+  --> $DIR/ub-incorrect-vtable.rs:34:1
    |
 LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
 LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
@@ -36,7 +23,7 @@ LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1us
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-incorrect-vtable.rs:41:1
+  --> $DIR/ub-incorrect-vtable.rs:39:1
    |
 LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
 LL | |     unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
index 7c514e804e01ab1b92f82549d17e32d8a36f0a28..4ec853576c91bd4b7a202f230c370f9db0662e9d 100644 (file)
@@ -17,14 +17,12 @@ trait Trait {}
 
 const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
 //~| invalid vtable: alignment `1000` is not a power of 2
 
 const INVALID_VTABLE_SIZE: &dyn Trait =
     unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
 //~| invalid vtable: size is bigger than largest supported object
 
 #[repr(transparent)]
index b68b9d6a180e8b8aa7a368e2f46a56a491428b9b..9d3b88e803ebd43d82bb34e0fe5763710b5acef9 100644 (file)
@@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
                00 00 00 00                                     │ ....
            }
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-nonnull.rs:19:30
    |
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | |     mem::transmute(out_of_bounds_ptr)
-LL | | } };
-   | |____-
-   |
-note: the lint level is defined here
-  --> $DIR/ub-nonnull.rs:15:8
-   |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
-   |        ^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     let out_of_bounds_ptr = &ptr[255];
+   |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:24:1
+  --> $DIR/ub-nonnull.rs:23:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:26:1
+  --> $DIR/ub-nonnull.rs:25:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -53,7 +38,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:34:1
+  --> $DIR/ub-nonnull.rs:33:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
@@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:42:1
+  --> $DIR/ub-nonnull.rs:41:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:48:1
+  --> $DIR/ub-nonnull.rs:47:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
index 687d96a183179fd0c862e699a3a4ddde05954505..bc230374ebf84bd810697a0d1be46fe63c48d270 100644 (file)
@@ -9,29 +9,14 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
                00 00 00 00 00 00 00 00                         │ ........
            }
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ub-nonnull.rs:19:30
    |
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | |     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | |     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | |     let out_of_bounds_ptr = &ptr[255];
-   | |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | |     mem::transmute(out_of_bounds_ptr)
-LL | | } };
-   | |____-
-   |
-note: the lint level is defined here
-  --> $DIR/ub-nonnull.rs:15:8
-   |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
-   |        ^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     let out_of_bounds_ptr = &ptr[255];
+   |                              ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:24:1
+  --> $DIR/ub-nonnull.rs:23:1
    |
 LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -42,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:26:1
+  --> $DIR/ub-nonnull.rs:25:1
    |
 LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
@@ -53,7 +38,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:34:1
+  --> $DIR/ub-nonnull.rs:33:1
    |
 LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
@@ -64,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:42:1
+  --> $DIR/ub-nonnull.rs:41:1
    |
 LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
@@ -75,7 +60,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
            }
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/ub-nonnull.rs:48:1
+  --> $DIR/ub-nonnull.rs:47:1
    |
 LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
index 75c02a8da194fdc2904dbcdca00a620a633a31a4..259707b8028da33ed0b6288655850180741b233a 100644 (file)
@@ -16,8 +16,7 @@
 const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
     let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
     // Use address-of-element for pointer arithmetic. This could wrap around to null!
-    let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error
-    //~| WARN this was previously accepted by the compiler but is being phased out
+    let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed
     mem::transmute(out_of_bounds_ptr)
 } };
 
index ae9b9bfd2811c7fc1ab03bada9fd9b92cc357598..0022d19e95395d734da46f03810340a10f2cfefc 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:5:14
    |
 LL |     unsafe { std::mem::transmute(()) }
@@ -6,21 +6,12 @@ LL |     unsafe { std::mem::transmute(()) }
    |              |
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
-   |              inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
-   | -----------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/validate_uninhabited_zsts.rs:14:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:18:1
+  --> $DIR/validate_uninhabited_zsts.rs:17:1
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
@@ -41,7 +32,7 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: the `!` type has no valid value
 
 warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:18:35
+  --> $DIR/validate_uninhabited_zsts.rs:17:35
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |
    = note: enums with no variants have no valid value
 
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
index ae9b9bfd2811c7fc1ab03bada9fd9b92cc357598..0022d19e95395d734da46f03810340a10f2cfefc 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:5:14
    |
 LL |     unsafe { std::mem::transmute(()) }
@@ -6,21 +6,12 @@ LL |     unsafe { std::mem::transmute(()) }
    |              |
    |              transmuting to uninhabited type
    |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
-   |              inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
 ...
 LL | const FOO: [Empty; 3] = [foo(); 3];
-   | -----------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/validate_uninhabited_zsts.rs:14:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                          ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/validate_uninhabited_zsts.rs:18:1
+  --> $DIR/validate_uninhabited_zsts.rs:17:1
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
@@ -41,7 +32,7 @@ LL |     unsafe { std::mem::transmute(()) }
    = note: the `!` type has no valid value
 
 warning: the type `Empty` does not permit zero-initialization
-  --> $DIR/validate_uninhabited_zsts.rs:18:35
+  --> $DIR/validate_uninhabited_zsts.rs:17:35
    |
 LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^
@@ -51,6 +42,6 @@ LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |
    = note: enums with no variants have no valid value
 
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
index 112ace5e97fe691857dfe3ab12108b29593fdf47..f6b6a1f53eb9f2c54dc1f23aad21e22b0cae6cda 100644 (file)
@@ -3,9 +3,8 @@
 
 const fn foo() -> ! {
     unsafe { std::mem::transmute(()) }
-    //~^ WARN any use of this value will cause an error [const_err]
+    //~^ ERROR evaluation of constant value failed
     //~| WARN the type `!` does not permit zero-initialization [invalid_value]
-    //~| WARN this was previously accepted by the compiler but is being phased out
 }
 
 #[derive(Clone, Copy)]
index 2ccc5d27bbb781f5fc5138dc79a25e76c60bcaeb..902a668488b8773d0754c1e6efdc2324f86631eb 100644 (file)
 // unsigned types:
 
 const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // signed types:
 
 const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and make sure we capture y < 0:
 
 const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and that there's no special relation to the value -1 by picking some
 // negative values at random:
 
 const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // Repeat it all over for `unchecked_shr`
 
 // unsigned types:
 
 const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // signed types:
 
 const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and make sure we capture y < 0:
 
 const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // and that there's no special relation to the value -1 by picking some
 // negative values at random:
 
 const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // Other arithmetic functions:
 
 const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 // capture fault with zero value
 
 const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
 
 fn main() {}
index 999b26543e2d51041141ecb42ad24186ba38c703..22e8c8dabc970a139b63d58e2fa635411e03b009 100644 (file)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/const-int-unchecked.rs:15:29
    |
 LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shl`
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:18:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:17:31
    |
 LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:21:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:19:31
    |
 LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:24:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:21:31
    |
 LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:27:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:23:33
    |
 LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:33:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:28:29
    |
 LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:36:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:30:31
    |
 LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:39:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:32:31
    |
 LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:42:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:34:31
    |
 LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:45:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:36:33
    |
 LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:51:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:41:33
    |
 LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 255 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:54:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:43:35
    |
 LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 65535 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:57:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:45:35
    |
 LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 4294967295 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:60:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:47:35
    |
 LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 18446744073709551615 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:63:37
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:49:37
    |
 LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                     |
-   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:70:40
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:55:40
    |
 LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                        |
-   |                                        overflowing shift by 250 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:73:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:57:42
    |
 LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 65523 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:76:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:59:42
    |
 LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 4294967271 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:79:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:61:42
    |
 LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 18446744073709551586 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:82:44
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:63:44
    |
 LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                            |
-   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:90:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:70:29
    |
 LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:93:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:72:31
    |
 LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:96:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:74:31
    |
 LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:99:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:76:31
    |
 LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:102:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:78:33
    |
 LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:108:29
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:83:29
    |
 LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
-   | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                             |
-   |                             overflowing shift by 8 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:111:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:85:31
    |
 LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 16 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:114:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:87:31
    |
 LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 32 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:117:31
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:89:31
    |
 LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
-   | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                               |
-   |                               overflowing shift by 64 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:120:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:91:33
    |
 LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 128 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:126:33
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:96:33
    |
 LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-   | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                 |
-   |                                 overflowing shift by 255 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:129:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:98:35
    |
 LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 65535 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:132:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:100:35
    |
 LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 4294967295 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:135:35
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:102:35
    |
 LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-   | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                   |
-   |                                   overflowing shift by 18446744073709551615 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:138:37
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:104:37
    |
 LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-   | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                     |
-   |                                     overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:145:40
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:110:40
    |
 LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-   | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                        |
-   |                                        overflowing shift by 250 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:148:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:112:42
    |
 LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 65523 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:151:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:114:42
    |
 LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 4294967271 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:154:42
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:116:42
    |
 LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-   | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                          |
-   |                                          overflowing shift by 18446744073709551586 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:157:44
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:118:44
    |
 LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-   | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                                            |
-   |                                            overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:163:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:123:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_add`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:167:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:126:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_sub`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:171:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:129:25
    |
 LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_mul`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:175:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:132:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         dividing by zero
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dividing by zero
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:178:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:134:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_div`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_div`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:182:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:137:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         calculating the remainder with a divisor of zero
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calculating the remainder with a divisor of zero
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:185:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:139:25
    |
 LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         overflow executing `unchecked_rem`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_rem`
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:191:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:144:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         `ctlz_nonzero` called on 0
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ctlz_nonzero` called on 0
 
-error: any use of this value will cause an error
-  --> $DIR/const-int-unchecked.rs:194:25
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-int-unchecked.rs:146:25
    |
 LL | const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
-   |                         |
-   |                         `cttz_nonzero` called on 0
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `cttz_nonzero` called on 0
 
 error: aborting due to 49 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 4ae3a88c45143a9ec2018a0df9e81ff37d8d564d..8cee5b506513623094dc9717d12b5beceb21bcde 100644 (file)
@@ -1,5 +1,4 @@
-// build-fail
-
+// error-pattern: evaluation of constant value failed
 #![feature(const_unreachable_unchecked)]
 
 const unsafe fn foo(x: bool) -> bool {
@@ -9,12 +8,8 @@
     }
 }
 
-#[warn(const_err)]
 const BAR: bool = unsafe { foo(false) };
 
 fn main() {
   assert_eq!(BAR, true);
-  //~^ ERROR E0080
-  //~| ERROR erroneous constant
-  //~| WARN this was previously accepted by the compiler but is being phased out
 }
index fc7a53e2774866e9933c182254084b7783296b3a..ecdd0ca3f54c1bf995b840caf38afa1c3d50d99a 100644 (file)
@@ -1,4 +1,4 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
 LL |     unsafe { intrinsics::unreachable() }
@@ -6,39 +6,15 @@ LL |     unsafe { intrinsics::unreachable() }
    |              |
    |              entering unreachable code
    |              inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
-   |              inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:8:18
-   |              inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:13:28
    | 
-  ::: $DIR/const_unsafe_unreachable_ub.rs:13:1
+  ::: $DIR/const_unsafe_unreachable_ub.rs:7:18
    |
+LL |         false => std::hint::unreachable_unchecked(),
+   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18
+...
 LL | const BAR: bool = unsafe { foo(false) };
-   | ----------------------------------------
-   |
-note: the lint level is defined here
-  --> $DIR/const_unsafe_unreachable_ub.rs:12:8
-   |
-LL | #[warn(const_err)]
-   |        ^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error[E0080]: evaluation of constant value failed
-  --> $DIR/const_unsafe_unreachable_ub.rs:16:14
-   |
-LL |   assert_eq!(BAR, true);
-   |              ^^^ referenced constant has errors
-
-error: erroneous constant used
-  --> $DIR/const_unsafe_unreachable_ub.rs:16:3
-   |
-LL |   assert_eq!(BAR, true);
-   |   ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28
 
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0080`.
index b73191d56a6129d840d3ede8f745f4de6ceaea05..f8fa2c5f177ea937108c948b92025ea93d1af353 100644 (file)
@@ -1,5 +1,8 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(const_ptr_offset_from)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::ptr_offset_from;
 
 #[repr(C)]
 struct Struct {
@@ -8,39 +11,38 @@ struct Struct {
 }
 
 pub const DIFFERENT_ALLOC: usize = {
-    //~^ NOTE
     let uninit = std::mem::MaybeUninit::<Struct>::uninit();
     let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
     let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
     let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
-    let offset = unsafe { field_ptr.offset_from(base_ptr) };
+    let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
+    //~| cannot compute offset of pointers into different allocations.
     offset as usize
 };
 
 pub const NOT_PTR: usize = {
-    //~^ NOTE
     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
 };
 
 pub const NOT_MULTIPLE_OF_SIZE: isize = {
-    //~^ NOTE
     let data = [5u8, 6, 7];
     let base_ptr = data.as_ptr();
     let field_ptr = &data[1] as *const u8 as *const u16;
-    unsafe { field_ptr.offset_from(base_ptr as *const u16) }
+    unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed
+    //~| 1_isize cannot be divided by 2_isize without remainder
 };
 
 pub const OFFSET_FROM_NULL: isize = {
-    //~^ NOTE
     let ptr = 0 as *const u8;
-    unsafe { ptr.offset_from(ptr) }
+    unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed
+    //~| null pointer is not a valid pointer
 };
 
 pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
-    //~^ NOTE
     let ptr1 = 8 as *const u8;
     let ptr2 = 16 as *const u8;
-    unsafe { ptr2.offset_from(ptr1) }
+    unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR any use of this value will cause an error
+    //~| WARN previously accepted
 };
 
 fn main() {}
index 4254cda2a0084c4f81f8f53b943e2584e9483cfe..4c2ba9297d84a24b2fd6098ab94200dfbe8285ab 100644 (file)
@@ -1,27 +1,8 @@
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    ptr_offset_from cannot compute offset of pointers into different allocations.
-   |                    inside `ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:16:27
-   | 
-  ::: $DIR/offset_from_ub.rs:10:1
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:18:27
    |
-LL | / pub const DIFFERENT_ALLOC: usize = {
-LL | |
-LL | |     let uninit = std::mem::MaybeUninit::<Struct>::uninit();
-LL | |     let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
-...  |
-LL | |     offset as usize
-LL | | };
-   | |__-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations.
 
 error: any use of this value will cause an error
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -31,82 +12,40 @@ LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
    |                    |
    |                    unable to turn bytes into a pointer
    |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_PTR` at $DIR/offset_from_ub.rs:22:14
+   |                    inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
    | 
-  ::: $DIR/offset_from_ub.rs:20:1
+  ::: $DIR/offset_from_ub.rs:23:1
    |
 LL | / pub const NOT_PTR: usize = {
-LL | |
 LL | |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
 LL | | };
    | |__-
    |
+   = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    exact_div: 1_isize cannot be divided by 2_isize without remainder
-   |                    inside `ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:30:14
-   | 
-  ::: $DIR/offset_from_ub.rs:25:1
-   |
-LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = {
-LL | |
-LL | |     let data = [5u8, 6, 7];
-LL | |     let base_ptr = data.as_ptr();
-LL | |     let field_ptr = &data[1] as *const u8 as *const u16;
-LL | |     unsafe { field_ptr.offset_from(base_ptr as *const u16) }
-LL | | };
-   | |__-
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:31:14
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
 
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    null pointer is not a valid pointer for this operation
-   |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:36:14
-   | 
-  ::: $DIR/offset_from_ub.rs:33:1
-   |
-LL | / pub const OFFSET_FROM_NULL: isize = {
-LL | |
-LL | |     let ptr = 0 as *const u8;
-LL | |     unsafe { ptr.offset_from(ptr) }
-LL | | };
-   | |__-
+error[E0080]: evaluation of constant value failed
+  --> $DIR/offset_from_ub.rs:37:14
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { ptr_offset_from(ptr, ptr) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation
 
 error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |
-LL |           unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                    |
-   |                    unable to turn bytes into a pointer
-   |                    inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                    inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:43:14
-   | 
-  ::: $DIR/offset_from_ub.rs:39:1
+  --> $DIR/offset_from_ub.rs:44:14
    |
 LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
-LL | |
 LL | |     let ptr1 = 8 as *const u8;
 LL | |     let ptr2 = 16 as *const u8;
-LL | |     unsafe { ptr2.offset_from(ptr1) }
+LL | |     unsafe { ptr_offset_from(ptr2, ptr1) }
+   | |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn bytes into a pointer
+LL | |
 LL | | };
    | |__-
    |
@@ -115,3 +54,4 @@ LL | | };
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 45203d3e271199b82e42e735f8d6685b51aa901e..e25bef0624de063e1055be715b2f49efc31f970f 100644 (file)
@@ -1,4 +1,4 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -6,18 +6,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `BEFORE_START` at $DIR/offset_ub.rs:6:46
    | 
-  ::: $DIR/offset_ub.rs:6:1
+  ::: $DIR/offset_ub.rs:6:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
-   | ------------------------------------------------------------------------------
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:6:46
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -25,17 +20,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `AFTER_END` at $DIR/offset_ub.rs:7:43
    | 
-  ::: $DIR/offset_ub.rs:7:1
+  ::: $DIR/offset_ub.rs:7:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
-   | --------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:7:43
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -43,17 +34,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45
    | 
-  ::: $DIR/offset_ub.rs:8:1
+  ::: $DIR/offset_ub.rs:8:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
-   | ------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -61,17 +48,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `OVERFLOW` at $DIR/offset_ub.rs:10:43
    | 
-  ::: $DIR/offset_ub.rs:10:1
+  ::: $DIR/offset_ub.rs:10:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
-   | ----------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:10:43
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -79,17 +62,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44
    | 
-  ::: $DIR/offset_ub.rs:11:1
+  ::: $DIR/offset_ub.rs:11:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
-   | -----------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -97,17 +76,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56
    | 
-  ::: $DIR/offset_ub.rs:12:1
+  ::: $DIR/offset_ub.rs:12:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
-   | ---------------------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -115,17 +90,13 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  overflowing in-bounds pointer arithmetic
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57
    | 
-  ::: $DIR/offset_ub.rs:13:1
+  ::: $DIR/offset_ub.rs:13:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
-   | --------------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -133,15 +104,11 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50
    | 
-  ::: $DIR/offset_ub.rs:15:1
+  ::: $DIR/offset_ub.rs:15:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
-   | -------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50
 
 error: any use of this value will cause an error
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
@@ -158,10 +125,11 @@ LL |         unsafe { intrinsics::offset(self, count) as *mut T }
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
    | ---------------------------------------------------------------------------------------------
    |
+   = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -169,15 +137,11 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: 0x0 is not a valid pointer
    |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50
    | 
-  ::: $DIR/offset_ub.rs:19:1
+  ::: $DIR/offset_ub.rs:19:50
    |
 LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
-   | -------------------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50
 
 error: any use of this value will cause an error
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -199,3 +163,4 @@ LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).off
 
 error: aborting due to 11 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 0306a55af4e09bfa4139d67809d109e545e0229f..aa8f511e07268694dc2b0a8a8e66f9ef0e505326 100644 (file)
@@ -62,8 +62,8 @@ macro_rules! check {
 
 const _: *const u8 =
     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
+//~| pointer must be in-bounds
 
 const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
 //~^ ERROR any use of this value will cause an error
index 943de47879b5369aa4409037efefd4eaf84b4b6b..f00f40b32548153dec764041eca1ad61069d25c8 100644 (file)
@@ -1,4 +1,4 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
@@ -6,28 +6,17 @@ LL |         unsafe { intrinsics::offset(self, count) }
    |                  |
    |                  pointer arithmetic failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD
    |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |                  inside `_` at $DIR/ptr_comparisons.rs:61:34
    | 
-  ::: $DIR/ptr_comparisons.rs:61:1
+  ::: $DIR/ptr_comparisons.rs:61:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   | -------------------------------------------------------------------
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:61:34
 
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
   --> $DIR/ptr_comparisons.rs:64:33
    |
-LL | / const _: *const u8 =
-LL | |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-   | |_________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
-   |                                   |
-   |                                   memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL |     unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
 
 error: any use of this value will cause an error
   --> $DIR/ptr_comparisons.rs:68:27
@@ -37,6 +26,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) +
    |                           |
    |                           cannot cast pointer to integer because it was not created by cast from integer
    |
+   = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
@@ -53,3 +43,4 @@ LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0080`.
index 980d99a6d6c11170b52e96ebe93845fc6a7bb17c..8aa65bbfdc9e7bd233ef93860622538b063b83b8 100644 (file)
@@ -29,6 +29,6 @@ fn index<'a>(&'a self, idx: usize) -> &'a (dyn Debug + 'static) {
 
 fn main() {
     assert_eq!(&S[0], "hello");
-    &T[0];
+    let _ = &T[0];
     // let x = &x as &Debug;
 }
index f8b4d61b3230102eda9efc78d08ec554706bdb43..98cd6d54c1fd4e00732c196172da08157c1caf01 100644 (file)
@@ -2,5 +2,4 @@ fn foo() -> _ { 5 } //~ ERROR E0121
 
 static BAR: _ = "test"; //~ ERROR E0121
 
-fn main() {
-}
+fn main() {}
index 7f118c88e5e6e5a8197c0e118734a837b51b2f0f..e0b856db7a55d9f9d8334642aa437f14335fdb65 100644 (file)
@@ -15,7 +15,7 @@ fn main() {
                 yield ();
                 4i32
             };
-            &a;
+            let _ = &a;
         };
     }
 }
index 88dacff7b559be1706de68efb5933b48b2b02c35..72a2bd4ebc55c3a7501ebd345688e6dc303a7e39 100644 (file)
@@ -6,7 +6,7 @@ LL | |             // Tests that the generator transformation finds out that `a`
 LL | |             // during the yield expression. Type checking will also compute liveness
 LL | |             // and it should also find out that `a` is not live.
 ...  |
-LL | |             &a;
+LL | |             let _ = &a;
 LL | |         };
    | |__________^
    |
index 2f8754c95715f15ab6d04b835d14e7acfdd4ff4c..0cab36e5f2880017d77000ff050150b078165961 100644 (file)
@@ -11,7 +11,7 @@ fn main() {
                 yield;
                 true
             };
-            &opt;
+            let _ = &opt;
         }
     };
 }
index 71c6746e0e04059f761981cad47234156eae2988..1b90727fbc0a66f1a706130a91a43476a9773c8d 100644 (file)
@@ -19,9 +19,7 @@
 
 pub fn parse_summary<R: Read>(_: R, _: &Path) {
      let path_from_root = Path::new("");
-     Path::new(&iter::repeat("../")
-               .take(path_from_root.components().count() - 1)
-               .collect::<String>());
+     Path::new(&"../".repeat(path_from_root.components().count() - 1));
  }
 
 fn foo() {
diff --git a/src/test/ui/issues/issue-27895.rs b/src/test/ui/issues/issue-27895.rs
deleted file mode 100644 (file)
index 0018ac1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-fn main() {
-    let i = 5;
-    let index = 6;
-
-    match i {
-        0..=index => println!("winner"),
-        //~^ ERROR runtime values cannot be referenced in patterns
-        _ => println!("hello"),
-    }
-}
diff --git a/src/test/ui/issues/issue-27895.stderr b/src/test/ui/issues/issue-27895.stderr
deleted file mode 100644 (file)
index 55bd938..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/issue-27895.rs:6:13
-   |
-LL |         0..=index => println!("winner"),
-   |             ^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
index 894a61f3eff0ee10939a6cde8ec49095256a46c9..f47d5a347bb11823fdca66d33cab33e60c793d16 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
 fn main() {
-   &&[()][0];
+   let _ = &&[()][0];
    println!("{:?}", &[(),()][1]);
 }
index 3c97dad6b148bb5c4f3dea66fed5e9ea9a47aaef..5c5ce6c987ad124a2bc7662418e98fbf88a1428a 100644 (file)
@@ -9,7 +9,7 @@ trait FontTableTagConversions {
 
 impl FontTableTagConversions for FontTableTag {
   fn tag_to_string(self) {
-    &self;
+      let _ = &self;
   }
 }
 
index d8408ed85491f38d83a4e0b3a31b24d6f1bd5796..15355d30db6a561bc5d0512a3609c3bcc2acb203 100644 (file)
@@ -2,7 +2,7 @@
 
 fn main() {
     // We shouldn't promote this
-    &(main as fn() == main as fn());
+    let _ = &(main as fn() == main as fn());
     // Also check nested case
-    &(&(main as fn()) == &(main as fn()));
+    let _ = &(&(main as fn()) == &(main as fn()));
 }
index c229458da47daabe37c9dd49650c3faa4d62404a..f7923bd47439f114235b3f16846ae7a56c24e56b 100644 (file)
@@ -1,8 +1,8 @@
 error: values of the type `[u8; 18446744073709551615]` are too big for the current architecture
-  --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12
+  --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5
    |
 LL |     Bug::V([0; !0]);
-   |            ^^^^^^^
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lint/unused-borrows.rs b/src/test/ui/lint/unused-borrows.rs
new file mode 100644 (file)
index 0000000..4518522
--- /dev/null
@@ -0,0 +1,33 @@
+#![deny(unused_must_use)]
+
+fn foo(_: i32) -> bool { todo!() }
+
+fn bar() -> &'static i32 {
+    &42;
+    //~^ unused
+
+    &mut foo(42);
+    //~^ unused
+
+    &&42;
+    //~^ unused
+
+    &&mut 42;
+    //~^ unused
+
+    &mut &42;
+    //~^ unused
+
+    let _result = foo(4)
+        && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines)
+    && foo(42);
+    //~^ unused
+
+    let _ = &42; // ok
+
+    &42 // ok
+}
+
+fn main() {
+    let _ = bar();
+}
diff --git a/src/test/ui/lint/unused-borrows.stderr b/src/test/ui/lint/unused-borrows.stderr
new file mode 100644 (file)
index 0000000..24899fe
--- /dev/null
@@ -0,0 +1,44 @@
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:6:5
+   |
+LL |     &42;
+   |     ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-borrows.rs:1:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:9:5
+   |
+LL |     &mut foo(42);
+   |     ^^^^^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:12:5
+   |
+LL |     &&42;
+   |     ^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:15:5
+   |
+LL |     &&mut 42;
+   |     ^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:18:5
+   |
+LL |     &mut &42;
+   |     ^^^^^^^^
+
+error: unused borrow that must be used
+  --> $DIR/unused-borrows.rs:23:5
+   |
+LL |     && foo(42);
+   |     ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.rs
new file mode 100644 (file)
index 0000000..9139775
--- /dev/null
@@ -0,0 +1,16 @@
+// Regression test for #84632: Recursion limit is ignored
+// for builtin macros that eagerly expands.
+
+#![recursion_limit = "15"]
+macro_rules! a {
+    () => ("");
+    (A) => (concat!("", a!()));
+    (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+    //~^ ERROR recursion limit reached
+    //~| HELP consider adding
+}
+
+fn main() {
+    a!(A, A, A, A, A);
+    a!(A, A, A, A, A, A, A, A, A, A, A);
+}
diff --git a/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/src/test/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr
new file mode 100644 (file)
index 0000000..e6067e3
--- /dev/null
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `concat!`
+  --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28
+   |
+LL |     (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     a!(A, A, A, A, A, A, A, A, A, A, A);
+   |     ------------------------------------ in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`)
+   = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
index f829129d516b2247ff39aa5b9533bc6f91e5ea5a..f4e81a6be2a8906b4607abb2bc817b4836cc6faf 100644 (file)
@@ -2,13 +2,22 @@
 
 #![deny(or_patterns_back_compat)]
 #![allow(unused_macros)]
-macro_rules! foo { ($x:pat_param | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+macro_rules! foo { ($x:pat_param | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
+macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
 macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
 macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
 macro_rules! match_any {
-    ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => {
+        //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        //~| WARN this was previously accepted
         match $expr {
             $(
                 $( $pat => $expr_arm, )+
index 1cdaa1cd6317bc8d809a7f445c1e51d554df53bb..49affdd38da9d79e4ac65db131ccbef38f255fd4 100644 (file)
@@ -2,13 +2,22 @@
 
 #![deny(or_patterns_back_compat)]
 #![allow(unused_macros)]
-macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+macro_rules! foo { ($x:pat | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
 macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
 macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
 macro_rules! match_any {
-    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+    ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
+        //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+        //~| WARN this was previously accepted
         match $expr {
             $(
                 $( $pat => $expr_arm, )+
index 01d220dd0b11473450c13bb4ba80902339dc83be..62687eb36b89e7984bc62cca630d88984f97dccf 100644 (file)
@@ -1,5 +1,5 @@
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:5:21
+  --> $DIR/macro-or-patterns-back-compat.rs:6:21
    |
 LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
    |                     ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
@@ -9,24 +9,35 @@ note: the lint level is defined here
    |
 LL | #![deny(or_patterns_back_compat)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:6:23
+  --> $DIR/macro-or-patterns-back-compat.rs:9:23
    |
 LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
    |                       ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:9:21
+  --> $DIR/macro-or-patterns-back-compat.rs:14:21
    |
 LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
    |                     ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
 
 error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-  --> $DIR/macro-or-patterns-back-compat.rs:11:26
+  --> $DIR/macro-or-patterns-back-compat.rs:18:26
    |
 LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
    |                          ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/non-constant-in-const-path.rs b/src/test/ui/non-constant-in-const-path.rs
deleted file mode 100644 (file)
index 343bb98..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    let x = 0;
-    match 1 {
-        0 ..= x => {}
-        //~^ ERROR runtime values cannot be referenced in patterns
-    };
-}
diff --git a/src/test/ui/non-constant-in-const-path.stderr b/src/test/ui/non-constant-in-const-path.stderr
deleted file mode 100644 (file)
index 5936f76..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/non-constant-in-const-path.rs:4:15
-   |
-LL |         0 ..= x => {}
-   |               ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.rs
deleted file mode 100644 (file)
index f10a7f2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let x = 255u8;
-    let 0u8..=x = 0;
-    //~^ ERROR runtime values cannot be referenced in patterns
-}
diff --git a/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr b/src/test/ui/pattern/issue-68394-let-pat-runtime-value.stderr
deleted file mode 100644 (file)
index c1508bd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: runtime values cannot be referenced in patterns
-  --> $DIR/issue-68394-let-pat-runtime-value.rs:3:15
-   |
-LL |     let 0u8..=x = 0;
-   |               ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/pattern/non-constant-in-const-path.rs b/src/test/ui/pattern/non-constant-in-const-path.rs
new file mode 100644 (file)
index 0000000..3918485
--- /dev/null
@@ -0,0 +1,18 @@
+// Checks if we emit `PatternError`s correctly.
+// This is also a regression test for #27895 and #68394.
+
+static FOO: u8 = 10;
+
+fn main() {
+    let x = 0;
+    let 0u8..=x = 0;
+    //~^ ERROR: runtime values cannot be referenced in patterns
+    let 0u8..=FOO = 0;
+    //~^ ERROR: statics cannot be referenced in patterns
+    match 1 {
+        0 ..= x => {}
+        //~^ ERROR: runtime values cannot be referenced in patterns
+        0 ..= FOO => {}
+        //~^ ERROR: statics cannot be referenced in patterns
+    };
+}
diff --git a/src/test/ui/pattern/non-constant-in-const-path.stderr b/src/test/ui/pattern/non-constant-in-const-path.stderr
new file mode 100644 (file)
index 0000000..53c3974
--- /dev/null
@@ -0,0 +1,28 @@
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:8:15
+   |
+LL |     let 0u8..=x = 0;
+   |               ^
+
+error[E0158]: statics cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:10:15
+   |
+LL |     let 0u8..=FOO = 0;
+   |               ^^^
+
+error[E0080]: runtime values cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:13:15
+   |
+LL |         0 ..= x => {}
+   |               ^
+
+error[E0158]: statics cannot be referenced in patterns
+  --> $DIR/non-constant-in-const-path.rs:15:15
+   |
+LL |         0 ..= FOO => {}
+   |               ^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0158.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/repr/issue-83505-repr-simd.rs b/src/test/ui/repr/issue-83505-repr-simd.rs
new file mode 100644 (file)
index 0000000..280b771
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test for the ICE described in #83505.
+
+#![crate_type="lib"]
+
+#[repr(simd)]
+//~^ ERROR: attribute should be applied to a struct [E0517]
+//~| ERROR: unsupported representation for zero-variant enum [E0084]
+enum Es {}
+static CLs: Es;
+//~^ ERROR: free static item without body
diff --git a/src/test/ui/repr/issue-83505-repr-simd.stderr b/src/test/ui/repr/issue-83505-repr-simd.stderr
new file mode 100644 (file)
index 0000000..f1390a6
--- /dev/null
@@ -0,0 +1,30 @@
+error: free static item without body
+  --> $DIR/issue-83505-repr-simd.rs:9:1
+   |
+LL | static CLs: Es;
+   | ^^^^^^^^^^^^^^-
+   |               |
+   |               help: provide a definition for the static: `= <expr>;`
+
+error[E0517]: attribute should be applied to a struct
+  --> $DIR/issue-83505-repr-simd.rs:5:8
+   |
+LL | #[repr(simd)]
+   |        ^^^^
+...
+LL | enum Es {}
+   | ---------- not a struct
+
+error[E0084]: unsupported representation for zero-variant enum
+  --> $DIR/issue-83505-repr-simd.rs:5:1
+   |
+LL | #[repr(simd)]
+   | ^^^^^^^^^^^^^
+...
+LL | enum Es {}
+   | ---------- zero-variant enum
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0084, E0517.
+For more information about an error, try `rustc --explain E0084`.
diff --git a/src/test/ui/rt-explody-panic-payloads.rs b/src/test/ui/rt-explody-panic-payloads.rs
new file mode 100644 (file)
index 0000000..1d3a2ff
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+use std::env;
+use std::process::Command;
+
+struct Bomb;
+
+impl Drop for Bomb {
+    fn drop(&mut self) {
+        std::panic::panic_any(Bomb);
+    }
+}
+
+fn main() {
+    let args = env::args().collect::<Vec<_>>();
+    let output = match &args[..] {
+        [me] => Command::new(&me).arg("plant the").output(),
+        [..] => std::panic::panic_any(Bomb),
+    }.expect("running the command should have succeeded");
+    println!("{:#?}", output);
+    let stderr = std::str::from_utf8(&output.stderr);
+    assert!(stderr.map(|v| {
+        v.ends_with("drop of the panic payload panicked")
+    }).unwrap_or(false));
+}
diff --git a/src/test/ui/traits/issue-78632.rs b/src/test/ui/traits/issue-78632.rs
new file mode 100644 (file)
index 0000000..c72a2ae
--- /dev/null
@@ -0,0 +1,59 @@
+// check-pass
+//
+// Regression test for issue #78632
+
+#![crate_type = "lib"]
+
+pub trait Corge<T> {
+    type Fred;
+}
+
+impl Corge<u8> for () {
+    type Fred = u32;
+}
+
+pub trait Waldo {
+    type Quax;
+}
+
+impl Waldo for u32 {
+    type Quax = u8;
+}
+
+pub trait Grault
+where
+    (): Corge<Self::Thud>,
+{
+    type Thud;
+    fn bar(_: <() as Corge<Self::Thud>>::Fred) {}
+}
+
+impl<T> Grault for T
+where
+    T: Waldo,
+    (): Corge<T::Quax>,
+    <() as Corge<T::Quax>>::Fred: Waldo,
+{
+    type Thud = u8;
+}
+
+pub trait Plugh<I> {
+    fn baz();
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct Qiz<T> {
+    foo: T,
+}
+
+impl<T> Plugh<<() as Corge<T::Thud>>::Fred> for Qiz<T>
+where
+    T: Grault,
+    (): Corge<T::Thud>,
+{
+    fn baz() {}
+}
+
+pub fn test() {
+    <Qiz<u32> as Plugh<u32>>::baz();
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-85113.rs b/src/test/ui/type-alias-impl-trait/issue-85113.rs
new file mode 100644 (file)
index 0000000..b09833f
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(min_type_alias_impl_trait)]
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+//~^ ERROR: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+//~| ERROR: the type `&'<empty> str` does not fulfill the required lifetime
+//~| ERROR: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+
+trait Output<'a> {}
+
+impl<'a> Output<'a> for &'a str {}
+
+fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
+    let out: OpaqueOutputImpl<'a> = arg;
+    arg
+}
+
+fn main() {
+    let s = String::from("wassup");
+    cool_fn(&s);
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-85113.stderr b/src/test/ui/type-alias-impl-trait/issue-85113.stderr
new file mode 100644 (file)
index 0000000..361d668
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-85113.rs:5:29
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                             ^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type `&'<empty> str` captures lifetime smaller than the function body
+  --> $DIR/issue-85113.rs:5:29
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                             ^^^^^^^^^^^^^^^^^^^^
+
+error[E0477]: the type `&'<empty> str` does not fulfill the required lifetime
+  --> $DIR/issue-85113.rs:5:29
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                             ^^^^^^^^^^^^^^^^^^^^
+   |
+note: type must outlive the lifetime `'a` as defined on the item at 5:23
+  --> $DIR/issue-85113.rs:5:23
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                       ^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/issue-85113.rs:5:29
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: first, the lifetime cannot outlive the empty lifetime...
+note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the item at 5:23...
+  --> $DIR/issue-85113.rs:5:23
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                       ^^
+note: ...so that the types are compatible
+  --> $DIR/issue-85113.rs:5:29
+   |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+   |                             ^^^^^^^^^^^^^^^^^^^^
+   = note: expected `Output<'a>`
+              found `Output<'_>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0477, E0495, E0700.
+For more information about an error, try `rustc --explain E0477`.
diff --git a/src/test/ui/typeck/issue-75889.rs b/src/test/ui/typeck/issue-75889.rs
new file mode 100644 (file)
index 0000000..84c067e
--- /dev/null
@@ -0,0 +1,6 @@
+// Regression test for #75889.
+
+const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-75889.stderr b/src/test/ui/typeck/issue-75889.stderr
new file mode 100644 (file)
index 0000000..0a8a3c9
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/issue-75889.rs:3:24
+   |
+LL | const FOO: dyn Fn() -> _ = "";
+   |                        ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/issue-75889.rs:4:25
+   |
+LL | static BOO: dyn Fn() -> _ = "";
+   |                         ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
index be18737b5f13105b8d5b7b89d01a727c679a5fa2..4b653238aa75032cd6e9aeeb9c332bd5308fd1ff 100644 (file)
@@ -39,7 +39,47 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:18:5
+  --> $DIR/variance-btree-invariant-types.rs:17:5
+   |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+   |                      ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:20:5
+   |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+   |                      ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:23:5
+   |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+   |                         ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:26:5
+   |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+   |                         ---- lifetime `'new` defined here
+LL |     v
+   |     ^ returning this value requires that `'new` must outlive `'static`
+   |
+   = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/variance-btree-invariant-types.rs:31:5
    |
 LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
    |                    ---- lifetime `'new` defined here
@@ -50,7 +90,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:22:5
+  --> $DIR/variance-btree-invariant-types.rs:35:5
    |
 LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
    |                    ---- lifetime `'new` defined here
@@ -61,7 +101,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:26:5
+  --> $DIR/variance-btree-invariant-types.rs:39:5
    |
 LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
    |                       ---- lifetime `'new` defined here
@@ -72,7 +112,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:30:5
+  --> $DIR/variance-btree-invariant-types.rs:43:5
    |
 LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
    |                       ---- lifetime `'new` defined here
@@ -83,7 +123,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:35:5
+  --> $DIR/variance-btree-invariant-types.rs:48:5
    |
 LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
    |                    ---- lifetime `'new` defined here
@@ -94,7 +134,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:39:5
+  --> $DIR/variance-btree-invariant-types.rs:52:5
    |
 LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
    |                    ---- lifetime `'new` defined here
@@ -105,7 +145,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:43:5
+  --> $DIR/variance-btree-invariant-types.rs:56:5
    |
 LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
    |                       ---- lifetime `'new` defined here
@@ -116,7 +156,7 @@ LL |     v
    = help: consider replacing `'new` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/variance-btree-invariant-types.rs:47:5
+  --> $DIR/variance-btree-invariant-types.rs:60:5
    |
 LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
    |                       ---- lifetime `'new` defined here
@@ -126,5 +166,5 @@ LL |     v
    |
    = help: consider replacing `'new` with `'static`
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
index 2e5dc671db8811684bb1abfa44734e032f0a02d8..4549622f24ac3276710b150c2e0c4cda970bc6b2 100644 (file)
@@ -1,4 +1,4 @@
-use std::collections::btree_map::{IterMut, OccupiedEntry, VacantEntry};
+use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry};
 
 fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> {
     v //~ ERROR mismatched types
@@ -13,6 +13,19 @@ fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'
     v //~ ERROR mismatched types
 }
 
+fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+    v //~ ERROR mismatched types
+}
+fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+    v //~ ERROR mismatched types
+}
+fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+    v //~ ERROR mismatched types
+}
+fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+    v //~ ERROR mismatched types
+}
+
 fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
                          -> OccupiedEntry<'a, &'new (), ()> {
     v //~ ERROR mismatched types
index 8172a019b65edcabcbd93ef39ef5f5cb483c962c..ba47bdff281a2afe6422db485e2761d09bca29e2 100644 (file)
@@ -59,125 +59,185 @@ LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:18:5
+  --> $DIR/variance-btree-invariant-types.rs:17:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, &'new (), _>`
+              found struct `RangeMut<'_, &'static (), _>`
+note: the lifetime `'new` as defined on the function body at 16:22...
+  --> $DIR/variance-btree-invariant-types.rs:16:22
+   |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+   |                      ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:20:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, _, &'new ()>`
+              found struct `RangeMut<'_, _, &'static ()>`
+note: the lifetime `'new` as defined on the function body at 19:22...
+  --> $DIR/variance-btree-invariant-types.rs:19:22
+   |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+   |                      ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:23:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, &'static (), _>`
+              found struct `RangeMut<'_, &'new (), _>`
+note: the lifetime `'new` as defined on the function body at 22:25...
+  --> $DIR/variance-btree-invariant-types.rs:22:25
+   |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+   |                         ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:26:5
+   |
+LL |     v
+   |     ^ lifetime mismatch
+   |
+   = note: expected struct `RangeMut<'_, _, &'static ()>`
+              found struct `RangeMut<'_, _, &'new ()>`
+note: the lifetime `'new` as defined on the function body at 25:25...
+  --> $DIR/variance-btree-invariant-types.rs:25:25
+   |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+   |                         ^^^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+  --> $DIR/variance-btree-invariant-types.rs:31:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 16:20...
-  --> $DIR/variance-btree-invariant-types.rs:16:20
+note: the lifetime `'new` as defined on the function body at 29:20...
+  --> $DIR/variance-btree-invariant-types.rs:29:20
    |
 LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:22:5
+  --> $DIR/variance-btree-invariant-types.rs:35:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 20:20...
-  --> $DIR/variance-btree-invariant-types.rs:20:20
+note: the lifetime `'new` as defined on the function body at 33:20...
+  --> $DIR/variance-btree-invariant-types.rs:33:20
    |
 LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:26:5
+  --> $DIR/variance-btree-invariant-types.rs:39:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 24:23...
-  --> $DIR/variance-btree-invariant-types.rs:24:23
+note: the lifetime `'new` as defined on the function body at 37:23...
+  --> $DIR/variance-btree-invariant-types.rs:37:23
    |
 LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:30:5
+  --> $DIR/variance-btree-invariant-types.rs:43:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
               found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 28:23...
-  --> $DIR/variance-btree-invariant-types.rs:28:23
+note: the lifetime `'new` as defined on the function body at 41:23...
+  --> $DIR/variance-btree-invariant-types.rs:41:23
    |
 LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:35:5
+  --> $DIR/variance-btree-invariant-types.rs:48:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
               found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 33:20...
-  --> $DIR/variance-btree-invariant-types.rs:33:20
+note: the lifetime `'new` as defined on the function body at 46:20...
+  --> $DIR/variance-btree-invariant-types.rs:46:20
    |
 LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:39:5
+  --> $DIR/variance-btree-invariant-types.rs:52:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
               found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 37:20...
-  --> $DIR/variance-btree-invariant-types.rs:37:20
+note: the lifetime `'new` as defined on the function body at 50:20...
+  --> $DIR/variance-btree-invariant-types.rs:50:20
    |
 LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
    |                    ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:43:5
+  --> $DIR/variance-btree-invariant-types.rs:56:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
               found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 41:23...
-  --> $DIR/variance-btree-invariant-types.rs:41:23
+note: the lifetime `'new` as defined on the function body at 54:23...
+  --> $DIR/variance-btree-invariant-types.rs:54:23
    |
 LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error[E0308]: mismatched types
-  --> $DIR/variance-btree-invariant-types.rs:47:5
+  --> $DIR/variance-btree-invariant-types.rs:60:5
    |
 LL |     v
    |     ^ lifetime mismatch
    |
    = note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
               found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 45:23...
-  --> $DIR/variance-btree-invariant-types.rs:45:23
+note: the lifetime `'new` as defined on the function body at 58:23...
+  --> $DIR/variance-btree-invariant-types.rs:58:23
    |
 LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
    |                       ^^^^
    = note: ...does not necessarily outlive the static lifetime
 
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 7265d1b832376401f9a8997a9b5c4b8e2a2a8209..7d7b7c811738e897ac7aa0a61d95908ca1b49368 100644 (file)
@@ -342,7 +342,7 @@ We have prioritization labels and a sync-blocker label, which are described belo
 - [P-low][p-low]: Requires attention (fix/response/evaluation) by a team member but isn't urgent.
 - [P-medium][p-medium]: Should be addressed by a team member until the next sync.
 - [P-high][p-high]: Should be immediately addressed and will require an out-of-cycle sync or a backport.
-- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync. 
+- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync.
 Or rather: before the sync this should be addressed,
 e.g. by removing a lint again, so it doesn't hit beta/stable.
 
index 6c556f579ca4f96cdc9e984663d2a3af00e8c364..bd322cc80702acc0ee8c2498fd71f903b81dfdf9 100644 (file)
@@ -95,7 +95,7 @@ As with `cargo check`, this includes dependencies that are members of the worksp
 If you want to run Clippy **only** on the given crate, use the `--no-deps` option like this:
 
 ```terminal
-cargo clippy -p example -- --no-deps 
+cargo clippy -p example -- --no-deps
 ```
 
 ### As a rustc replacement (`clippy-driver`)
index 840c1eba79d115ad120dffc8c8a9edaaebbfc792..729941f345a9217ad6b6304062965b3b9052b5b0 100644 (file)
@@ -411,9 +411,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
 
         if let ExprKind::Block(block, _) = expr.kind {
             match block.rules {
-                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
-                | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided)
-                | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => {
+                BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => {
                     self.has_unsafe = true;
                 },
                 _ => {},
index e6d84bc7560ba9cc9ae8d2d76c633d938d896a77..90c034bd02a9e8493b93718f178de160cd60857e 100644 (file)
@@ -178,7 +178,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
         (MacCall(l), MacCall(r)) => eq_mac_call(l, r),
         (Struct(lse), Struct(rse)) => {
-            eq_maybe_qself(&lse.qself, &rse.qself) 
+            eq_maybe_qself(&lse.qself, &rse.qself)
                 && eq_path(&lse.path, &rse.path)
                 && eq_struct_rest(&lse.rest, &rse.rest)
                 && unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
index e2e307ce4f6cf93df422f3c10afa1328191da276..ed3a2fff83f168e7825b1c4e2fce3dee7cf6b820 100644 (file)
@@ -96,9 +96,9 @@ cargo dev ide_setup
 
 ## lintcheck
 `cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results.  
-You can `git diff` the updated log against its previous version and 
+You can `git diff` the updated log against its previous version and
 see what impact your lint made on a small set of crates.  
-If you add a new lint, please audit the resulting warnings and make sure 
+If you add a new lint, please audit the resulting warnings and make sure
 there are no false positives and that the suggestions are valid.
 
 Refer to the tools [README] for more details.
index 52bbcc0a8317dd47e2afbe4ccd2e854deaac7d10..a61070d8a80efc11fb1c3aae004b5c14d1fc28b8 100644 (file)
@@ -73,5 +73,5 @@ You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy wit
 print a warning if Clippys suggestions fail to apply (if the resulting code does not build).  
 This lets us spot bad suggestions or false positives automatically in some cases.  
 
-Please note that the target dir should be cleaned afterwards since clippy will modify 
+Please note that the target dir should be cleaned afterwards since clippy will modify
 the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
index bf68a7bbbf1d4e1b398b25216a0ee8009cb7dde0..46b7833f42804c2b55787d49b947e9fca45fcc38 100644 (file)
@@ -6,6 +6,6 @@
 fn main() {
     let s = String::from("String");
     s.as_bytes().get(3);
-    &s.as_bytes().get(3);
+    let _ = &s.as_bytes().get(3);
     s[..].as_bytes().get(3);
 }
index 629812cc02cb899961fb384c7d51cb698713a698..c5e983d4d4e00d1c0c9dd803f70cd95b45b7cf95 100644 (file)
@@ -6,6 +6,6 @@
 fn main() {
     let s = String::from("String");
     s.bytes().nth(3);
-    &s.bytes().nth(3);
+    let _ = &s.bytes().nth(3);
     s[..].bytes().nth(3);
 }
index 9a5742928cd617da55eadb98ded6f012b9553f3e..536decf5e7fc49bf8ce585585ef35d02c8c49abc 100644 (file)
@@ -7,10 +7,10 @@ LL |     s.bytes().nth(3);
    = note: `-D clippy::bytes-nth` implied by `-D warnings`
 
 error: called `.byte().nth()` on a `String`
-  --> $DIR/bytes_nth.rs:9:6
+  --> $DIR/bytes_nth.rs:9:14
    |
-LL |     &s.bytes().nth(3);
-   |      ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL |     let _ = &s.bytes().nth(3);
+   |              ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
 
 error: called `.byte().nth()` on a `str`
   --> $DIR/bytes_nth.rs:10:5
index b11dadda6c24ed753f23663492f5a675a6f82702..97c5929783d882c51dd754244c8bec46ff292f5d 100644 (file)
@@ -50,7 +50,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec.len();
     boxed_slice.len();
     vec_deque.len();
@@ -62,13 +62,13 @@ fn main() {
     binary_heap.len();
 
     vec.len();
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec_deque.len();
     hash_map.len();
     b_tree_map.len();
     linked_list.len();
 
-    &vec[..].len();
+    let _ = &vec[..].len();
     vec.len();
     vec_deque.len();
     hash_set.len();
index 7d49c6a3dbbb939d90144b60e51123e85293d620..70bb734763f09bef26eb35bc4b45f9c196dce29b 100644 (file)
@@ -50,7 +50,7 @@ fn main() {
     linked_list.push_back(1);
     binary_heap.push(1);
 
-    &vec[..].iter().count();
+    let _ = &vec[..].iter().count();
     vec.iter().count();
     boxed_slice.iter().count();
     vec_deque.iter().count();
@@ -62,13 +62,13 @@ fn main() {
     binary_heap.iter().count();
 
     vec.iter_mut().count();
-    &vec[..].iter_mut().count();
+    let _ = &vec[..].iter_mut().count();
     vec_deque.iter_mut().count();
     hash_map.iter_mut().count();
     b_tree_map.iter_mut().count();
     linked_list.iter_mut().count();
 
-    &vec[..].into_iter().count();
+    let _ = &vec[..].into_iter().count();
     vec.into_iter().count();
     vec_deque.into_iter().count();
     hash_set.into_iter().count();
index f3fb98e65b9906aa35381897f64948aa21635d42..1d2c22f9dfad5470e0b1d478b439a26587bc7a1b 100644 (file)
@@ -1,8 +1,8 @@
 error: called `.iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:53:6
+  --> $DIR/iter_count.rs:53:14
    |
-LL |     &vec[..].iter().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].iter().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
    |
    = note: `-D clippy::iter-count` implied by `-D warnings`
 
@@ -67,10 +67,10 @@ LL |     vec.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
 
 error: called `.iter_mut().count()` on a `slice`
-  --> $DIR/iter_count.rs:65:6
+  --> $DIR/iter_count.rs:65:14
    |
-LL |     &vec[..].iter_mut().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].iter_mut().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.iter_mut().count()` on a `VecDeque`
   --> $DIR/iter_count.rs:66:5
@@ -97,10 +97,10 @@ LL |     linked_list.iter_mut().count();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
 
 error: called `.into_iter().count()` on a `slice`
-  --> $DIR/iter_count.rs:71:6
+  --> $DIR/iter_count.rs:71:14
    |
-LL |     &vec[..].into_iter().count();
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL |     let _ = &vec[..].into_iter().count();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
 
 error: called `.into_iter().count()` on a `Vec`
   --> $DIR/iter_count.rs:72:5
index 27ecb532dd00e97bbaa2672049c03e64af9e5ef3..0174d3ffcbc2af59caf2dae5668fadd27b737161 100644 (file)
 
             $scope.bySearch = function (lint, index, array) {
                 let searchStr = $scope.search;
-                // It can be `null` I haven't missed this value 
+                // It can be `null` I haven't missed this value
                 if (searchStr == null || searchStr.length < 3) {
                     return true;
                 }
                 }
 
                 // Search the description
-                // The use of `for`-loops instead of `foreach` enables us to return early 
+                // The use of `for`-loops instead of `foreach` enables us to return early
                 let terms = searchStr.split(" ");
                 for (index = 0; index < terms.length; index++) {
                     if (lint.id.indexOf(terms[index]) !== -1) {
 
         let children = themeMenu.children;
         for (let index = 0; index < children.length; index++) {
-            let child = children[index]; 
+            let child = children[index];
             child.addEventListener("click", function(e) {
                 setTheme(child.id, true);
             });
         let enableHighlight = false;
         let enableNight = false;
         let enableAyu = false;
-        
+
         if (theme == "ayu") {
             enableAyu = true;
         } else if (theme == "coal" || theme == "navy") {
index 47960c3f6cc2b596d9977cae1c7116ff173381ca..15edd628cdffcfa4532f48f6b30175143ceeba0f 100644 (file)
@@ -347,7 +347,7 @@ fn check(&mut self, file: &Path, report: &mut Report) {
                 } else {
                     report.errors += 1;
                     print!("{}:{}: broken link fragment ", pretty_path, i + 1);
-                    println!("`#{}` pointing to `{}`", fragment, pretty_path);
+                    println!("`#{}` pointing to `{}`", fragment, target_pretty_path);
                 };
             }
         });
index 3e376629f74fe6f6cd7657302074bc53ad2ae04f..9c580d8e07ee8c6ce7f3eef11cd76d8c31873448 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=sometarget">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="sometarget">sometarget</a>...</p>
index c6ec999e5cfe229422420eb7b1fb5aa09ae8cbf2..1a0b1b00e0de095dde50d75f8a2cbe7f8a2a9bf8 100644 (file)
@@ -15,7 +15,7 @@ fn run(dirname: &str) -> (ExitStatus, String, String) {
 fn broken_test(dirname: &str, expected: &str) {
     let (status, stdout, stderr) = run(dirname);
     assert!(!status.success());
-    if !stdout.contains(expected) {
+    if !contains(expected, &stdout) {
         panic!(
             "stdout did not contain expected text: {}\n\
             --- stdout:\n\
@@ -27,6 +27,25 @@ fn broken_test(dirname: &str, expected: &str) {
     }
 }
 
+fn contains(expected: &str, actual: &str) -> bool {
+    // Normalize for Windows paths.
+    let actual = actual.replace('\\', "/");
+    actual.lines().any(|mut line| {
+        for (i, part) in expected.split("[..]").enumerate() {
+            match line.find(part) {
+                Some(j) => {
+                    if i == 0 && j != 0 {
+                        return false;
+                    }
+                    line = &line[j + part.len()..];
+                }
+                None => return false,
+            }
+        }
+        line.is_empty() || expected.ends_with("[..]")
+    })
+}
+
 fn valid_test(dirname: &str) {
     let (status, stdout, stderr) = run(dirname);
     if !status.success() {
@@ -48,30 +67,47 @@ fn valid() {
 
 #[test]
 fn basic_broken() {
-    broken_test("basic_broken", "bar.html");
+    broken_test("basic_broken", "foo.html:3: broken link - `bar.html`");
 }
 
 #[test]
 fn broken_fragment_local() {
-    broken_test("broken_fragment_local", "#somefrag");
+    broken_test(
+        "broken_fragment_local",
+        "foo.html:3: broken link fragment `#somefrag` pointing to `foo.html`",
+    );
 }
 
 #[test]
 fn broken_fragment_remote() {
-    broken_test("broken_fragment_remote/inner", "#somefrag");
+    broken_test(
+        "broken_fragment_remote/inner",
+        "foo.html:3: broken link fragment `#somefrag` pointing to \
+         `[..]/broken_fragment_remote/bar.html`",
+    );
 }
 
 #[test]
 fn broken_redir() {
-    broken_test("broken_redir", "sometarget");
+    broken_test(
+        "broken_redir",
+        "foo.html:3: broken redirect from `redir-bad.html` to `sometarget`",
+    );
 }
 
 #[test]
 fn directory_link() {
-    broken_test("directory_link", "somedir");
+    broken_test(
+        "directory_link",
+        "foo.html:3: directory link to `somedir` (directory links should use index.html instead)",
+    );
 }
 
 #[test]
 fn redirect_loop() {
-    broken_test("redirect_loop", "redir-bad.html");
+    broken_test(
+        "redirect_loop",
+        "foo.html:3: redirect from `redir-bad.html` to `[..]redirect_loop/redir-bad.html` \
+         which is also a redirect (not supported)",
+    );
 }
index fe7780e6739bfe3106e66f7982833ccc6ebea34d..bc567caa78b7e500efaba0d7c2290fc73931a39d 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=redir-bad.html">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="redir-bad.html">redir-bad.html</a>...</p>
index d21336e7e738bb08d3497a27aa49ecd0fda99abe..f32683efe67ec8bf382534aa88f201d38b19d61f 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=xxx">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="xxx">xxx</a>...</p>
index 1808b23aed8564f539a3e902dee107bd4773727b..3a52a8973853738b9b882e5aaeba45c341f58572 100644 (file)
@@ -2,6 +2,7 @@
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL=redir-target.html">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="redir-target.html">redir-target.html</a>...</p>
index 35af23b6a94459da538ee1479e863c7699620f84..23f05fc603252b7906bd7e44208ab24038f8da12 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 35af23b6a94459da538ee1479e863c7699620f84
+Subproject commit 23f05fc603252b7906bd7e44208ab24038f8da12
index 0f23663d6c2f9d057b35b8479bb3a1037fdea46b..68354b6ceaf25aa1a973050c358bac6baaf823fe 100644 (file)
@@ -176,7 +176,7 @@ https://rust-lang.github.io/rustfmt/?version=v1.4.33&search=#imports_granularity
 
 ### Changed
 
-- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506)) 
+- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506))
 
 In this example the `// else comment` refers to the `else`:
 ```rust
@@ -213,7 +213,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 ### Fixed
 - Formatting of empty blocks with attributes which only contained comments is no longer butchered.([#4475](https://github.com/rust-lang/rustfmt/issues/4475), [#4467](https://github.com/rust-lang/rustfmt/issues/4467), [#4452](https://github.com/rust-lang/rustfmt/issues/4452#issuecomment-705886282), [#4522](https://github.com/rust-lang/rustfmt/issues/4522))
-- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872)) 
+- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872))
 
 ### Install/Download Options
 - **crates.io package** - *pending*
@@ -297,7 +297,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 - Fix aligning comments of different group
 - Fix flattening imports with a single `self`.
 - Fix removing attributes on function parameters.
-- Fix removing `impl` keyword from opaque type. 
+- Fix removing `impl` keyword from opaque type.
 
 ## [1.4.8] 2019-09-08
 
@@ -329,7 +329,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 - Add `--message-format` command line option to `cargo-fmt`.
 - Add `-l,--files-with-diff` command line option to `rustfmt`.
-- Add `json` emit mode. 
+- Add `json` emit mode.
 
 ### Fixed
 
@@ -380,7 +380,7 @@ if toks.eat_token(Token::Word("modify"))? && toks.eat_token(Token::Word("labels"
 
 ### Added
 
-- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt 
+- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt
 from formatting an attribute #3665
 
 ### Changed
index 37cb7474130c8086300ec3d2a95d6e0c3d9e3f52..9daa70653797657d6488a952e1f56f3c7f4d3411 100644 (file)
@@ -17,7 +17,7 @@ To enable unstable options, set `unstable_features = true` in `rustfmt.toml` or
 
 Below you find a detailed visual guide on all the supported configuration options of rustfmt:
 
-## `array_width` 
+## `array_width`
 
 Maximum width of an array literal before falling back to vertical formatting.
 
@@ -25,11 +25,11 @@ Maximum width of an array literal before falling back to vertical formatting.
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
-## `attr_fn_like_width` 
+## `attr_fn_like_width`
 
 Maximum width of the args of a function-like attributes before falling back to vertical formatting.
 
@@ -37,7 +37,7 @@ Maximum width of the args of a function-like attributes before falling back to v
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -295,7 +295,7 @@ where
 }
 ```
 
-## `chain_width` 
+## `chain_width`
 
 Maximum width of a chain to fit on one line.
 
@@ -303,7 +303,7 @@ Maximum width of a chain to fit on one line.
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -751,7 +751,7 @@ trait Lorem {
 }
 ```
 
-## `fn_call_width` 
+## `fn_call_width`
 
 Maximum width of the args of a function call before falling back to vertical formatting.
 
@@ -759,7 +759,7 @@ Maximum width of the args of a function call before falling back to vertical for
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2124,7 +2124,7 @@ Don't reformat out of line modules
 - **Possible values**: `true`, `false`
 - **Stable**: No (tracking issue: #3389)
 
-## `single_line_if_else_max_width` 
+## `single_line_if_else_max_width`
 
 Maximum line length for single line if-else expressions. A value of `0` (zero) results in if-else expressions always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2132,7 +2132,7 @@ Maximum line length for single line if-else expressions. A value of `0` (zero) r
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2313,7 +2313,7 @@ fn main() {
 
 See also: [`indent_style`](#indent_style).
 
-## `struct_lit_width` 
+## `struct_lit_width`
 
 Maximum width in the body of a struct literal before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2321,11 +2321,11 @@ Maximum width in the body of a struct literal before falling back to vertical fo
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence.
 
 See also [`max_width`](#max_width), [`use_small_heuristics`](#use_small_heuristics), and [`struct_lit_single_line`](#struct_lit_single_line)
 
-## `struct_variant_width` 
+## `struct_variant_width`
 
 Maximum width in the body of a struct variant before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
 
@@ -2333,7 +2333,7 @@ Maximum width in the body of a struct variant before falling back to vertical fo
 - **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
 - **Stable**: Yes
 
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence. 
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence.
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
@@ -2530,7 +2530,7 @@ fn main() {
 
 This option can be used to simplify the management and bulk updates of the granular width configuration settings ([`fn_call_width`](#fn_call_width), [`attr_fn_like_width`](#attr_fn_like_width), [`struct_lit_width`](#struct_lit_width), [`struct_variant_width`](#struct_variant_width), [`array_width`](#array_width), [`chain_width`](#chain_width), [`single_line_if_else_max_width`](#single_line_if_else_max_width)), that respectively control when formatted constructs are multi-lined/vertical based on width.
 
-Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`. 
+Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`.
 
 - **Default value**: `"Default"`
 - **Possible values**: `"Default"`, `"Off"`, `"Max"`
@@ -2595,7 +2595,7 @@ fn main() {
 ```
 
 #### `Off`:
-When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics. 
+When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics.
 
 ```rust
 enum Lorem {
index 131f38dd06a2b74031117e4f692cf5edd3d86050..1b77dad11f0fe9b397de1f4ddc28f1452d4dd7a2 100644 (file)
@@ -38,7 +38,7 @@ colourised diff will be printed so that the offending line(s) can quickly be
 identified.
 
 Without explicit settings, the tests will be run using rustfmt's default
-configuration. It is possible to run a test using non-default settings in several 
+configuration. It is possible to run a test using non-default settings in several
 ways. Firstly, you can include configuration parameters in comments at the top
 of the file. For example: to use 3 spaces per tab, start your test with
 `// rustfmt-tab_spaces: 3`. Just remember that the comment is part of the input,
index 00a7652aee0dcb10286f7ea9de0cfedfc6335e6c..7a4dcf8773b61a85b7fc6fcc6dd08c9a91b55a00 100644 (file)
@@ -150,8 +150,8 @@ for its configuration.
 
 Our visitor keeps track of the desired current indent due to blocks (
 `block_indent`). Each `visit_*` method reformats code according to this indent,
-`config.comment_width()` and `config.max_width()`. Most reformatting that is done 
-in the `visit_*` methods is a bit hacky and is meant to be temporary until it can 
+`config.comment_width()` and `config.max_width()`. Most reformatting that is done
+in the `visit_*` methods is a bit hacky and is meant to be temporary until it can
 be done properly.
 
 There are a bunch of methods called `rewrite_*`. They do the bulk of the
index 7a97d31bab9c7ac70162cd1c066fa09ff14d2614..500a9f9a37c8cb58f4f718ae1a829a3a6a1b0f3e 100644 (file)
@@ -180,13 +180,13 @@ needs to be specified in `rustfmt.toml`, e.g., with `edition = "2018"`.
 
 * For things you do not want rustfmt to mangle, use `#[rustfmt::skip]`
 * To prevent rustfmt from formatting a macro or an attribute,
-  use `#[rustfmt::skip::macros(target_macro_name)]` or 
+  use `#[rustfmt::skip::macros(target_macro_name)]` or
   `#[rustfmt::skip::attributes(target_attribute_name)]`
 
   Example:
 
     ```rust
-    #![rustfmt::skip::attributes(custom_attribute)]   
+    #![rustfmt::skip::attributes(custom_attribute)]
 
     #[custom_attribute(formatting , here , should , be , Skipped)]
     #[rustfmt::skip::macros(html)]
index 13a3ecaa1961cd99188bd49f0a7e650fce36f752..0269e3ee4af931437a9e6c5d9c81bd172c1fb193 100755 (executable)
@@ -15,7 +15,7 @@ set -ex
 # it again.
 #
 #which cargo-fmt || cargo install --force
-CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force 
+CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force
 
 echo "Integration tests for: ${INTEGRATION}"
 cargo fmt -- --version
index 2a12da3881f0573ba2566453b9123239663ffe97..56d1917e2b61b211eb8ae3112f07e93ea1cdf0c9 100644 (file)
@@ -85,7 +85,7 @@
                 outputHtml() {
                   const ast = this.configurationDescriptions
                                   .filter(({ head, text, stable }) => {
-                                    
+
                                     if (
                                       text.includes(this.searchCondition) === false &&
                                       head.includes(this.searchCondition) === false
               },
               created: async function() {
                 const res = await axios.get(ConfigurationMdUrl);
-                const { 
+                const {
                   about,
                   configurationAbout,
                   configurationDescriptions
                   const lastIndex = stack.length - 1;
                   stack[lastIndex].push(next);
                   return stack;
-                }, 
+                },
                 [[]]);
               });
             }
                 configurationAbout, ...configurationDescriptions
               ] = configurations;
               configurationAbout.value.links = {};
-              
+
               return {
                 about,
                 configurationAbout: configurationAbout.value,
index 5597af9ee320cbe67ec82f37d6bb9a01ce073b3c..974c0c5990c7ddb38f015d1aae4ccccd35645a69 100644 (file)
@@ -1,7 +1,7 @@
 use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
-use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
 use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
 
 use crate::config::lists::*;
@@ -776,7 +776,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 );
                 let data = ast::VariantData::Struct(fields.clone(), recovered);
                 let variant = ast::Variant {
-                    attrs: vec![],
+                    attrs: AttrVec::new(),
                     id: self.id,
                     span: self.span,
                     vis: DEFAULT_VISIBILITY,
@@ -800,7 +800,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 );
                 let data = ast::VariantData::Struct(fields.clone(), recovered);
                 let variant = ast::Variant {
-                    attrs: vec![],
+                    attrs: AttrVec::new(),
                     id: self.id,
                     span: self.span,
                     vis: DEFAULT_VISIBILITY,