]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #86492 - hyd-dev:no-mangle-method, r=petrochenkov
authorbors <bors@rust-lang.org>
Fri, 13 Aug 2021 19:47:03 +0000 (19:47 +0000)
committerbors <bors@rust-lang.org>
Fri, 13 Aug 2021 19:47:03 +0000 (19:47 +0000)
Associated functions that contain extern indicator or have `#[rustc_std_internal_symbol]` are reachable

Previously these fails to link with ``undefined reference to `foo'``:

<details>
<summary>Example 1</summary>

```rs
struct AssocFn;

impl AssocFn {
    #[no_mangle]
    fn foo() {}
}

fn main() {
    extern "Rust" {
        fn foo();
    }
    unsafe { foo() }
}
```
([Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=f1244afcdd26e2a28445f6e82ca46b50))
</details>

<details>
<summary>Example 2</summary>

```rs
#![crate_name = "lib"]
#![crate_type = "lib"]

struct AssocFn;

impl AssocFn {
    #[no_mangle]
    fn foo() {}
}
```
```rs
extern crate lib;

fn main() {
    extern "Rust" {
        fn foo();
    }
    unsafe { foo() }
}
```
</details>

But I believe they should link successfully, because this works:
<details>

```rs
#[no_mangle]
fn foo() {}

fn main() {
    extern "Rust" {
        fn foo();
    }
    unsafe { foo() }
}
```
([Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=789b3f283ee6126f53939429103ed98d))
</details>

This PR fixes the problem, by adding associated functions that have "custom linkage" to `reachable_set`, just like normal functions.

I haven't tested whether #76211 and [Miri](https://github.com/rust-lang/miri/issues/1837) are fixed by this PR yet, but I'm submitting this anyway since this fixes the examples above.

I added a `run-pass` test that combines my two examples above, but I'm not sure if that's the right way to test this. Maybe I should add / modify an existing codegen test (`src/test/codegen/export-no-mangle.rs`?) instead?

245 files changed:
Cargo.lock
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/placeholders.rs
compiler/rustc_lexer/src/unescape.rs
compiler/rustc_lexer/src/unescape/tests.rs
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/non_fmt_panic.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
compiler/rustc_target/src/spec/armv7a_none_eabi.rs
compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
compiler/rustc_target/src/spec/armv7r_none_eabi.rs
compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/thumb_base.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/collect/type_of.rs
library/core/src/hint.rs
library/core/src/intrinsics.rs
library/core/src/iter/traits/collect.rs
library/core/src/iter/traits/iterator.rs
library/panic_unwind/src/lib.rs
library/std/Cargo.toml
library/std/build.rs
library/std/src/os/espidf/fs.rs [new file with mode: 0644]
library/std/src/os/espidf/mod.rs [new file with mode: 0644]
library/std/src/os/espidf/raw.rs [new file with mode: 0644]
library/std/src/os/mod.rs
library/std/src/os/unix/mod.rs
library/std/src/sys/common/alloc.rs
library/std/src/sys/unix/alloc.rs
library/std/src/sys/unix/args.rs
library/std/src/sys/unix/condvar.rs
library/std/src/sys/unix/env.rs
library/std/src/sys/unix/fd.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/mod.rs
library/std/src/sys/unix/net.rs
library/std/src/sys/unix/os.rs
library/std/src/sys/unix/process/mod.rs
library/std/src/sys/unix/process/process_unsupported.rs [new file with mode: 0644]
library/std/src/sys/unix/rand.rs
library/std/src/sys/unix/thread.rs
library/std/src/sys/unix/time.rs
library/std/src/sys/windows/process.rs
library/std/src/sys_common/io.rs
library/std/src/sys_common/process.rs
library/unwind/src/lib.rs
src/doc/book
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/rustc-dev-guide
src/doc/rustc/src/platform-support.md
src/etc/pre-commit.sh [changed mode: 0644->0755]
src/test/rustdoc-gui/headers-color.goml [new file with mode: 0644]
src/test/rustdoc-gui/search-result-colors.goml
src/test/ui/associated-types/defaults-cyclic-fail-1.stderr
src/test/ui/associated-types/defaults-cyclic-fail-2.stderr
src/test/ui/auxiliary/fancy-panic.rs
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs
src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs
src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr
src/test/ui/closures/2229_closure_analysis/migrations/macro.fixed [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/macro.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs
src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed
src/test/ui/closures/2229_closure_analysis/migrations/precise.rs
src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr
src/test/ui/command/command-create-pidfd.rs
src/test/ui/const-generics/min_const_generics/const-expression-suggest-missing-braces.stderr
src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr
src/test/ui/fmt/format-string-error-2.rs
src/test/ui/fmt/format-string-error-2.stderr
src/test/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr
src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr
src/test/ui/generic-associated-types/projection-bound-cycle.stderr
src/test/ui/issues/issue-21946.stderr
src/test/ui/issues/issue-23122-1.stderr
src/test/ui/issues/issue-23122-2.stderr
src/test/ui/issues/issue-86756.stderr
src/test/ui/iterators/into-iter-on-arrays-2018.stderr
src/test/ui/iterators/into-iter-on-arrays-lint.stderr
src/test/ui/layout/thumb-enum.rs [new file with mode: 0644]
src/test/ui/layout/thumb-enum.stderr [new file with mode: 0644]
src/test/ui/lint/bare-trait-objects-path.stderr
src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
src/test/ui/lint/force-warn/force-warn-cap-lints-allow.stderr
src/test/ui/lint/force-warn/force-warn-cap-lints-warn.stderr
src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
src/test/ui/lint/force-warn/force-warn-group.stderr
src/test/ui/lint/inclusive-range-pattern-syntax.stderr
src/test/ui/macros/macro-or-patterns-back-compat.stderr
src/test/ui/non-fmt-panic.rs
src/test/ui/non-fmt-panic.stderr
src/test/ui/parser/issue-68890-2.stderr
src/test/ui/parser/issue-73568-lifetime-after-mut.stderr
src/test/ui/parser/macro/trait-object-macro-matcher.stderr
src/test/ui/parser/recover-range-pats.stderr
src/test/ui/parser/trait-object-trait-parens.stderr
src/test/ui/range/range-inclusive-pattern-precedence.stderr
src/test/ui/range/range-inclusive-pattern-precedence2.stderr
src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr
src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr
src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr
src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr
src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
src/test/ui/rust-2021/future-prelude-collision-generic.stderr
src/test/ui/rust-2021/future-prelude-collision-imported.stderr
src/test/ui/rust-2021/future-prelude-collision.stderr
src/test/ui/rust-2021/generic-type-collision.stderr
src/test/ui/rust-2021/inherent-dyn-collision.stderr
src/test/ui/rust-2021/reserved-prefixes-migration.stderr
src/test/ui/sanitize/memory.rs
src/test/ui/specialization/issue-51892.stderr
src/test/ui/str/str-escape.rs [new file with mode: 0644]
src/test/ui/str/str-escape.stderr [new file with mode: 0644]
src/test/ui/suggestions/for-i-in-vec.fixed
src/test/ui/suggestions/for-i-in-vec.rs
src/test/ui/suggestions/for-i-in-vec.stderr
src/test/ui/suggestions/issue-61963.stderr
src/test/ui/traits/bound/not-on-bare-trait.stderr
src/test/ui/wf/hir-wf-check-erase-regions.stderr
src/test/ui/wf/wf-impl-associated-type-region.stderr
src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
src/test/ui/wf/wf-trait-associated-type-region.stderr
src/tools/cargo
src/tools/clippy/.github/ISSUE_TEMPLATE/new_lint.md
src/tools/clippy/.github/workflows/clippy.yml
src/tools/clippy/.github/workflows/clippy_bors.yml
src/tools/clippy/.github/workflows/remark.yml
src/tools/clippy/CHANGELOG.md
src/tools/clippy/clippy_lints/src/as_conversions.rs
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/else_if_without_else.rs
src/tools/clippy/clippy_lints/src/functions/mod.rs
src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
src/tools/clippy/clippy_lints/src/if_not_else.rs
src/tools/clippy/clippy_lints/src/items_after_statements.rs
src/tools/clippy/clippy_lints/src/len_zero.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/literal_representation.rs
src/tools/clippy/clippy_lints/src/loops/never_loop.rs
src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
src/tools/clippy/clippy_lints/src/methods/extend_with_drain.rs
src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/misc_early/mod.rs
src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
src/tools/clippy/clippy_lints/src/needless_borrow.rs
src/tools/clippy/clippy_lints/src/needless_continue.rs
src/tools/clippy/clippy_lints/src/needless_for_each.rs
src/tools/clippy/clippy_lints/src/no_effect.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
src/tools/clippy/clippy_lints/src/reference.rs
src/tools/clippy/clippy_lints/src/swap.rs
src/tools/clippy/clippy_lints/src/types/mod.rs
src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
src/tools/clippy/clippy_lints/src/unused_unit.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
src/tools/clippy/clippy_utils/src/diagnostics.rs
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/source.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/clippy/doc/basics.md
src/tools/clippy/rust-toolchain
src/tools/clippy/tests/auxiliary/test_macro.rs [deleted file]
src/tools/clippy/tests/ui-toml/functions_maxlines/test.rs
src/tools/clippy/tests/ui-toml/functions_maxlines/test.stderr
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr
src/tools/clippy/tests/ui/auxiliary/test_macro.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/crashes/ice-3969.stderr
src/tools/clippy/tests/ui/extend_with_drain.fixed
src/tools/clippy/tests/ui/extend_with_drain.rs
src/tools/clippy/tests/ui/extend_with_drain.stderr
src/tools/clippy/tests/ui/implicit_hasher.rs
src/tools/clippy/tests/ui/map_flatten.fixed
src/tools/clippy/tests/ui/map_flatten.rs
src/tools/clippy/tests/ui/map_flatten.stderr
src/tools/clippy/tests/ui/never_loop.stderr
src/tools/clippy/tests/ui/no_effect.stderr
src/tools/clippy/tests/ui/or_fun_call.fixed
src/tools/clippy/tests/ui/or_fun_call.rs
src/tools/clippy/tests/ui/or_fun_call.stderr
src/tools/clippy/tests/ui/similar_names.rs
src/tools/clippy/tests/ui/similar_names.stderr
src/tools/clippy/tests/ui/swap.fixed
src/tools/clippy/tests/ui/swap.rs
src/tools/clippy/tests/ui/swap.stderr
src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
src/tools/clippy/tests/ui/unwrap_or_else_default.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/unwrap_or_else_default.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/unwrap_or_else_default.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/while_let_on_iterator.fixed
src/tools/clippy/tests/ui/while_let_on_iterator.rs
src/tools/clippy/tests/ui/while_let_on_iterator.stderr
src/tools/rust-analyzer
src/tools/rustdoc-js/tester.js

index 5253c819ca2c93ac4505afae60554cb8ce693405..940608975c5ecd3d4a15412339a85a3869e75bcf 100644 (file)
@@ -356,7 +356,7 @@ dependencies = [
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.1"
+version = "0.1.2"
 dependencies = [
  "serde",
 ]
@@ -1723,9 +1723,9 @@ checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
 
 [[package]]
 name = "jobserver"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"
+checksum = "f5ca711fd837261e14ec9e674f092cbb931d3fa1482b017ae59328ddc6f3212b"
 dependencies = [
  "libc",
 ]
@@ -1880,9 +1880,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.98"
+version = "0.2.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
+checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
 dependencies = [
  "rustc-std-workspace-core",
 ]
index 86698460747494f7a95711fe58bfada5da0a34e0..1c4d307fc50e14c4281b5bd487b83137e7342a33 100644 (file)
@@ -1136,6 +1136,11 @@ fn type_by_size(size: Size) -> Option<Type> {
                 };
             ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
         };
+
+        black_box, (c a) {
+            // FIXME implement black_box semantics
+            ret.write_cvalue(fx, a);
+        };
     }
 
     if let Some((_, dest)) = destination {
index ebc3773df57cd7fd84b1bbce79876ce3142a64b2..4790b44bd19ef0c3672ea3a9367dafee8a9efe6d 100644 (file)
@@ -425,7 +425,7 @@ fn codegen_global_asm(
     }
 }
 
-fn inline_asm_call(
+pub(crate) fn inline_asm_call(
     bx: &mut Builder<'a, 'll, 'tcx>,
     asm: &str,
     cons: &str,
index ed4841858651749e613e83abc9516bf496ab7d42..fe2ed21c1e3b02287533cb5237b9a19ce2c294e8 100644 (file)
@@ -7,6 +7,7 @@
 use crate::va_arg::emit_va_arg;
 use crate::value::Value;
 
+use rustc_ast as ast;
 use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
 use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
@@ -327,6 +328,31 @@ fn codegen_intrinsic_call(
                 }
             }
 
+            sym::black_box => {
+                args[0].val.store(self, result);
+
+                // We need to "use" the argument in some way LLVM can't introspect, and on
+                // targets that support it we can typically leverage inline assembly to do
+                // this. LLVM's interpretation of inline assembly is that it's, well, a black
+                // box. This isn't the greatest implementation since it probably deoptimizes
+                // more than we want, but it's so far good enough.
+                crate::asm::inline_asm_call(
+                    self,
+                    "",
+                    "r,~{memory}",
+                    &[result.llval],
+                    self.type_void(),
+                    true,
+                    false,
+                    ast::LlvmAsmDialect::Att,
+                    &[span],
+                )
+                .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
+
+                // We have copied the value to `result` already.
+                return;
+            }
+
             _ if name_str.starts_with("simd_") => {
                 match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
                     Ok(llval) => llval,
index 84dd69ebd963496696d0ed03e9d7d5bc1d4a40b5..fcc70b2e4c5ff3e600993e2f82e5ea8cb053858e 100644 (file)
@@ -1287,9 +1287,6 @@ pub fn init_env_logger(env: &str) {
         .with_indent_lines(true)
         .with_ansi(color_logs)
         .with_targets(true)
-        .with_wraparound(10)
-        .with_verbose_exit(true)
-        .with_verbose_entry(true)
         .with_indent_amount(2);
     #[cfg(parallel_compiler)]
     let layer = layer.with_thread_ids(true).with_thread_names(true);
index 3629e668fa9f8989b4637058d1fe8b3463ea1b81..09beda33483745b0c85d7b120a1265dde17a76e3 100644 (file)
@@ -559,7 +559,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
         self.cx.force_mode = orig_force_mode;
 
         // Finally incorporate all the expanded macros into the input AST fragment.
-        let mut placeholder_expander = PlaceholderExpander::default();
+        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
         while let Some(expanded_fragments) = expanded_fragments.pop() {
             for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
                 placeholder_expander
@@ -1341,9 +1341,14 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
             }
         }
 
+        // The placeholder expander gives ids to statements, so we avoid folding the id here.
         // We don't use `assign_id!` - it will be called when we visit statement's contents
         // (e.g. an expression, item, or local)
-        let res = noop_flat_map_stmt(stmt, self);
+        let ast::Stmt { id, kind, span } = stmt;
+        let res = noop_flat_map_stmt_kind(kind, self)
+            .into_iter()
+            .map(|kind| ast::Stmt { id, kind, span })
+            .collect();
 
         self.cx.current_expansion.is_trailing_mac = false;
         res
index 43287984050d4726f7ceb7f1200551757576dc64..efed41de23a89ebf23b7f0c86841db93167d20f5 100644 (file)
@@ -7,7 +7,6 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
 #![feature(try_blocks)]
-#![recursion_limit = "256"]
 
 #[macro_use]
 extern crate rustc_macros;
index 8e78fcbb8dbc14a40110def4bda0c03506a63947..6586ba138fb9956c61baf25f0eb13edd301cdbd5 100644 (file)
@@ -1,3 +1,4 @@
+use crate::base::ExtCtxt;
 use crate::expand::{AstFragment, AstFragmentKind};
 
 use rustc_ast as ast;
@@ -174,12 +175,17 @@ fn mac_placeholder() -> ast::MacCall {
     }
 }
 
-#[derive(Default)]
-pub struct PlaceholderExpander {
+pub struct PlaceholderExpander<'a, 'b> {
     expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
+    cx: &'a mut ExtCtxt<'b>,
+    monotonic: bool,
 }
 
-impl PlaceholderExpander {
+impl<'a, 'b> PlaceholderExpander<'a, 'b> {
+    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
+        PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
+    }
+
     pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
         fragment.mut_visit_with(self);
         self.expanded_fragments.insert(id, fragment);
@@ -190,7 +196,7 @@ fn remove(&mut self, id: ast::NodeId) -> AstFragment {
     }
 }
 
-impl MutVisitor for PlaceholderExpander {
+impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
         if arm.is_placeholder {
             self.remove(arm.id).make_arms()
@@ -354,4 +360,15 @@ fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
             _ => noop_visit_ty(ty, self),
         }
     }
+
+    fn visit_block(&mut self, block: &mut P<ast::Block>) {
+        noop_visit_block(block, self);
+
+        for stmt in block.stmts.iter_mut() {
+            if self.monotonic {
+                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
+                stmt.id = self.cx.resolver.next_node_id();
+            }
+        }
+    }
 }
index 9a96c03cd3c8086806ebcfd1ea3ee3f47395e6d1..b970c9e4911fafb36ff0612c0e30fb417d46437f 100644 (file)
@@ -60,6 +60,9 @@ pub enum EscapeError {
     /// After a line ending with '\', the next line contains whitespace
     /// characters that are not skipped.
     UnskippedWhitespaceWarning,
+
+    /// After a line ending with '\', multiple lines are skipped.
+    MultipleSkippedLinesWarning,
 }
 
 impl EscapeError {
@@ -67,6 +70,7 @@ impl EscapeError {
     pub fn is_fatal(&self) -> bool {
         match self {
             EscapeError::UnskippedWhitespaceWarning => false,
+            EscapeError::MultipleSkippedLinesWarning => false,
             _ => true,
         }
     }
@@ -315,12 +319,17 @@ fn skip_ascii_whitespace<F>(chars: &mut Chars<'_>, start: usize, callback: &mut
     where
         F: FnMut(Range<usize>, Result<char, EscapeError>),
     {
-        let str = chars.as_str();
-        let first_non_space = str
+        let tail = chars.as_str();
+        let first_non_space = tail
             .bytes()
             .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
-            .unwrap_or(str.len());
-        let tail = &str[first_non_space..];
+            .unwrap_or(tail.len());
+        if tail[1..first_non_space].contains('\n') {
+            // The +1 accounts for the escaping slash.
+            let end = start + first_non_space + 1;
+            callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning));
+        }
+        let tail = &tail[first_non_space..];
         if let Some(c) = tail.chars().nth(0) {
             // For error reporting, we would like the span to contain the character that was not
             // skipped.  The +1 is necessary to account for the leading \ that started the escape.
index 1f4dbb20f4e9896e292e44e3208146c8ab23830e..fa61554afde6c5d16c87b462e0ca802b15a7e0a7 100644 (file)
@@ -106,6 +106,10 @@ fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)])
         assert_eq!(unescaped, expected);
     }
 
+    // Check we can handle escaped newlines at the end of a file.
+    check("\\\n", &[]);
+    check("\\\n ", &[]);
+
     check(
         "\\\n \u{a0} x",
         &[
@@ -115,6 +119,7 @@ fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)])
             (6..7, Ok('x')),
         ],
     );
+    check("\\\n  \n  x", &[(0..7, Err(EscapeError::MultipleSkippedLinesWarning)), (7..8, Ok('x'))]);
 }
 
 #[test]
index 77741c7240b0d100ae1749094dbdd9e780a67f90..21fad5f9af683fb20f1c4ae70b4d4288966a941b 100644 (file)
@@ -32,7 +32,7 @@
     Warn,
     "detects calling `into_iter` on arrays in Rust 2015 and 2018",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #66145 <https://github.com/rust-lang/rust/issues/66145>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>",
         reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
     };
 }
index 5bd48a54383cf0cde767c20d3a1c726dec47f690..77c7040e6a76dafed5533b200ffd359ddb2542cf 100644 (file)
@@ -1722,7 +1722,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
     Warn,
     "`...` range patterns are deprecated",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>",
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
index a32caf1bc433df1cbf94ffa4f3d7322f2ff43ed5..ec53625f10525014264c53f0dc895ec7c858aa19 100644 (file)
@@ -2,6 +2,7 @@
 use rustc_ast as ast;
 use rustc_errors::{pluralize, Applicability};
 use rustc_hir as hir;
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_parse_format::{ParseMode, Parser, Piece};
 use rustc_session::lint::FutureIncompatibilityReason;
@@ -75,6 +76,11 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
 
     let (span, panic, symbol_str) = panic_call(cx, f);
 
+    if in_external_macro(cx.sess(), span) {
+        // Nothing that can be done about it in the current crate.
+        return;
+    }
+
     // Find the span of the argument to `panic!()`, before expansion in the
     // case of `panic!(some_macro!())`.
     // We don't use source_callsite(), because this `panic!(..)` might itself
@@ -152,6 +158,13 @@ fn check_panic_str<'tcx>(
         return;
     }
 
+    let (span, _, _) = panic_call(cx, f);
+
+    if in_external_macro(cx.sess(), span) && in_external_macro(cx.sess(), arg.span) {
+        // Nothing that can be done about it in the current crate.
+        return;
+    }
+
     let fmt_span = arg.span.source_callsite();
 
     let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
@@ -167,8 +180,6 @@ fn check_panic_str<'tcx>(
         Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
     let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
 
-    let (span, _, _) = panic_call(cx, f);
-
     if n_arguments > 0 && fmt_parser.errors.is_empty() {
         let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
             [] => vec![fmt_span],
index 1998386603f12df543a4541f73f1f9ffae43d337..9ea17e0ccb61389375ec8422c6d3656f4188ee13 100644 (file)
     Warn,
     "suggest using `dyn Trait` for trait objects",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>",
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
     Allow,
     "detects usage of old versions of or-patterns",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #84869 <https://github.com/rust-lang/rust/issues/84869>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>",
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
     "detects the usage of trait methods which are ambiguous with traits added to the \
         prelude in future editions",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #85684 <https://github.com/rust-lang/rust/issues/85684>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>",
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
 }
     Allow,
     "identifiers that will be parsed as a prefix in Rust 2021",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #84978 <https://github.com/rust-lang/rust/issues/84978>",
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>",
         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
     };
     crate_level_only
index 3bdd91d2136093af3fa003d7323a96d7e1c996c0..ef0392e51970b27f96a16cdc942036e880811930 100644 (file)
@@ -32,7 +32,6 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
-use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -46,7 +45,6 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::OpaqueTypeKey;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
@@ -477,7 +475,7 @@ pub struct TypeckResults<'tcx> {
 
     /// All the opaque types that are restricted to concrete types
     /// by this function.
-    pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+    pub concrete_opaque_types: FxHashSet<DefId>,
 
     /// Tracks the minimum captures required for a closure;
     /// see `MinCaptureInformationMap` for more details.
index 423f3faf21ffff66887fb65e80319af6d0e50533..3caca313ffddd9de044f12345c5ee3ca5c636083 100644 (file)
@@ -112,9 +112,6 @@ fn repr_discr<'tcx>(
         let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
         let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
 
-        let mut min_from_extern = None;
-        let min_default = I8;
-
         if let Some(ity) = repr.int {
             let discr = Integer::from_attr(&tcx, ity);
             let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
@@ -128,19 +125,14 @@ fn repr_discr<'tcx>(
             return (discr, ity.is_signed());
         }
 
-        if repr.c() {
-            match &tcx.sess.target.arch[..] {
-                "hexagon" => min_from_extern = Some(I8),
-                // WARNING: the ARM EABI has two variants; the one corresponding
-                // to `at_least == I32` appears to be used on Linux and NetBSD,
-                // but some systems may use the variant corresponding to no
-                // lower bound. However, we don't run on those yet...?
-                "arm" => min_from_extern = Some(I32),
-                _ => min_from_extern = Some(I32),
-            }
-        }
-
-        let at_least = min_from_extern.unwrap_or(min_default);
+        let at_least = if repr.c() {
+            // This is usually I32, however it can be different on some platforms,
+            // notably hexagon and arm-none/thumb-none
+            tcx.data_layout().c_enum_min_size
+        } else {
+            // repr(Rust) enums try to be as small as possible
+            I8
+        };
 
         // If there are no negative values, we can use the unsigned fit.
         if min >= 0 {
index 2be23159bf563a5938e0fd70fa54eaa10ea0c556..66e06325fa982df6d564fa048a2284c2a10343c3 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::source_map::DesugaringKind;
@@ -409,13 +410,17 @@ fn report_cannot_move_from_borrowed_content(
             );
         } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
             let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
-                Some(def_id) => type_known_to_meet_bound_modulo_regions(
-                    &self.infcx,
-                    self.param_env,
-                    self.infcx.tcx.mk_imm_ref(self.infcx.tcx.lifetimes.re_erased, ty),
-                    def_id,
-                    DUMMY_SP,
-                ),
+                Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+                    type_known_to_meet_bound_modulo_regions(
+                        &infcx,
+                        self.param_env,
+                        infcx
+                            .tcx
+                            .mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
+                        def_id,
+                        DUMMY_SP,
+                    )
+                }),
                 _ => false,
             };
             if suggest {
index dc1f9053b61f028fe968a3c1b31928e657a61481..bfab886b6ee4f9fd2ab9c40b62099c287170884f 100644 (file)
@@ -465,7 +465,7 @@ pub fn emulate_intrinsic(
                 );
                 self.copy_op(&self.operand_index(&args[0], index)?, dest)?;
             }
-            sym::likely | sym::unlikely => {
+            sym::likely | sym::unlikely | sym::black_box => {
                 // These just return their argument
                 self.copy_op(&args[0], dest)?;
             }
index 4e95cdc0efa5f30c83392dc47498ca379b5d6d4d..aa6b424ce2b57ec167c85c7086471cc3165d62ec 100644 (file)
@@ -280,6 +280,11 @@ pub(crate) fn emit_unescape_error(
                 format!("non-ASCII whitespace symbol '{}' is not skipped", c.escape_unicode());
             handler.struct_span_warn(span, &msg).span_label(char_span, &msg).emit();
         }
+        EscapeError::MultipleSkippedLinesWarning => {
+            let msg = "multiple lines skipped by escaped newline";
+            let bottom_msg = "skipping everything up to and including this point";
+            handler.struct_span_warn(span, msg).span_label(span, bottom_msg).emit();
+        }
     }
 }
 
index 3f5d8273b38b8829bf5b216fc9ad2f1943465f88..6d03f1a37329e0d50fdfe9e41e40e058e484f905 100644 (file)
         bitreverse,
         bitxor,
         bitxor_assign,
+        black_box,
         block,
         bool,
         borrowck_graphviz_format,
index 9a24edf1a42cb25f24f6c5eed27356f49f4ef157..8ef6e142caecfe02745d6a58cdddce78fd852af6 100644 (file)
@@ -36,6 +36,9 @@ pub struct TargetDataLayout {
     pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
 
     pub instruction_address_space: AddressSpace,
+
+    /// Minimum size of #[repr(C)] enums (default I32 bits)
+    pub c_enum_min_size: Integer,
 }
 
 impl Default for TargetDataLayout {
@@ -60,6 +63,7 @@ fn default() -> TargetDataLayout {
                 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
             ],
             instruction_address_space: AddressSpace::DATA,
+            c_enum_min_size: Integer::I32,
         }
     }
 }
@@ -173,6 +177,8 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
             ));
         }
 
+        dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?;
+
         Ok(dl)
     }
 
@@ -610,6 +616,17 @@ pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
         }
         I8
     }
+
+    fn from_size(size: Size) -> Result<Self, String> {
+        match size.bits() {
+            8 => Ok(Integer::I8),
+            16 => Ok(Integer::I16),
+            32 => Ok(Integer::I32),
+            64 => Ok(Integer::I64),
+            128 => Ok(Integer::I128),
+            _ => Err(format!("rust does not support integers with {} bits", size.bits())),
+        }
+    }
 }
 
 /// Fundamental unit of memory access and layout.
index c98a12cfc4977f7d392340ad3543193e49fac5c0..ed4779c0c023210a112ffd5fa61392f875db0db6 100644 (file)
@@ -20,6 +20,8 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
index 292635403fbd476c9d4bc12eb214a960b4fed986..b60e2895d7727db2863ac5638ca4c872f1609239 100644 (file)
@@ -21,6 +21,8 @@ pub fn target() -> Target {
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
index 8bff60e9ed99a64f5f4ca87f7558ac4222441b8c..88040f49d9e4e926dfd4cce8cb4776f64427d87b 100644 (file)
@@ -28,6 +28,7 @@ pub fn target() -> Target {
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
+        c_enum_min_bits: 8,
         ..Default::default()
     };
     Target {
index ea2751e375e0b6078145c92c34fff2e1372d50d9..af324843cede5c7090c01279be7fef673308a1c7 100644 (file)
@@ -19,6 +19,8 @@ pub fn target() -> Target {
         max_atomic_width: Some(64),
         panic_strategy: PanicStrategy::Abort,
         emit_debug_gdb_scripts: false,
+        // GCC and Clang default to 8 for arm-none here
+        c_enum_min_bits: 8,
         ..Default::default()
     };
     Target {
index c695542805599b00a40a63f02a2e157c6043b8f3..c0e970983e70484470aceaeb49af0142128c9385 100644 (file)
@@ -19,6 +19,8 @@ pub fn target() -> Target {
             panic_strategy: PanicStrategy::Abort,
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
index 50c37021b74e9b9b93529e15e656999741d5080f..b126887b27b33f946dded05057718f7945e61f47 100644 (file)
@@ -20,6 +20,8 @@ pub fn target() -> Target {
             features: "+vfp3,-d32,-fp16".to_string(),
             max_atomic_width: Some(32),
             emit_debug_gdb_scripts: false,
+            // GCC and Clang default to 8 for arm-none here
+            c_enum_min_bits: 8,
             ..Default::default()
         },
     }
index e0097ee220a464c39d189c48c7009db094831519..27d306c41b79550f462224fbd7d32e44909f936c 100644 (file)
@@ -13,6 +13,8 @@ pub fn target() -> Target {
     base.dynamic_linking = true;
     base.executables = true;
 
+    base.c_enum_min_bits = 8;
+
     Target {
         llvm_target: "hexagon-unknown-linux-musl".to_string(),
         pointer_width: 32,
index 9c957cba6cc098b4073aefa67a5f9b8732bbda43..911956859b8619b263b1e1c252627642bea512bd 100644 (file)
@@ -903,6 +903,7 @@ fn $module() {
 
     ("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
     ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
+    ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
     ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
     ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
     ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
@@ -1335,6 +1336,9 @@ pub struct TargetOptions {
 
     /// If present it's a default value to use for adjusting the C ABI.
     pub default_adjusted_cabi: Option<Abi>,
+
+    /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
+    pub c_enum_min_bits: u64,
 }
 
 impl Default for TargetOptions {
@@ -1439,6 +1443,7 @@ fn default() -> TargetOptions {
             split_debuginfo: SplitDebuginfo::Off,
             supported_sanitizers: SanitizerSet::empty(),
             default_adjusted_cabi: None,
+            c_enum_min_bits: 32,
         }
     }
 }
@@ -1603,6 +1608,12 @@ macro_rules! key {
                     base.$key_name = s;
                 }
             } );
+            ($key_name:ident, u64) => ( {
+                let name = (stringify!($key_name)).replace("_", "-");
+                if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
+                    base.$key_name = s;
+                }
+            } );
             ($key_name:ident, Option<u32>) => ( {
                 let name = (stringify!($key_name)).replace("_", "-");
                 if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
@@ -2016,6 +2027,7 @@ macro_rules! key {
         key!(split_debuginfo, SplitDebuginfo)?;
         key!(supported_sanitizers, SanitizerSet)?;
         key!(default_adjusted_cabi, Option<Abi>)?;
+        key!(c_enum_min_bits, u64);
 
         if base.is_builtin {
             // This can cause unfortunate ICEs later down the line.
@@ -2254,6 +2266,7 @@ macro_rules! target_option_val {
         target_option_val!(has_thumb_interworking);
         target_option_val!(split_debuginfo);
         target_option_val!(supported_sanitizers);
+        target_option_val!(c_enum_min_bits);
 
         if let Some(abi) = self.default_adjusted_cabi {
             d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
new file mode 100644 (file)
index 0000000..fb084af
--- /dev/null
@@ -0,0 +1,37 @@
+use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        pointer_width: 32,
+        arch: "riscv32".to_string(),
+
+        options: TargetOptions {
+            families: vec!["unix".to_string()],
+            os: "espidf".to_string(),
+            env: "newlib".to_string(),
+            vendor: "espressif".to_string(),
+            linker_flavor: LinkerFlavor::Gcc,
+            linker: Some("riscv32-esp-elf-gcc".to_string()),
+            cpu: "generic-rv32".to_string(),
+
+            // While the RiscV32IMC architecture does not natively support atomics, ESP-IDF does support
+            // the __atomic* and __sync* GCC builtins, so setting `max_atomic_width` to `Some(32)`
+            // and `atomic_cas` to `true` will cause the compiler to emit libcalls to these builtins.
+            //
+            // Support for atomics is necessary for the Rust STD library, which is supported by the ESP-IDF framework.
+            max_atomic_width: Some(32),
+            atomic_cas: true,
+
+            features: "+m,+c".to_string(),
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: RelocModel::Static,
+            emit_debug_gdb_scripts: false,
+            eh_frame_header: false,
+            ..Default::default()
+        },
+    }
+}
index bac1203980eb010720829fe3570be0bcb8a20497..e2e528561e79719c9a78f8d29b26c394fa0ba584 100644 (file)
@@ -53,6 +53,9 @@ pub fn opts() -> TargetOptions {
         // LLVM is eager to trash the link register when calling `noreturn` functions, which
         // breaks debugging. Preserve LR by default to prevent that from happening.
         frame_pointer: FramePointer::Always,
+        // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
+        // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
+        c_enum_min_bits: 8,
         ..Default::default()
     }
 }
index 6661df21ed952cef4b2748a90e4748d75a6fd491..664954b0eb7a229673d8ad715b1545689f8a48b3 100644 (file)
@@ -102,6 +102,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
         | sym::maxnumf64
         | sym::type_name
         | sym::forget
+        | sym::black_box
         | sym::variant_count => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     }
@@ -387,6 +388,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
 
+            sym::black_box => (1, vec![param(0)], param(0)),
+
             other => {
                 tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
                 return;
index 013cb2a49b29c145d07145fcb9a0e4aa1d999e5c..46f360075c09d7d6a195933ceab3743bbbd75413 100644 (file)
@@ -47,7 +47,7 @@
 };
 use rustc_session::lint;
 use rustc_span::sym;
-use rustc_span::{MultiSpan, Span, Symbol};
+use rustc_span::{MultiSpan, Span, Symbol, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 use rustc_data_structures::stable_map::FxHashMap;
@@ -611,7 +611,7 @@ fn perform_2229_migration_anaysis(
                         for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
                             if let Some(captured_hir_id) = captured_hir_id {
                                 let cause_span = self.tcx.hir().span(*captured_hir_id);
-                                diagnostics_builder.span_label(cause_span, format!("in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`",
+                                diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
                                     self.tcx.hir().name(*var_hir_id),
                                     captured_name,
                                 ));
@@ -622,7 +622,7 @@ fn perform_2229_migration_anaysis(
                             if reasons.contains("drop order") {
                                 let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
 
-                                diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only `{}` would be dropped here alongside the closure",
+                                diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
                                     self.tcx.hir().name(*var_hir_id),
                                     captured_name,
                                 ));
@@ -632,7 +632,7 @@ fn perform_2229_migration_anaysis(
                             if reasons.contains("trait implementation") {
                                 let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
 
-                                diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure would no longer implement {} as `{}` does not implement {}",
+                                diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}",
                                     missing_trait,
                                     self.tcx.hir().name(*var_hir_id),
                                     missing_trait,
@@ -644,22 +644,41 @@ fn perform_2229_migration_anaysis(
                         }
                     }
                     diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
-                    let closure_body_span = self.tcx.hir().span(body_id.hir_id);
-                    let (sugg, app) =
+
+                    let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
+
+                    // If the body was entirely expanded from a macro
+                    // invocation, i.e. the body is not contained inside the
+                    // closure span, then we walk up the expansion until we
+                    // find the span before the expansion.
+                    while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
+                        closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
+                    }
+
+                    let (span, sugg, app) =
                         match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
                             Ok(s) => {
                                 let trimmed = s.trim_start();
+                                let mut lines = trimmed.lines();
+                                let line1 = lines.next().unwrap_or_default();
 
                                 // If the closure contains a block then replace the opening brace
                                 // with "{ let _ = (..); "
-                                let sugg = if let Some('{') = trimmed.chars().next() {
-                                    format!("{{ {}; {}", migration_string, &trimmed[1..])
+                                let sugg = if line1.trim_end() == "{" {
+                                    // This is a multi-line closure with just a `{` on the first line,
+                                    // so we put the `let` on its own line.
+                                    // We take the indentation from the next non-empty line.
+                                    let line2 = lines.filter(|line| !line.is_empty()).next().unwrap_or_default();
+                                    let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
+                                    format!("{{\n{}{};{}", indent, migration_string, &trimmed[line1.len()..])
+                                } else if line1.starts_with('{') {
+                                    format!("{{ {}; {}", migration_string, &trimmed[1..].trim_start())
                                 } else {
                                     format!("{{ {}; {} }}", migration_string, s)
                                 };
-                                (sugg, Applicability::MachineApplicable)
+                                (closure_body_span, sugg, Applicability::MachineApplicable)
                             }
-                            Err(_) => (migration_string.clone(), Applicability::HasPlaceholders),
+                            Err(_) => (closure_span, migration_string.clone(), Applicability::HasPlaceholders),
                         };
 
                     let diagnostic_msg = format!(
@@ -668,7 +687,7 @@ fn perform_2229_migration_anaysis(
                     );
 
                     diagnostics_builder.span_suggestion(
-                        closure_body_span,
+                        span,
                         &diagnostic_msg,
                         sugg,
                         app,
index e33cc603b5e543cc95cd8b3699642cb2ec2761e4..b82437096592807b823b2f966ca3cf1bf80cb7da 100644 (file)
@@ -194,12 +194,13 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let trait_item = tcx.hir().expect_trait_item(hir_id);
 
-    let method_sig = match trait_item.kind {
-        hir::TraitItemKind::Fn(ref sig, _) => Some(sig),
-        _ => None,
+    let (method_sig, span) = match trait_item.kind {
+        hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
+        hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
+        _ => (None, trait_item.span),
     };
     check_object_unsafe_self_trait_by_name(tcx, &trait_item);
-    check_associated_item(tcx, trait_item.hir_id(), trait_item.span, method_sig);
+    check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
 }
 
 fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
@@ -268,12 +269,13 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let impl_item = tcx.hir().expect_impl_item(hir_id);
 
-    let method_sig = match impl_item.kind {
-        hir::ImplItemKind::Fn(ref sig, _) => Some(sig),
-        _ => None,
+    let (method_sig, span) = match impl_item.kind {
+        hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
+        hir::ImplItemKind::TyAlias(ty) => (None, ty.span),
+        _ => (None, impl_item.span),
     };
 
-    check_associated_item(tcx, impl_item.hir_id(), impl_item.span, method_sig);
+    check_associated_item(tcx, impl_item.hir_id(), span, method_sig);
 }
 
 fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
index 959ab69a679eb1d6075b02f1f42a2daf021679e1..a13157b460828a809cf7a251dbde2164bf729a8a 100644 (file)
@@ -552,23 +552,7 @@ fn visit_opaque_types(&mut self, span: Span) {
             // in some other location, or we'll end up emitting an error due
             // to the lack of defining usage
             if !skip_add {
-                let old_concrete_ty = self
-                    .typeck_results
-                    .concrete_opaque_types
-                    .insert(opaque_type_key, definition_ty);
-                if let Some(old_concrete_ty) = old_concrete_ty {
-                    if old_concrete_ty != definition_ty {
-                        span_bug!(
-                            span,
-                            "`visit_opaque_types` tried to write different types for the same \
-                                 opaque type: {:?}, {:?}, {:?}, {:?}",
-                            opaque_type_key.def_id,
-                            definition_ty,
-                            opaque_defn,
-                            old_concrete_ty,
-                        );
-                    }
-                }
+                self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id);
             }
         }
     }
index b9483d6f987602c665b5867facaccbd1b12851e8..e63c3346e02b1dfc5a4a2f3ae53e8f45cb6f9286 100644 (file)
@@ -540,13 +540,7 @@ fn check(&mut self, def_id: LocalDefId) {
             }
             // Calling `mir_borrowck` can lead to cycle errors through
             // const-checking, avoid calling it if we don't have to.
-            if self
-                .tcx
-                .typeck(def_id)
-                .concrete_opaque_types
-                .any_value_matching(|(key, _)| key.def_id == self.def_id)
-                .is_none()
-            {
+            if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
                 debug!("no constraints in typeck results");
                 return;
             }
index a0b65399da2c5444d4db3eaa7ac0a9f3b8687ef6..a4924554919b07217af17ae101ad38e555aa32f4 100644 (file)
@@ -152,23 +152,19 @@ pub fn spin_loop() {
 /// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
 ///
 /// [`std::convert::identity`]: crate::convert::identity
-#[cfg_attr(not(miri), inline)]
-#[cfg_attr(miri, inline(never))]
+#[inline]
 #[unstable(feature = "bench_black_box", issue = "64102")]
-#[cfg_attr(miri, allow(unused_mut))]
+#[cfg_attr(not(bootstrap), allow(unused_mut))]
 pub fn black_box<T>(mut dummy: T) -> T {
-    // We need to "use" the argument in some way LLVM can't introspect, and on
-    // targets that support it we can typically leverage inline assembly to do
-    // this. LLVM's interpretation of inline assembly is that it's, well, a black
-    // box. This isn't the greatest implementation since it probably deoptimizes
-    // more than we want, but it's so far good enough.
-
-    #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
+    #[cfg(bootstrap)]
     // SAFETY: the inline assembly is a no-op.
     unsafe {
-        // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
         llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+        dummy
     }
 
-    dummy
+    #[cfg(not(bootstrap))]
+    {
+        crate::intrinsics::black_box(dummy)
+    }
 }
index d15ac89668fa397c5ce123daa2cda8a4ee3c5ae4..272b1e3a1d75ee9549fc9903a36aba90c284b339 100644 (file)
@@ -1933,6 +1933,12 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     /// which is UB if any of their inputs are `undef`.)
     #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
     pub fn raw_eq<T>(a: &T, b: &T) -> bool;
+
+    /// See documentation of [`std::hint::black_box`] for details.
+    ///
+    /// [`std::hint::black_box`]: crate::hint::black_box
+    #[cfg(not(bootstrap))]
+    pub fn black_box<T>(dummy: T) -> T;
 }
 
 // Some functions are defined here because they accidentally got made
index 7f87ead6feed6c132faec40398c48dc1912591e6..aa91346851f9dc83aa003def0a3949ad412b215d 100644 (file)
@@ -360,3 +360,61 @@ fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
     }
     fn extend_one(&mut self, _item: ()) {}
 }
+
+#[stable(feature = "extend_for_tuple", since = "1.56.0")]
+impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
+where
+    ExtendA: Extend<A>,
+    ExtendB: Extend<B>,
+{
+    /// Allows to `extend` a tuple of collections that also implement `Extend`.
+    ///
+    /// See also: [`Iterator::unzip`]
+    ///
+    /// # Examples
+    /// ```
+    /// let mut tuple = (vec![0], vec![1]);
+    /// tuple.extend(vec![(2, 3), (4, 5), (6, 7)]);
+    /// assert_eq!(tuple.0, vec![0, 2, 4, 6]);
+    /// assert_eq!(tuple.1, vec![1, 3, 5, 7]);
+    ///
+    /// // also allows for arbitrarily nested tuples
+    /// let mut nested_tuple = (vec![(1, -1)], vec![(2, -2)]);
+    /// nested_tuple.extend(vec![((3, -3), (4, -4)), ((5, -5), (6, -6))]);
+    ///
+    /// assert_eq!(nested_tuple.0, vec![(1, -1), (3, -3), (5, -5)]);
+    /// assert_eq!(nested_tuple.1, vec![(2, -2), (4, -4), (6, -6)]);
+    /// ```
+    fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
+        let (a, b) = self;
+        let iter = into_iter.into_iter();
+
+        fn extend<'a, A, B>(
+            a: &'a mut impl Extend<A>,
+            b: &'a mut impl Extend<B>,
+        ) -> impl FnMut((), (A, B)) + 'a {
+            move |(), (t, u)| {
+                a.extend_one(t);
+                b.extend_one(u);
+            }
+        }
+
+        let (lower_bound, _) = iter.size_hint();
+        if lower_bound > 0 {
+            a.extend_reserve(lower_bound);
+            b.extend_reserve(lower_bound);
+        }
+
+        iter.fold((), extend(a, b));
+    }
+
+    fn extend_one(&mut self, item: (A, B)) {
+        self.0.extend_one(item.0);
+        self.1.extend_one(item.1);
+    }
+
+    fn extend_reserve(&mut self, additional: usize) {
+        self.0.extend_reserve(additional);
+        self.1.extend_reserve(additional);
+    }
+}
index 6b24d33bebca39239d618a74f3cd0d23615eadbd..524d8f857e2a5e26db1b757cb25abad31b4626b8 100644 (file)
@@ -2841,6 +2841,14 @@ fn rev(self) -> Rev<Self>
     ///
     /// assert_eq!(left, [1, 3]);
     /// assert_eq!(right, [2, 4]);
+    ///
+    /// // you can also unzip multiple nested tuples at once
+    /// let a = [(1, (2, 3)), (4, (5, 6))];
+    ///
+    /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip();
+    /// assert_eq!(x, [1, 4]);
+    /// assert_eq!(y, [2, 5]);
+    /// assert_eq!(z, [3, 6]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
@@ -2849,28 +2857,9 @@ fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
         FromB: Default + Extend<B>,
         Self: Sized + Iterator<Item = (A, B)>,
     {
-        fn extend<'a, A, B>(
-            ts: &'a mut impl Extend<A>,
-            us: &'a mut impl Extend<B>,
-        ) -> impl FnMut((), (A, B)) + 'a {
-            move |(), (t, u)| {
-                ts.extend_one(t);
-                us.extend_one(u);
-            }
-        }
-
-        let mut ts: FromA = Default::default();
-        let mut us: FromB = Default::default();
-
-        let (lower_bound, _) = self.size_hint();
-        if lower_bound > 0 {
-            ts.extend_reserve(lower_bound);
-            us.extend_reserve(lower_bound);
-        }
-
-        self.fold((), extend(&mut ts, &mut us));
-
-        (ts, us)
+        let mut unzipped: (FromA, FromB) = Default::default();
+        unzipped.extend(self);
+        unzipped
     }
 
     /// Creates an iterator which copies all of its elements.
index 14b454da4f46f58675e6069509107218cf9fad79..ac7d8c18e3e029282473c1f695ea1ef1d993eb2c 100644 (file)
@@ -45,7 +45,7 @@
     } else if #[cfg(any(
         all(target_family = "windows", target_env = "gnu"),
         target_os = "psp",
-        target_family = "unix",
+        all(target_family = "unix", not(target_os = "espidf")),
         all(target_vendor = "fortanix", target_env = "sgx"),
     ))] {
         // Rust runtime's startup objects depend on these symbols, so make them public.
@@ -58,6 +58,7 @@
         // - arch=wasm32
         // - os=none ("bare metal" targets)
         // - os=uefi
+        // - os=espidf
         // - nvptx64-nvidia-cuda
         // - arch=avr
         #[path = "dummy.rs"]
index 492bffbba74c6fb45de0434138976ff89a6b6a10..64f413acd9709383b9850eedc7cea835272502d0 100644 (file)
@@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.98", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.99", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.44" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
index a14ac63c7a8e4ee908cb955e8ab86ba55ef24445..726157c1f1a41a9e1dd301264f825dfaeadba2c4 100644 (file)
@@ -26,6 +26,7 @@ fn main() {
         || target.contains("vxworks")
         || target.contains("wasm32")
         || target.contains("asmjs")
+        || target.contains("espidf")
     {
         // These platforms don't have any special requirements.
     } else {
diff --git a/library/std/src/os/espidf/fs.rs b/library/std/src/os/espidf/fs.rs
new file mode 100644 (file)
index 0000000..93dc2c0
--- /dev/null
@@ -0,0 +1,117 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[allow(deprecated)]
+use crate::os::espidf::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    #[rustc_deprecated(
+        since = "1.8.0",
+        reason = "deprecated in favor of the accessor \
+                  methods of this trait"
+    )]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_spare4(&self) -> [u32; 2];
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat {
+        unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+    }
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        0
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        0
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        0
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+    fn st_spare4(&self) -> [u32; 2] {
+        let spare4 = self.as_inner().as_inner().st_spare4;
+        [spare4[0] as u32, spare4[1] as u32]
+    }
+}
diff --git a/library/std/src/os/espidf/mod.rs b/library/std/src/os/espidf/mod.rs
new file mode 100644 (file)
index 0000000..a9cef97
--- /dev/null
@@ -0,0 +1,6 @@
+//! Definitions for the ESP-IDF framework.
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub mod raw;
diff --git a/library/std/src/os/espidf/raw.rs b/library/std/src/os/espidf/raw.rs
new file mode 100644 (file)
index 0000000..fb18ec6
--- /dev/null
@@ -0,0 +1,69 @@
+//! Raw type definitions for the ESP-IDF framework.
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![rustc_deprecated(
+    since = "1.8.0",
+    reason = "these type aliases are no longer supported by \
+              the standard library, the `libc` crate on \
+              crates.io should be used instead for the correct \
+              definitions"
+)]
+
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{gid_t, uid_t};
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = libc::pthread_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = libc::blkcnt_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = libc::blksize_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = libc::dev_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = libc::ino_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = libc::mode_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = libc::nlink_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = libc::off_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = libc::time_t;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: ino_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: mode_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: nlink_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: uid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: gid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: off_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: blksize_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: blkcnt_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_spare4: [c_long; 2usize],
+}
index 07e29ebf3681cd6ca635738616699c60c8b4fd0c..4c9814919cdfa5e2aee68672909ff60b4c054c22 100644 (file)
@@ -80,6 +80,8 @@ mod imp {
     pub mod dragonfly;
     #[cfg(target_os = "emscripten")]
     pub mod emscripten;
+    #[cfg(target_os = "espidf")]
+    pub mod espidf;
     #[cfg(target_os = "freebsd")]
     pub mod freebsd;
     #[cfg(target_os = "fuchsia")]
index 73489c0f1620a5148106c0b7ebe79bc5fe4b68fb..6c73d4b21dd3dbc71f51e289316825df9409031c 100644 (file)
@@ -40,6 +40,8 @@ mod platform {
     pub use crate::os::dragonfly::*;
     #[cfg(target_os = "emscripten")]
     pub use crate::os::emscripten::*;
+    #[cfg(target_os = "espidf")]
+    pub use crate::os::espidf::*;
     #[cfg(target_os = "freebsd")]
     pub use crate::os::freebsd::*;
     #[cfg(target_os = "fuchsia")]
index 2a54e99020e38f1bd673e1a4d2c5106aaf7ba0a9..576667c017392054ff825cfdde82b1dc7be202ba 100644 (file)
@@ -14,7 +14,8 @@
     target_arch = "asmjs",
     target_arch = "wasm32",
     target_arch = "hexagon",
-    target_arch = "riscv32"
+    target_arch = "riscv32",
+    target_arch = "xtensa"
 )))]
 pub const MIN_ALIGN: usize = 8;
 #[cfg(all(any(
index 1b71905aa09b77b448cb6cb433fd2cfa54d82b52..7c3d9573940ae500d53b3638ffc0fe9257689221 100644 (file)
@@ -57,7 +57,8 @@ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut
         target_os = "android",
         target_os = "illumos",
         target_os = "redox",
-        target_os = "solaris"
+        target_os = "solaris",
+        target_os = "espidf"
     ))] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
index 0bd1ea645779f6d524e1cb9e27156bcfe3f82b38..ee5e3983ac26ae4bc53377aa071cbc9cd70d30de 100644 (file)
@@ -246,3 +246,15 @@ pub fn args() -> Args {
         Args { iter: res.into_iter() }
     }
 }
+
+#[cfg(target_os = "espidf")]
+mod imp {
+    use super::Args;
+
+    #[inline(always)]
+    pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+
+    pub fn args() -> Args {
+        Args { iter: Vec::new().into_iter() }
+    }
+}
index e38f91af9f0b9ba6d17543c1a216002092f3e6a6..61261c0aa84e3e084aca6bc5a7f46698b8f91b3e 100644 (file)
@@ -34,12 +34,23 @@ pub const fn new() -> Condvar {
     ))]
     pub unsafe fn init(&mut self) {}
 
+    // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet
+    // So on that platform, init() should always be called
+    // Moreover, that platform does not have pthread_condattr_setclock support,
+    // hence that initialization should be skipped as well
+    #[cfg(target_os = "espidf")]
+    pub unsafe fn init(&mut self) {
+        let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
+        assert_eq!(r, 0);
+    }
+
     #[cfg(not(any(
         target_os = "macos",
         target_os = "ios",
         target_os = "l4re",
         target_os = "android",
-        target_os = "redox"
+        target_os = "redox",
+        target_os = "espidf"
     )))]
     pub unsafe fn init(&mut self) {
         use crate::mem::MaybeUninit;
@@ -76,7 +87,12 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
     // where we configure condition variable to use monotonic clock (instead of
     // default system clock). This approach avoids all problems that result
     // from changes made to the system time.
-    #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
+    #[cfg(not(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "android",
+        target_os = "espidf"
+    )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         use crate::mem;
 
@@ -103,7 +119,12 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
     // This implementation is modeled after libcxx's condition_variable
     // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
     // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "android",
+        target_os = "espidf"
+    ))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use crate::ptr;
         use crate::time::Instant;
index 3a88dc083b06c735fc0274abeea9ea357dfbe659..60551aeb3e73e5f1c0ee92452c48cd146908dbef 100644 (file)
@@ -184,3 +184,14 @@ pub mod os {
     pub const EXE_SUFFIX: &str = "";
     pub const EXE_EXTENSION: &str = "";
 }
+
+#[cfg(target_os = "espidf")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "espidf";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
index 821851a6c65b70be433262d9f783a6961284c291..28e32681e15b3d3624d1ba3c7ab935600e7ccad0 100644 (file)
@@ -91,6 +91,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         Ok(ret as usize)
     }
 
+    #[cfg(not(target_os = "espidf"))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::readv(
@@ -102,9 +103,14 @@ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         Ok(ret as usize)
     }
 
+    #[cfg(target_os = "espidf")]
+    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        return crate::io::default_read_vectored(|b| self.read(b), bufs);
+    }
+
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        true
+        cfg!(not(target_os = "espidf"))
     }
 
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -148,6 +154,7 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         Ok(ret as usize)
     }
 
+    #[cfg(not(target_os = "espidf"))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::writev(
@@ -159,9 +166,14 @@ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         Ok(ret as usize)
     }
 
+    #[cfg(target_os = "espidf")]
+    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        return crate::io::default_write_vectored(|b| self.write(b), bufs);
+    }
+
     #[inline]
     pub fn is_write_vectored(&self) -> bool {
-        true
+        cfg!(not(target_os = "espidf"))
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
@@ -217,7 +229,7 @@ pub fn set_cloexec(&self) -> io::Result<()> {
         }
     }
     #[cfg(any(
-        target_env = "newlib",
+        all(target_env = "newlib", not(target_os = "espidf")),
         target_os = "solaris",
         target_os = "illumos",
         target_os = "emscripten",
@@ -238,6 +250,12 @@ pub fn set_cloexec(&self) -> io::Result<()> {
             Ok(())
         }
     }
+    #[cfg(target_os = "espidf")]
+    pub fn set_cloexec(&self) -> io::Result<()> {
+        // FD_CLOEXEC is not supported in ESP-IDF but there's no need to,
+        // because ESP-IDF does not support spawning processes either.
+        Ok(())
+    }
 
     #[cfg(target_os = "linux")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
@@ -268,7 +286,17 @@ pub fn duplicate(&self) -> io::Result<FileDesc> {
         // We want to atomically duplicate this file descriptor and set the
         // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
         // is a POSIX flag that was added to Linux in 2.6.24.
-        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
+        #[cfg(not(target_os = "espidf"))]
+        let cmd = libc::F_DUPFD_CLOEXEC;
+
+        // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+        // will never be supported, as this is a bare metal framework with
+        // no capabilities for multi-process execution.  While F_DUPFD is also
+        // not supported yet, it might be (currently it returns ENOSYS).
+        #[cfg(target_os = "espidf")]
+        let cmd = libc::F_DUPFD;
+
+        let fd = cvt(unsafe { libc::fcntl(self.raw(), cmd, 0) })?;
         Ok(FileDesc::new(fd))
     }
 }
index 7f69ebbeb4de60df54a3317946568fd07f0e2a54..fd4defd72eb4736b5f6389265820a78e5848be89 100644 (file)
@@ -312,7 +312,7 @@ pub fn created(&self) -> io::Result<SystemTime> {
 
 #[cfg(not(target_os = "netbsd"))]
 impl FileAttr {
-    #[cfg(not(target_os = "vxworks"))]
+    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
     pub fn modified(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_mtime as libc::time_t,
@@ -320,7 +320,7 @@ pub fn modified(&self) -> io::Result<SystemTime> {
         }))
     }
 
-    #[cfg(target_os = "vxworks")]
+    #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
     pub fn modified(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_mtime as libc::time_t,
@@ -328,7 +328,7 @@ pub fn modified(&self) -> io::Result<SystemTime> {
         }))
     }
 
-    #[cfg(not(target_os = "vxworks"))]
+    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_atime as libc::time_t,
@@ -336,7 +336,7 @@ pub fn accessed(&self) -> io::Result<SystemTime> {
         }))
     }
 
-    #[cfg(target_os = "vxworks")]
+    #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
             tv_sec: self.stat.st_atime as libc::time_t,
@@ -609,7 +609,8 @@ pub fn file_type(&self) -> io::Result<FileType> {
         target_os = "l4re",
         target_os = "fuchsia",
         target_os = "redox",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "espidf"
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
@@ -648,7 +649,8 @@ fn name_bytes(&self) -> &[u8] {
         target_os = "emscripten",
         target_os = "l4re",
         target_os = "haiku",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "espidf"
     ))]
     fn name_bytes(&self) -> &[u8] {
         unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() }
@@ -1106,8 +1108,8 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
     let original = cstr(original)?;
     let link = cstr(link)?;
     cfg_if::cfg_if! {
-        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
-            // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves
+        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf"))] {
+            // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
             // it implementation-defined whether `link` follows symlinks, so rely on the
             // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
             // Android has `linkat` on newer versions, but we happen to know `link`
@@ -1199,6 +1201,18 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)>
     Ok((reader, metadata))
 }
 
+#[cfg(target_os = "espidf")]
+fn open_to_and_set_permissions(
+    to: &Path,
+    reader_metadata: crate::fs::Metadata,
+) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
+    use crate::fs::OpenOptions;
+    let writer = OpenOptions::new().open(to)?;
+    let writer_metadata = writer.metadata()?;
+    Ok((writer, writer_metadata))
+}
+
+#[cfg(not(target_os = "espidf"))]
 fn open_to_and_set_permissions(
     to: &Path,
     reader_metadata: crate::fs::Metadata,
index f827a4bca53f0f35b85a44a4b97889e94c49b62f..f5424e3d282140abebd04d371147d56e9f4a715f 100644 (file)
@@ -5,6 +5,7 @@
 pub use self::rand::hashmap_random_keys;
 pub use libc::strlen;
 
+#[cfg(not(target_os = "espidf"))]
 #[macro_use]
 pub mod weak;
 
 pub mod thread_local_key;
 pub mod time;
 
+#[cfg(target_os = "espidf")]
+pub fn init(argc: isize, argv: *const *const u8) {}
+
+#[cfg(not(target_os = "espidf"))]
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
 pub unsafe fn init(argc: isize, argv: *const *const u8) {
@@ -304,3 +309,19 @@ pub fn abort_internal() -> ! {
         extern "C" {}
     }
 }
+
+#[cfg(target_os = "espidf")]
+mod unsupported {
+    use crate::io;
+
+    pub fn unsupported<T>() -> io::Result<T> {
+        Err(unsupported_err())
+    }
+
+    pub fn unsupported_err() -> io::Error {
+        io::Error::new_const(
+            io::ErrorKind::Unsupported,
+            &"operation not supported on this platform",
+        )
+    }
+}
index 753cad55ce74546805385f7e48e9adbe3890580d..3f614fde08aca6482e0b8b1988266083f575aeb9 100644 (file)
@@ -9,7 +9,7 @@
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::{Duration, Instant};
 
-use libc::{c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
 
 pub use crate::sys::{cvt, cvt_r};
 
@@ -30,13 +30,19 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
     // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
     on_resolver_failure();
 
-    if err == EAI_SYSTEM {
+    #[cfg(not(target_os = "espidf"))]
+    if err == libc::EAI_SYSTEM {
         return Err(io::Error::last_os_error());
     }
 
+    #[cfg(not(target_os = "espidf"))]
     let detail = unsafe {
         str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
     };
+
+    #[cfg(target_os = "espidf")]
+    let detail = "";
+
     Err(io::Error::new(
         io::ErrorKind::Uncategorized,
         &format!("failed to lookup address information: {}", detail)[..],
index bbfe846e31556d732a9ad70ee33800b894d11e2d..1d5ffb073211bcde9f40a679e2d296422bc45053 100644 (file)
@@ -128,6 +128,12 @@ pub fn error_string(errno: i32) -> String {
     }
 }
 
+#[cfg(target_os = "espidf")]
+pub fn getcwd() -> io::Result<PathBuf> {
+    Ok(PathBuf::from("/"))
+}
+
+#[cfg(not(target_os = "espidf"))]
 pub fn getcwd() -> io::Result<PathBuf> {
     let mut buf = Vec::with_capacity(512);
     loop {
@@ -154,6 +160,12 @@ pub fn getcwd() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(target_os = "espidf")]
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+    super::unsupported::unsupported()
+}
+
+#[cfg(not(target_os = "espidf"))]
 pub fn chdir(p: &path::Path) -> io::Result<()> {
     let p: &OsStr = p.as_ref();
     let p = CString::new(p.as_bytes())?;
@@ -432,6 +444,11 @@ pub fn current_exe() -> io::Result<PathBuf> {
     path.canonicalize()
 }
 
+#[cfg(target_os = "espidf")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    super::unsupported::unsupported()
+}
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
@@ -541,6 +558,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     }
 }
 
+#[cfg(not(target_os = "espidf"))]
 pub fn page_size() -> usize {
     unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
 }
@@ -563,7 +581,8 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "ios",
         target_os = "emscripten",
         target_os = "redox",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "espidf"
     ))]
     unsafe fn fallback() -> Option<OsString> {
         None
@@ -573,7 +592,8 @@ unsafe fn fallback() -> Option<OsString> {
         target_os = "ios",
         target_os = "emscripten",
         target_os = "redox",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "espidf"
     )))]
     unsafe fn fallback() -> Option<OsString> {
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
index b5a19ed54a2f25e78d1fc25dc52d4589778c5d14..0165ece849ee5034aba41becf2552fe03b61c139 100644 (file)
@@ -13,6 +13,9 @@
     } else if #[cfg(target_os = "vxworks")] {
         #[path = "process_vxworks.rs"]
         mod process_inner;
+    } else if #[cfg(target_os = "espidf")] {
+        #[path = "process_unsupported.rs"]
+        mod process_inner;
     } else {
         #[path = "process_unix.rs"]
         mod process_inner;
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
new file mode 100644 (file)
index 0000000..7d549d0
--- /dev/null
@@ -0,0 +1,122 @@
+use crate::convert::{TryFrom, TryInto};
+use crate::fmt;
+use crate::io;
+use crate::io::ErrorKind;
+use crate::num::NonZeroI32;
+use crate::os::raw::NonZero_c_int;
+use crate::sys;
+use crate::sys::cvt;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::process::process_common::*;
+use crate::sys::unix::unsupported::*;
+
+use libc::{c_int, pid_t};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+impl Command {
+    pub fn spawn(
+        &mut self,
+        default: Stdio,
+        needs_stdin: bool,
+    ) -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+
+    pub fn exec(&mut self, default: Stdio) -> io::Error {
+        unsupported_err()
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Processes
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Process {
+    handle: pid_t,
+}
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        0
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        unsupported()
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        unsupported()
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatus(c_int);
+
+impl ExitStatus {
+    pub fn success(&self) -> bool {
+        self.code() == Some(0)
+    }
+
+    pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
+        Err(ExitStatusError(1.try_into().unwrap()))
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        None
+    }
+
+    pub fn signal(&self) -> Option<i32> {
+        None
+    }
+
+    pub fn core_dumped(&self) -> bool {
+        false
+    }
+
+    pub fn stopped_signal(&self) -> Option<i32> {
+        None
+    }
+
+    pub fn continued(&self) -> bool {
+        false
+    }
+
+    pub fn into_raw(&self) -> c_int {
+        0
+    }
+}
+
+/// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
+impl From<c_int> for ExitStatus {
+    fn from(a: c_int) -> ExitStatus {
+        ExitStatus(a as i32)
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "exit code: {}", self.0)
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatusError(NonZero_c_int);
+
+impl Into<ExitStatus> for ExitStatusError {
+    fn into(self) -> ExitStatus {
+        ExitStatus(self.0.into())
+    }
+}
+
+impl ExitStatusError {
+    pub fn code(self) -> Option<NonZeroI32> {
+        ExitStatus(self.0.into()).code().map(|st| st.try_into().unwrap())
+    }
+}
index 32895001a65bae83dd119e5735dced1dd55c084e..7a3f6b0d95a09aace1cdba7529287315eeb6655a 100644 (file)
@@ -44,12 +44,17 @@ fn getrandom(
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(not(any(target_os = "linux", target_os = "android")))]
+    #[cfg(target_os = "espidf")]
+    fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
+        unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
+    }
+
+    #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "espidf")))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
         false
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "espidf"))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         use crate::sync::atomic::{AtomicBool, Ordering};
         use crate::sys::os::errno;
index bc61f472a2b0501fcbda5f5e4c01a3a61ed58fee..133ad3ea420b83b6bceb81d63020619154eb42d5 100644 (file)
@@ -9,12 +9,14 @@
 
 #[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
 use crate::sys::weak::weak;
-#[cfg(not(any(target_os = "l4re", target_os = "vxworks")))]
+#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
 #[cfg(target_os = "l4re")]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
 #[cfg(target_os = "vxworks")]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
+#[cfg(target_os = "espidf")]
+pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used
 
 #[cfg(target_os = "fuchsia")]
 mod zircon {
@@ -50,22 +52,35 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         let mut attr: libc::pthread_attr_t = mem::zeroed();
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
 
-        let stack_size = cmp::max(stack, min_stack_size(&attr));
-
-        match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
-            0 => {}
-            n => {
-                assert_eq!(n, libc::EINVAL);
-                // EINVAL means |stack_size| is either too small or not a
-                // multiple of the system page size.  Because it's definitely
-                // >= PTHREAD_STACK_MIN, it must be an alignment issue.
-                // Round up to the nearest page and try again.
-                let page_size = os::page_size();
-                let stack_size =
-                    (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
-                assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
-            }
-        };
+        #[cfg(target_os = "espidf")]
+        if stack > 0 {
+            // Only set the stack if a non-zero value is passed
+            // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used
+            assert_eq!(
+                libc::pthread_attr_setstacksize(&mut attr, cmp::max(stack, min_stack_size(&attr))),
+                0
+            );
+        }
+
+        #[cfg(not(target_os = "espidf"))]
+        {
+            let stack_size = cmp::max(stack, min_stack_size(&attr));
+
+            match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
+                0 => {}
+                n => {
+                    assert_eq!(n, libc::EINVAL);
+                    // EINVAL means |stack_size| is either too small or not a
+                    // multiple of the system page size.  Because it's definitely
+                    // >= PTHREAD_STACK_MIN, it must be an alignment issue.
+                    // Round up to the nearest page and try again.
+                    let page_size = os::page_size();
+                    let stack_size =
+                        (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
+                    assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+                }
+            };
+        }
 
         let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
         // Note: if the thread creation fails and this assert fails, then p will
@@ -183,6 +198,7 @@ pub fn set_name(_name: &CStr) {
         // Newlib, Emscripten, and VxWorks have no way to set a thread name.
     }
 
+    #[cfg(not(target_os = "espidf"))]
     pub fn sleep(dur: Duration) {
         let mut secs = dur.as_secs();
         let mut nsecs = dur.subsec_nanos() as _;
@@ -208,6 +224,19 @@ pub fn sleep(dur: Duration) {
         }
     }
 
+    #[cfg(target_os = "espidf")]
+    pub fn sleep(dur: Duration) {
+        let mut micros = dur.as_micros();
+        unsafe {
+            while micros > 0 {
+                let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 };
+                libc::usleep(st);
+
+                micros -= st as u128;
+            }
+        }
+    }
+
     pub fn join(self) {
         unsafe {
             let ret = libc::pthread_join(self.id, ptr::null_mut());
index 23a5c81c0053bb4abdf8b2cc2c4f520dcc035b0c..7dc09add27fd717c7487bd2af781a4c9dc1f7131 100644 (file)
@@ -361,9 +361,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         }
     }
 
-    #[cfg(not(target_os = "dragonfly"))]
+    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf")))]
     pub type clock_t = libc::c_int;
-    #[cfg(target_os = "dragonfly")]
+    #[cfg(any(target_os = "dragonfly", target_os = "espidf"))]
     pub type clock_t = libc::c_ulong;
 
     fn now(clock: clock_t) -> Timespec {
index 0fdf72c8067d25abf66ddc39df771fb5bcf9f37d..ae193b82e91bb4ce67631babc0ff1c67a6f2e583 100644 (file)
@@ -3,7 +3,6 @@
 #[cfg(test)]
 mod tests;
 
-use crate::borrow::Borrow;
 use crate::cmp;
 use crate::collections::BTreeMap;
 use crate::convert::{TryFrom, TryInto};
@@ -46,6 +45,12 @@ pub struct EnvKey {
     utf16: Vec<u16>,
 }
 
+impl EnvKey {
+    fn new<T: Into<OsString>>(key: T) -> Self {
+        EnvKey::from(key.into())
+    }
+}
+
 // Comparing Windows environment variable keys[1] are behaviourally the
 // composition of two operations[2]:
 //
@@ -100,6 +105,20 @@ fn eq(&self, other: &Self) -> bool {
         }
     }
 }
+impl PartialOrd<str> for EnvKey {
+    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+        Some(self.cmp(&EnvKey::new(other)))
+    }
+}
+impl PartialEq<str> for EnvKey {
+    fn eq(&self, other: &str) -> bool {
+        if self.os_string.len() != other.len() {
+            false
+        } else {
+            self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal
+        }
+    }
+}
 
 // Environment variable keys should preserve their original case even though
 // they are compared using a caseless string mapping.
@@ -115,9 +134,9 @@ fn from(k: EnvKey) -> Self {
     }
 }
 
-impl Borrow<OsStr> for EnvKey {
-    fn borrow(&self) -> &OsStr {
-        &self.os_string
+impl From<&OsStr> for EnvKey {
+    fn from(k: &OsStr) -> Self {
+        Self::from(k.to_os_string())
     }
 }
 
@@ -242,7 +261,7 @@ pub fn spawn(
         // to read the *child's* PATH if one is provided. See #15149 for more
         // details.
         let program = maybe_env.as_ref().and_then(|env| {
-            if let Some(v) = env.get(OsStr::new("PATH")) {
+            if let Some(v) = env.get(&EnvKey::new("PATH")) {
                 // Split the value and test each path to see if the
                 // program exists.
                 for path in split_paths(&v) {
index 7c1d98a5abd599bb6b0460c6942ebaebd94175d4..ea9108f17133af8491544944727c7fc2a4f46a72 100644 (file)
@@ -1,4 +1,6 @@
-pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
+// Bare metal platforms usually have very small amounts of RAM
+// (in the order of hundreds of KB)
+pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 };
 
 #[cfg(test)]
 #[allow(dead_code)] // not used on emscripten
index fe89b11043c0ff879703925a2f4307030f157971..38007d5c414ecd42bd97456334005c4231756bd9 100644 (file)
@@ -65,16 +65,18 @@ pub fn capture_if_changed(&self) -> Option<BTreeMap<EnvKey, OsString>> {
 
     // The following functions build up changes
     pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
-        self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
+        self.vars.insert(key, Some(value.to_owned()));
     }
 
     pub fn remove(&mut self, key: &OsStr) {
+        let key = EnvKey::from(key);
         self.maybe_saw_path(&key);
         if self.clear {
-            self.vars.remove(key);
+            self.vars.remove(&key);
         } else {
-            self.vars.insert(key.to_owned().into(), None);
+            self.vars.insert(key, None);
         }
     }
 
@@ -87,7 +89,7 @@ pub fn have_changed_path(&self) -> bool {
         self.saw_path || self.clear
     }
 
-    fn maybe_saw_path(&mut self, key: &OsStr) {
+    fn maybe_saw_path(&mut self, key: &EnvKey) {
         if !self.saw_path && key == "PATH" {
             self.saw_path = true;
         }
index 9e52802450682137789e05161593441cad620451..53b13b9043b3a2e9fef7fe26e318e2f8a83303e4 100644 (file)
@@ -13,6 +13,7 @@
     } else if #[cfg(any(
         target_os = "l4re",
         target_os = "none",
+        target_os = "espidf",
     ))] {
         // These "unix" family members do not have unwinder.
         // Note this also matches x86_64-unknown-none-linuxkernel.
index a07036f864b37896b31eb996cd7aedb489f69a1f..7e49659102f0977d9142190e1ba23345c0f00eb1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a07036f864b37896b31eb996cd7aedb489f69a1f
+Subproject commit 7e49659102f0977d9142190e1ba23345c0f00eb1
index 09986cd352404eb4659db44613b27cac9aa652fc..4f9fcaa30d11ba52b641e6fd5206536d65838af9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 09986cd352404eb4659db44613b27cac9aa652fc
+Subproject commit 4f9fcaa30d11ba52b641e6fd5206536d65838af9
index f51734eb5566c826b471977747ea3d7d6915bbe9..0c7e5bd1428e7838252bb57b7f0fbfda4ec82f02 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f51734eb5566c826b471977747ea3d7d6915bbe9
+Subproject commit 0c7e5bd1428e7838252bb57b7f0fbfda4ec82f02
index 3b7be075af5d6e402a18efff672a8a265b4596fd..4884fe45c14f8b22121760fb117181bb4da8dfe0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3b7be075af5d6e402a18efff672a8a265b4596fd
+Subproject commit 4884fe45c14f8b22121760fb117181bb4da8dfe0
index 09343d6f921d2a07c66f8c41ec3d65bf1fa52556..c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 09343d6f921d2a07c66f8c41ec3d65bf1fa52556
+Subproject commit c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f
index 5718a18393f9cec330351d8af919443e7fc6c865..0bfe35ea861899ae80009c4250775f30a05c46ca 100644 (file)
@@ -256,6 +256,7 @@ target | std | host | notes
 `powerpc64le-unknown-linux-musl` | ? |  |
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
+`riscv32imc-esp-espidf` | âœ“ |  | RISC-V ESP-IDF
 `riscv64gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 4.20, musl 1.2.0)
 `s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 2.6.32, MUSL)
 `sparc-unknown-linux-gnu` | âœ“ |  | 32-bit SPARC Linux
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml
new file mode 100644 (file)
index 0000000..b5be31b
--- /dev/null
@@ -0,0 +1,46 @@
+// This test check for headers text and background colors for the different themes.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+reload:
+
+assert-css: (".impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(230, 225, 207)", "background-color": "rgb(15, 20, 25)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ALL)
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+assert-css: (".impl", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(221, 221, 221)", "background-color": "rgb(53, 53, 53)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ALL)
+
+// Light theme
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+reload:
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+assert-css: (".impl", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}, ALL)
index 6ed62006151a216fad74811d036f436e530f2efc..daf8bc9dea3501d690393056e3cf98a752c5247a 100644 (file)
@@ -1,5 +1,5 @@
 goto: file://|DOC_PATH|/test_docs/index.html
-// We set the theme so we're sure that the corect values will be used, whatever the computer
+// We set the theme so we're sure that the correct values will be used, whatever the computer
 // this test is running on.
 local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
 // If the text isn't displayed, the browser doesn't compute color style correctly...
index 5e98520b41187a5c9261e03603184c1022ecdbcf..008eddcb29dbcc121770f7fa6681913bea60960d 100644 (file)
@@ -1,14 +1,14 @@
 error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:26:5
+  --> $DIR/defaults-cyclic-fail-1.rs:26:14
    |
 LL |     type A = Box<Self::B>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^
 
 error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
-  --> $DIR/defaults-cyclic-fail-1.rs:32:5
+  --> $DIR/defaults-cyclic-fail-1.rs:32:14
    |
 LL |     type B = &'static Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index c538805f858219dbccb8bdc34a4b4b5bd4d06f4e..d0fbab077153f4bbf974ed21d3dc48722df8038b 100644 (file)
@@ -1,14 +1,14 @@
 error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:27:5
+  --> $DIR/defaults-cyclic-fail-2.rs:27:14
    |
 LL |     type A = Box<Self::B>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^
 
 error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
-  --> $DIR/defaults-cyclic-fail-2.rs:33:5
+  --> $DIR/defaults-cyclic-fail-2.rs:33:14
    |
 LL |     type B = &'static Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index e5a25a171fbe00417469add5e35b271a4723ea1e..35be93b0590326121fad5b9b18aa71d5c8b157f2 100644 (file)
@@ -1,5 +1,8 @@
 #[macro_export]
 macro_rules! fancy_panic {
+    () => {
+        panic!("{}");
+    };
     ($msg:expr) => {
         panic!($msg)
     };
index e2b7b8f0275204194965c83012005aba659739bd..beebb118399f3920f0b04fbc154be73ae751108a 100644 (file)
@@ -13,11 +13,11 @@ fn test_send_trait() {
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || { let _ = &fptr; unsafe {
         //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
     } });
 }
 
@@ -33,11 +33,11 @@ fn test_sync_trait() {
     let fptr = SyncPointer(f);
     thread::spawn(move || { let _ = &fptr; unsafe {
         //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
     } });
 }
 
@@ -55,13 +55,14 @@ impl Clone for U {
 
 fn test_clone_trait() {
     let f = U(S(String::from("Hello World")), T(0));
-    let c = || { let _ = &f; 
+    let c = || {
+        let _ = &f;
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
         println!("{:?}", f_1.0);
     };
 
@@ -69,7 +70,7 @@ fn test_clone_trait() {
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
 
 fn main() {
     test_send_trait();
index 6c56ca27475a3d177492a48885e29ea70989b66d..812ecae262f77b8b2ee74d99024aec6fc021fa2f 100644 (file)
@@ -13,11 +13,11 @@ fn test_send_trait() {
     let fptr = SendPointer(&mut f as *mut i32);
     thread::spawn(move || unsafe {
         //~^ ERROR: `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
     });
 }
 
@@ -33,11 +33,11 @@ fn test_sync_trait() {
     let fptr = SyncPointer(f);
     thread::spawn(move || unsafe {
         //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr` to be fully captured
         *fptr.0.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
     });
 }
 
@@ -57,11 +57,11 @@ fn test_clone_trait() {
     let f = U(S(String::from("Hello World")), T(0));
     let c = || {
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         let f_1 = f.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
         println!("{:?}", f_1.0);
     };
 
@@ -69,7 +69,7 @@ fn test_clone_trait() {
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
 
 fn main() {
     test_send_trait();
index e60d01f0c2caab9b4ec3de6370e4c65e223ce05d..e8dd81ede2547124aed40b3cc7b4314657add1e5 100644 (file)
@@ -2,10 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `Send` trait implemen
   --> $DIR/auto_traits.rs:14:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
 ...
 LL |         *fptr.0 = 20;
-   |         ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+   |         ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
    |
 note: the lint level is defined here
   --> $DIR/auto_traits.rs:2:9
@@ -27,10 +27,10 @@ error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait
   --> $DIR/auto_traits.rs:34:19
    |
 LL |     thread::spawn(move || unsafe {
-   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+   |                   ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
 ...
 LL |         *fptr.0.0 = 20;
-   |         --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+   |         --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `fptr` to be fully captured
@@ -47,23 +47,23 @@ error: changes to closure capture in Rust 2021 will affect `Clone` trait impleme
   --> $DIR/auto_traits.rs:58:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
 ...
 LL |         let f_1 = f.1;
-   |                   --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+   |                   --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
 ...
 LL | }
-   | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+   | - in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f` to be fully captured
    |
-LL ~     let c = || { let _ = &f; 
+LL ~     let c = || {
+LL +         let _ = &f;
 LL +
 LL +
 LL +
 LL +
-LL +         let f_1 = f.1;
  ...
 
 error: aborting due to 3 previous errors
index e836f27cd7af1ff1ae363ceceeb32bf8f33807b8..982407e2e25567e47885098c281edf556c99b322 100644 (file)
@@ -12,24 +12,25 @@ fn test1_all_need_migration() {
     let t1 = (String::new(), String::new());
     let t2 = (String::new(), String::new());
 
-    let c = || { let _ = (&t, &t1, &t2); 
+    let c = || {
+        let _ = (&t, &t1, &t2);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
 
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -38,39 +39,41 @@ fn test2_only_precise_paths_need_migration() {
     let t1 = (String::new(), String::new());
     let t2 = (String::new(), String::new());
 
-    let c = || { let _ = (&t, &t1); 
+    let c = || {
+        let _ = (&t, &t1);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
 fn test3_only_by_value_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         println!("{}", t1.1);
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Copy types get copied into the closure instead of move. Therefore we don't need to
 // migrate then as their drop order isn't tied to the closure.
@@ -80,18 +83,19 @@ fn test4_only_non_copy_types_need_migration() {
     // `t1` is Copy because all of its elements are Copy
     let t1 = (0i32, 0i32);
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn test5_only_drop_types_need_migration() {
     struct S(i32, i32);
@@ -101,37 +105,39 @@ fn test5_only_drop_types_need_migration() {
     // `s` doesn't implement Drop or any elements within it, and doesn't need migration
     let s = S(0i32, 0i32);
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _s = s.0;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
 fn test6_move_closures_non_copy_types_might_need_migration() {
     let t = (String::new(), String::new());
     let t1 = (String::new(), String::new());
-    let c = move || { let _ = (&t1, &t); 
+    let c = move || {
+        let _ = (&t1, &t);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{} {}", t1.1, t.1);
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
-        //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
+        //~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -139,17 +145,18 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
 fn test7_drop_non_drop_aggregate_need_migration() {
     let t = (String::new(), String::new(), 0i32);
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn main() {
     test1_all_need_migration();
index fbf9b983f07a265092cae5b2d56ed935b75db791..1ac034959cbc80d3d672a4c9b20611064f6b4907 100644 (file)
@@ -18,18 +18,18 @@ fn test1_all_need_migration() {
         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
 
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -43,16 +43,16 @@ fn test2_only_precise_paths_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -64,13 +64,13 @@ fn test3_only_by_value_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         println!("{}", t1.1);
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Copy types get copied into the closure instead of move. Therefore we don't need to
 // migrate then as their drop order isn't tied to the closure.
@@ -85,13 +85,13 @@ fn test4_only_non_copy_types_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn test5_only_drop_types_need_migration() {
     struct S(i32, i32);
@@ -106,13 +106,13 @@ fn test5_only_drop_types_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _s = s.0;
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -124,14 +124,14 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{} {}", t1.1, t.1);
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
-        //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
+        //~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -144,12 +144,12 @@ fn test7_drop_non_drop_aggregate_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn main() {
     test1_all_need_migration();
index f4677297611578cda27dfad437a8c3cdc99b5c8f..b719b89f5fcbc4a90e36c3a0f6df0439988ed351 100644 (file)
@@ -5,20 +5,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 LL |
 LL |         let _t1 = t1.0;
-   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+   |                   ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
 LL |
 LL |         let _t2 = t2.0;
-   |                   ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+   |                   ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-   | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+   | in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/insignificant_drop.rs:3:9
@@ -28,12 +28,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
    |
-LL ~     let c = || { let _ = (&t, &t1, &t2); 
+LL ~     let c = || {
+LL +         let _ = (&t, &t1, &t2);
 LL +
 LL +
 LL +
 LL + 
-LL +         let _t = t.0;
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -43,26 +43,26 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 LL |
 LL |         let _t1 = t1.0;
-   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+   |                   ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1` to be fully captured
    |
-LL ~     let c = || { let _ = (&t, &t1); 
+LL ~     let c = || {
+LL +         let _ = (&t, &t1);
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -72,20 +72,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -95,20 +95,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -118,20 +118,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -141,25 +141,25 @@ LL |     let c = move || {
    |             ^^^^^^^
 ...
 LL |         println!("{} {}", t1.1, t.1);
-   |                           ----  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                           ----  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
    |                           |
-   |                           in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+   |                           in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t1`, `t` to be fully captured
    |
-LL ~     let c = move || { let _ = (&t1, &t); 
+LL ~     let c = move || {
+LL +         let _ = (&t1, &t);
 LL +
 LL +
 LL +
 LL +         println!("{} {}", t1.1, t.1);
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -169,20 +169,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: aborting due to 7 previous errors
index 4626c04e9ba6ea3a51b342b471f74aa6d5cd7cac..e672d9266fcd19dba7135009d4e73e3111528304 100644 (file)
@@ -34,17 +34,18 @@ impl<T> Drop for GenericStruct<T> {
 fn significant_drop_needs_migration() {
     let t = (SigDrop {}, SigDrop {});
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Even if a type implements an insignificant drop, if it's
 // elements have a significant drop then the overall type is
@@ -54,17 +55,18 @@ fn generic_struct_with_significant_drop_needs_migration() {
     let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5);
 
     // move is used to force i32 to be copied instead of being a ref
-    let c = move || { let _ = &t; 
+    let c = move || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
 
 fn main() {
     significant_drop_needs_migration();
index ebcf1551bacf62d9547e53fbd5750c76fb47ab9f..45850ec5f36dce9f68e8ee665e29456bea5a641e 100644 (file)
@@ -39,12 +39,12 @@ fn significant_drop_needs_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Even if a type implements an insignificant drop, if it's
 // elements have a significant drop then the overall type is
@@ -59,12 +59,12 @@ fn generic_struct_with_significant_drop_needs_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
 
 fn main() {
     significant_drop_needs_migration();
index 2de6ffb0673233befc51e5481aa1bf3197db097c..669614fee0a9354c72a5f2dcdde8c003c9fbc954 100644 (file)
@@ -5,10 +5,10 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/insignificant_drop_attr_migrations.rs:3:9
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -33,20 +33,20 @@ LL |     let c = move || {
    |             ^^^^^^^
 ...
 LL |         let _t = t.1;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = move || { let _ = &t; 
+LL ~     let c = move || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.1;
-LL +
  ...
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/macro.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/macro.fixed
new file mode 100644 (file)
index 0000000..b9dd8a2
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+// See https://github.com/rust-lang/rust/issues/87955
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+fn main() {
+    let a = ("hey".to_string(), "123".to_string());
+    let _ = || { let _ = &a; dbg!(a.0) };
+    //~^ ERROR: drop order
+    //~| NOTE: will only capture `a.0`
+    //~| NOTE: for more information, see
+    //~| HELP: add a dummy let to cause `a` to be fully captured
+}
+//~^ NOTE: dropped here
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/macro.rs b/src/test/ui/closures/2229_closure_analysis/migrations/macro.rs
new file mode 100644 (file)
index 0000000..f7ccdb7
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+// See https://github.com/rust-lang/rust/issues/87955
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+fn main() {
+    let a = ("hey".to_string(), "123".to_string());
+    let _ = || dbg!(a.0);
+    //~^ ERROR: drop order
+    //~| NOTE: will only capture `a.0`
+    //~| NOTE: for more information, see
+    //~| HELP: add a dummy let to cause `a` to be fully captured
+}
+//~^ NOTE: dropped here
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr
new file mode 100644 (file)
index 0000000..0614b78
--- /dev/null
@@ -0,0 +1,24 @@
+error: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/macro.rs:10:13
+   |
+LL |     let _ = || dbg!(a.0);
+   |             ^^^^^^^^---^
+   |                     |
+   |                     in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
+...
+LL | }
+   | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
+   |
+note: the lint level is defined here
+  --> $DIR/macro.rs:5:9
+   |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `a` to be fully captured
+   |
+LL |     let _ = || { let _ = &a; dbg!(a.0) };
+   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
index f3c15a2e6b676e08dc3966c66b644365f4912241..ce8b607259576b11d5819bf22868b5a0c5647f9f 100644 (file)
@@ -16,29 +16,30 @@ impl Drop for Foo {
 
 fn closure_contains_block() {
     let t = (Foo(0), Foo(0));
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || { let _ = &t; t.0 };
     //~^ ERROR: drop order
-    //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+    //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     //~| NOTE: for more information, see
     //~| HELP: add a dummy let to cause `t` to be fully captured
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn main() {
     closure_contains_block();
index 50936d15302b7914e36f1abd1dd8a134c68912da..2237bebd788e7c8e37204bf88eecd8c0d69f8771 100644 (file)
@@ -21,24 +21,24 @@ fn closure_contains_block() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn closure_doesnt_contain_block() {
     let t = (Foo(0), Foo(0));
     let c = || t.0;
     //~^ ERROR: drop order
-    //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+    //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     //~| NOTE: for more information, see
     //~| HELP: add a dummy let to cause `t` to be fully captured
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 fn main() {
     closure_contains_block();
index e8e1eb03e93a4c30af7044e16d24ea21a65524bf..8d4819fe2e22168b521b5162a46b345351ee5bb0 100644 (file)
@@ -5,10 +5,10 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/migrations_rustfix.rs:2:9
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -32,10 +32,10 @@ error: changes to closure capture in Rust 2021 will affect drop order
 LL |     let c = || t.0;
    |             ^^^---
    |                |
-   |                in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
index f24804018cd85ca10427cb560f13c865089cfd43..a5652154682c5b672da67568c79a30dbc1f1e384 100644 (file)
@@ -17,13 +17,14 @@ where
     F: FnOnce(),
 {
     let f = panic::AssertUnwindSafe(f);
-    let result = panic::catch_unwind(move || { let _ = &f; 
+    let result = panic::catch_unwind(move || {
+        let _ = &f;
         //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
-        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
     });
     if let Ok(..) = result {
         panic!("diverging function returned");
index 6a6a51c51322d8a3c163eb0a49e8ab378153be06..d9acde073fc3d38fffd84202b80668764057f394 100644 (file)
@@ -19,11 +19,11 @@ fn assert_panics<F>(f: F)
     let f = panic::AssertUnwindSafe(f);
     let result = panic::catch_unwind(move || {
         //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+        //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f` to be fully captured
         f.0()
-        //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
     });
     if let Ok(..) = result {
         panic!("diverging function returned");
index acd9fb654e5e0b18ce829578ddfed0e3bea0afeb..b6ee5edb59e7925168f6117caa0b2228258565ca 100644 (file)
@@ -2,10 +2,10 @@ error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnw
   --> $DIR/mir_calls_to_shims.rs:20:38
    |
 LL |     let result = panic::catch_unwind(move || {
-   |                                      ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+   |                                      ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
 ...
 LL |         f.0()
-   |         --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+   |         --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
    |
 note: the lint level is defined here
   --> $DIR/mir_calls_to_shims.rs:3:9
@@ -15,12 +15,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f` to be fully captured
    |
-LL ~     let result = panic::catch_unwind(move || { let _ = &f; 
+LL ~     let result = panic::catch_unwind(move || {
+LL +         let _ = &f;
 LL +
 LL +
 LL +
 LL +
-LL +         f.0()
  ...
 
 error: aborting due to previous error
index 98f578abc44dcc1cac03f97d0b8c0fd7da012528..ef90257474a9f78eb9da9e65d5b1823fa8ff5ead 100644 (file)
@@ -20,32 +20,34 @@ impl Clone for U {
 fn test_multi_issues() {
     let f1 = U(S(String::from("foo")), T(0));
     let f2 = U(S(String::from("bar")), T(0));
-    let c = || { let _ = (&f1, &f2); 
+    let c = || {
+        let _ = (&f1, &f2);
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f2.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
     };
 
     let c_clone = c.clone();
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
 
 fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(String::from("foo")), T(0));
-    let c = || { let _ = &f1; 
+    let c = || {
+        let _ = &f1;
         //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f1.1;
     };
 
@@ -64,16 +66,17 @@ impl Clone for U1 {
 
 fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
-    let c = || { let _ = &f1; 
+    let c = || {
+        let _ = &f1;
         //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f1.2;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
     };
 
     let c_clone = c.clone();
@@ -83,23 +86,24 @@ fn test_capturing_several_disjoint_fields_individually_1() {
 
 fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
-    let c = || { let _ = &f1; 
+    let c = || {
+        let _ = &f1;
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_1 = f1.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
     };
 
     let c_clone = c.clone();
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
 
 struct SendPointer(*mut i32);
 unsafe impl Send for SendPointer {}
@@ -118,14 +122,14 @@ fn test_multi_traits_issues() {
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
         //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
         *fptr2.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
     } });
 }
 
index 1577b91c960185a04f71084cbd96ae9c72301190..b9644c18d28e28465ee5a40e3de4eefa1318c0f8 100644 (file)
@@ -22,30 +22,30 @@ fn test_multi_issues() {
     let f2 = U(S(String::from("bar")), T(0));
     let c = || {
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
         let _f_1 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f2.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
     };
 
     let c_clone = c.clone();
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
 
 fn test_capturing_all_disjoint_fields_individually() {
     let f1 = U(S(String::from("foo")), T(0));
     let c = || {
         //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_1 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f1.1;
     };
 
@@ -66,14 +66,14 @@ fn test_capturing_several_disjoint_fields_individually_1() {
     let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
     let c = || {
         //~^ ERROR: `Clone` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_2 = f1.2;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
     };
 
     let c_clone = c.clone();
@@ -85,21 +85,21 @@ fn test_capturing_several_disjoint_fields_individually_2() {
     let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
     let c = || {
         //~^ ERROR: `Clone` trait implementation for closure and drop order
-        //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+        //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `f1` to be fully captured
         let _f_0 = f1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
         let _f_1 = f1.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
     };
 
     let c_clone = c.clone();
 
     c_clone();
 }
-//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
 
 struct SendPointer(*mut i32);
 unsafe impl Send for SendPointer {}
@@ -118,14 +118,14 @@ fn test_multi_traits_issues() {
     let fptr2 = SendPointer(&mut f2 as *mut i32);
     thread::spawn(move || unsafe {
         //~^ ERROR: `Sync`, `Send` trait implementation for closure
-        //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-        //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+        //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
         *fptr1.0.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
         *fptr2.0 = 20;
-        //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
     });
 }
 
index b347516c95ce468738f3a5ffc2aa164dc70b1245..b887b212e3d45dc8c57cadeb6c161f8b1c909b43 100644 (file)
@@ -2,16 +2,16 @@ error: changes to closure capture in Rust 2021 will affect `Clone` trait impleme
   --> $DIR/multi_diagnostics.rs:23:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
 LL |
 LL |         let _f_2 = f2.1;
-   |                    ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+   |                    ---- in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
 ...
 LL | }
-   | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+   | - in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/multi_diagnostics.rs:2:9
@@ -21,32 +21,32 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f1`, `f2` to be fully captured
    |
-LL ~     let c = || { let _ = (&f1, &f2); 
+LL ~     let c = || {
+LL +         let _ = (&f1, &f2);
 LL +
 LL +
 LL +
 LL +
-LL +         let _f_1 = f1.0;
  ...
 
 error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
   --> $DIR/multi_diagnostics.rs:42:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
 ...
 LL |         let _f_1 = f1.0;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f1` to be fully captured
    |
-LL ~     let c = || { let _ = &f1; 
+LL ~     let c = || {
+LL +         let _ = &f1;
 LL +
 LL +
 LL +
 LL +
-LL +         let _f_1 = f1.0;
  ...
 
 error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
@@ -55,20 +55,20 @@ error: changes to closure capture in Rust 2021 will affect `Clone` trait impleme
 LL |     let c = || {
    |             ^^
    |             |
-   |             in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
-   |             in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
 LL |
 LL |         let _f_2 = f1.2;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f1` to be fully captured
    |
-LL ~     let c = || { let _ = &f1; 
-LL +
+LL ~     let c = || {
+LL +         let _ = &f1;
 LL +
 LL +
 LL +
@@ -79,29 +79,29 @@ error: changes to closure capture in Rust 2021 will affect `Clone` trait impleme
   --> $DIR/multi_diagnostics.rs:86:13
    |
 LL |     let c = || {
-   |             ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+   |             ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
 ...
 LL |         let _f_0 = f1.0;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
 LL |
 LL |         let _f_1 = f1.1;
-   |                    ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+   |                    ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
-   | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+   | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
+   | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `f1` to be fully captured
    |
-LL ~     let c = || { let _ = &f1; 
+LL ~     let c = || {
+LL +         let _ = &f1;
 LL +
 LL +
 LL +
 LL +
-LL +         let _f_0 = f1.0;
  ...
 
 error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
@@ -110,14 +110,14 @@ error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait
 LL |     thread::spawn(move || unsafe {
    |                   ^^^^^^^^^^^^^^
    |                   |
-   |                   in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
-   |                   in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+   |                   in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+   |                   in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
 ...
 LL |         *fptr1.0.0 = 20;
-   |         ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+   |         ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
 LL |
 LL |         *fptr2.0 = 20;
-   |         -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+   |         -------- in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
index 226172fb93eb12575d2bdea6e081dafa66f68076..7892a72c76523a97ab901821b06f65ef80cca328 100644 (file)
@@ -17,18 +17,19 @@ struct ConstainsDropField(Foo, Foo);
 fn test_precise_analysis_drop_paths_not_captured_by_move() {
     let t = ConstainsDropField(Foo(10), Foo(20));
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t = &t.1;
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 struct S;
 impl Drop for S {
@@ -42,23 +43,24 @@ struct U(T, T);
 fn test_precise_analysis_long_path_missing() {
     let u = U(T(S, S), T(S, S));
 
-    let c = || { let _ = &u; 
+    let c = || {
+        let _ = &u;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `u` to be fully captured
         let _x = u.0.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
         let _x = u.0.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
         let _x = u.1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
 
 
 fn main() {
index 7035abe6de0a29ef3d37275431ddf7f318a12d8f..f5e99002bd08a4a943110b9e25228e5daaf4bf5e 100644 (file)
@@ -22,13 +22,13 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t = &t.1;
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 struct S;
 impl Drop for S {
@@ -47,18 +47,18 @@ fn test_precise_analysis_long_path_missing() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `u` to be fully captured
         let _x = u.0.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
         let _x = u.0.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
         let _x = u.1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
 
 
 fn main() {
index 494d7e8e84236a07ae00608734522f014e1b0ff5..51b4e11819f4554850ffd713f7e594b4c89d9de6 100644 (file)
@@ -5,10 +5,10 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/precise.rs:3:9
@@ -18,12 +18,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -33,30 +33,30 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _x = u.0.0;
-   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+   |                  ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
 LL |
 LL |         let _x = u.0.1;
-   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+   |                  ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
 LL |
 LL |         let _x = u.1.0;
-   |                  ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+   |                  ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
-   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
-   | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+   | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+   | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+   | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `u` to be fully captured
    |
-LL ~     let c = || { let _ = &u; 
+LL ~     let c = || {
+LL +         let _ = &u;
 LL +
 LL +
 LL +
 LL +         let _x = u.0.0;
-LL +
  ...
 
 error: aborting due to 2 previous errors
index 236fdb9e26ea2b3972400e0e992529c7f356b8e2..aca0b2a96ac56bc2b6a6cc5fdb2ec0b73a474222 100644 (file)
@@ -22,23 +22,24 @@ fn test1_all_need_migration() {
     let t1 = (Foo(0), Foo(0));
     let t2 = (Foo(0), Foo(0));
 
-    let c = || { let _ = (&t, &t1, &t2); 
+    let c = || {
+        let _ = (&t, &t1, &t2);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -47,39 +48,41 @@ fn test2_only_precise_paths_need_migration() {
     let t1 = (Foo(0), Foo(0));
     let t2 = (Foo(0), Foo(0));
 
-    let c = || { let _ = (&t, &t1); 
+    let c = || {
+        let _ = (&t, &t1);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
 fn test3_only_by_value_need_migration() {
     let t = (Foo(0), Foo(0));
     let t1 = (Foo(0), Foo(0));
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         println!("{:?}", t1.1);
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // The root variable might not implement drop themselves but some path starting
 // at the root variable might implement Drop.
@@ -88,17 +91,18 @@ fn test3_only_by_value_need_migration() {
 fn test4_type_contains_drop_need_migration() {
     let t = ConstainsDropField(Foo(0), Foo(0));
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -106,33 +110,35 @@ fn test4_type_contains_drop_need_migration() {
 fn test5_drop_non_drop_aggregate_need_migration() {
     let t = (Foo(0), Foo(0), 0i32);
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Test migration analysis in case of Significant and Insignificant Drop aggregates.
 fn test6_significant_insignificant_drop_aggregate_need_migration() {
     let t = (Foo(0), String::new());
 
-    let c = || { let _ = &t; 
+    let c = || {
+        let _ = &t;
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -140,19 +146,20 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
     let t = (Foo(0), Foo(0));
     let t1 = (Foo(0), Foo(0), Foo(0));
 
-    let c = move || { let _ = (&t1, &t); 
+    let c = move || {
+        let _ = (&t1, &t);
         //~^ ERROR: drop order
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{:?} {:?}", t1.1, t.1);
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
-        //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
+        //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
 
 
 fn test8_drop_order_and_blocks() {
@@ -160,17 +167,18 @@ fn test8_drop_order_and_blocks() {
         let tuple =
           (String::from("foo"), String::from("bar"));
         {
-            let c = || { let _ = &tuple; 
+            let c = || {
+                let _ = &tuple;
                 //~^ ERROR: drop order
                 //~| NOTE: for more information, see
                 //~| HELP: add a dummy let to cause `tuple` to be fully captured
                 tuple.0;
-                //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+                //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
             };
 
             c();
         }
-        //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+        //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
     }
 }
 
@@ -178,17 +186,18 @@ fn test9_drop_order_and_nested_closures() {
     let tuple =
         (String::from("foo"), String::from("bar"));
     let b = || {
-        let c = || { let _ = &tuple; 
+        let c = || {
+            let _ = &tuple;
             //~^ ERROR: drop order
             //~| NOTE: for more information, see
             //~| HELP: add a dummy let to cause `tuple` to be fully captured
             tuple.0;
-            //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+            //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
         };
 
         c();
     };
-    //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+    //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
 
     b();
 }
index a57f7aa565e120788fd2994648d502bc7fc8125e..fd4134a7704793daacf70bf73b243ee027b0a782 100644 (file)
@@ -27,18 +27,18 @@ fn test1_all_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
 
 // String implements drop and therefore should be migrated.
 // But in this test cases, `t2` is completely captured and when it is dropped won't be affected
@@ -52,16 +52,16 @@ fn test2_only_precise_paths_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         let _t1 = t1.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
         let _t2 = t2;
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
 
 // If a variable would've not been captured by value then it would've not been
 // dropped with the closure and therefore doesn't need migration.
@@ -73,13 +73,13 @@ fn test3_only_by_value_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
         println!("{:?}", t1.1);
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // The root variable might not implement drop themselves but some path starting
 // at the root variable might implement Drop.
@@ -93,12 +93,12 @@ fn test4_type_contains_drop_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Test migration analysis in case of Drop + Non Drop aggregates.
 // Note we need migration here only because the non-copy (because Drop type) is captured,
@@ -111,12 +111,12 @@ fn test5_drop_non_drop_aggregate_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.0;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
 
 // Test migration analysis in case of Significant and Insignificant Drop aggregates.
 fn test6_significant_insignificant_drop_aggregate_need_migration() {
@@ -127,12 +127,12 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t` to be fully captured
         let _t = t.1;
-        //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
 
 // Since we are using a move closure here, both `t` and `t1` get moved
 // even though they are being used by ref inside the closure.
@@ -145,14 +145,14 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
         //~| NOTE: for more information, see
         //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
         println!("{:?} {:?}", t1.1, t.1);
-        //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
-        //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+        //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
+        //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
     };
 
     c();
 }
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
 
 
 fn test8_drop_order_and_blocks() {
@@ -165,12 +165,12 @@ fn test8_drop_order_and_blocks() {
                 //~| NOTE: for more information, see
                 //~| HELP: add a dummy let to cause `tuple` to be fully captured
                 tuple.0;
-                //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+                //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
             };
 
             c();
         }
-        //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+        //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
     }
 }
 
@@ -183,12 +183,12 @@ fn test9_drop_order_and_nested_closures() {
             //~| NOTE: for more information, see
             //~| HELP: add a dummy let to cause `tuple` to be fully captured
             tuple.0;
-            //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+            //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
         };
 
         c();
     };
-    //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+    //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
 
     b();
 }
index 32afc07af7968a5bdb375fada8bf160f3bada8de..81700e32b5f40d0e8869d7af740a49e67125400b 100644 (file)
@@ -5,20 +5,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 LL |
 LL |         let _t1 = t1.0;
-   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+   |                   ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
 LL |
 LL |         let _t2 = t2.0;
-   |                   ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+   |                   ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-   | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+   | in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
    |
 note: the lint level is defined here
   --> $DIR/significant_drop.rs:2:9
@@ -28,12 +28,12 @@ LL | #![deny(rust_2021_incompatible_closure_captures)]
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
    |
-LL ~     let c = || { let _ = (&t, &t1, &t2); 
+LL ~     let c = || {
+LL +         let _ = (&t, &t1, &t2);
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -43,26 +43,26 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 LL |
 LL |         let _t1 = t1.0;
-   |                   ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+   |                   ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t`, `t1` to be fully captured
    |
-LL ~     let c = || { let _ = (&t, &t1); 
+LL ~     let c = || {
+LL +         let _ = (&t, &t1);
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -72,20 +72,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -95,20 +95,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -118,20 +118,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.0;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -141,20 +141,20 @@ LL |     let c = || {
    |             ^^
 ...
 LL |         let _t = t.1;
-   |                  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
 ...
 LL | }
-   | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+   | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t` to be fully captured
    |
-LL ~     let c = || { let _ = &t; 
+LL ~     let c = || {
+LL +         let _ = &t;
 LL +
 LL +
 LL +
 LL +         let _t = t.1;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -164,25 +164,25 @@ LL |     let c = move || {
    |             ^^^^^^^
 ...
 LL |         println!("{:?} {:?}", t1.1, t.1);
-   |                               ----  --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+   |                               ----  --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
    |                               |
-   |                               in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+   |                               in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
 ...
 LL | }
    | -
    | |
-   | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
-   | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+   | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
+   | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `t1`, `t` to be fully captured
    |
-LL ~     let c = move || { let _ = (&t1, &t); 
+LL ~     let c = move || {
+LL +         let _ = (&t1, &t);
 LL +
 LL +
 LL +
 LL +         println!("{:?} {:?}", t1.1, t.1);
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -192,20 +192,20 @@ LL |             let c = || {
    |                     ^^
 ...
 LL |                 tuple.0;
-   |                 ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+   |                 ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
 ...
 LL |         }
-   |         - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+   |         - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `tuple` to be fully captured
    |
-LL ~             let c = || { let _ = &tuple; 
+LL ~             let c = || {
+LL +                 let _ = &tuple;
 LL +
 LL +
 LL +
 LL +                 tuple.0;
-LL +
  ...
 
 error: changes to closure capture in Rust 2021 will affect drop order
@@ -215,20 +215,20 @@ LL |         let c = || {
    |                 ^^
 ...
 LL |             tuple.0;
-   |             ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+   |             ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
 ...
 LL |     };
-   |     - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+   |     - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
 help: add a dummy let to cause `tuple` to be fully captured
    |
-LL ~         let c = || { let _ = &tuple; 
+LL ~         let c = || {
+LL +             let _ = &tuple;
 LL +
 LL +
 LL +
 LL +             tuple.0;
-LL +
  ...
 
 error: aborting due to 9 previous errors
index 93321ac536ab916c47b6db1b3ae592da9c6d8a2a..4df443c66d65bc0b2339b0e9a89b17f7663ecc8c 100644 (file)
@@ -15,7 +15,18 @@ fn has_clone3() -> bool {
     let err = (res == -1)
         .then(|| Error::last_os_error())
         .expect("probe syscall should not succeed");
-    err.raw_os_error() != Some(libc::ENOSYS)
+
+    // If the `clone3` syscall is not implemented in the current kernel version it should return an
+    // `ENOSYS` error. Docker also blocks the whole syscall inside unprivileged containers, and
+    // returns `EPERM` (instead of `ENOSYS`) when a program tries to invoke the syscall. Because of
+    // that we need to check for *both* `ENOSYS` and `EPERM`.
+    //
+    // Note that Docker's behavior is breaking other projects (notably glibc), so they're planning
+    // to update their filtering to return `ENOSYS` in a future release:
+    //
+    //     https://github.com/moby/moby/issues/42680
+    //
+    err.raw_os_error() != Some(libc::ENOSYS) && err.raw_os_error() != Some(libc::EPERM)
 }
 
 fn main() {
index 1707640f6edec273c2e9e9d6fde365a61b1952e1..380c17c8e62bbcb98b7ecf589c1a9beb12e84001 100644 (file)
@@ -139,7 +139,7 @@ LL |     foo::<BAR + BAR>();
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0747]: type provided when a constant was expected
   --> $DIR/const-expression-suggest-missing-braces.rs:11:11
index 30f09e22792167ea0a9151c9a4430713810fb8c0..c9bb08cf35c1dc3111962c2650683b36ce345be5 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #[deny(bare_trait_objects)]
    |        ^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: trait objects without an explicit `dyn` are deprecated
   --> $DIR/dyn-2018-edition-lint.rs:4:35
@@ -19,7 +19,7 @@ LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
    |                                   ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: trait objects without an explicit `dyn` are deprecated
   --> $DIR/dyn-2018-edition-lint.rs:9:14
@@ -28,7 +28,7 @@ LL |     let _x: &SomeTrait = todo!();
    |              ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to 3 previous errors
 
index 69fed2cb69ad8898a240b80f59f9cb05f7616d02..1f7f0d8f6be6ae72c93d62814c3296dc4c807350 100644 (file)
@@ -5,7 +5,7 @@ fn main() {
     a");
     //~^ ERROR invalid format string
     format!("{ \
-
+               \
     b");
     //~^ ERROR invalid format string
     format!(r#"{ \
@@ -38,12 +38,12 @@ fn main() {
     { \
        \
     b \
-
+      \
     ");
     //~^^^ ERROR invalid format string
     format!(r#"
 raw  { \
-
+       \
     c"#);
     //~^^^ ERROR invalid format string
     format!(r#"
index c421fe49ef0a4897c9b035b04e5841976dc5a372..76cdfbb93bf24cad988434f806f096698cd8a0c6 100644 (file)
@@ -19,7 +19,7 @@ error: invalid format string: expected `'}'`, found `'b'`
    |
 LL |     format!("{ \
    |              - because of this opening brace
-LL | 
+LL |                \
 LL |     b");
    |     ^ expected `}` in format string
    |
index d557802bbd941d930f2d468d4e622d4d2de629ec..5e0f98c0bbf0a73caf33193f69b6504a2f2ede88 100644 (file)
@@ -18,7 +18,7 @@ LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {}
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
   --> $DIR/gat-trait-path-parenthesised-args.rs:7:27
index d5e9caf9ecd4e3f0bc2a15cd7300791bf2fcf013..345e2b3fcb12ca1fcf8d61b2d920b455462874dc 100644 (file)
@@ -1,11 +1,11 @@
 error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
-  --> $DIR/projection-bound-cycle-generic.rs:44:5
+  --> $DIR/projection-bound-cycle-generic.rs:44:18
    |
 LL | struct OnlySized<T> where T: Sized { f: T }
    |                  - required by this bound in `OnlySized`
 ...
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index fac62fef1ecff0094f9a50ad0259babd5dde441d..eefc09fa78863bfcfbd1427e4f5f306562d35081 100644 (file)
@@ -1,11 +1,11 @@
 error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
-  --> $DIR/projection-bound-cycle.rs:46:5
+  --> $DIR/projection-bound-cycle.rs:46:18
    |
 LL | struct OnlySized<T> where T: Sized { f: T }
    |                  - required by this bound in `OnlySized`
 ...
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 0497bd20469a0e6bddaea19c5f4c408773890ca4..67f6b3081bb3042603362155ebce71f855f7bace 100644 (file)
@@ -1,8 +1,8 @@
 error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
-  --> $DIR/issue-21946.rs:8:5
+  --> $DIR/issue-21946.rs:8:14
    |
 LL |     type A = <FooStruct as Foo>::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 8613c1ef8c201e2982293d726029bb64e5fe9ea8..0b568b30e08d8dab9e7e3c6e25dc835746f4c4f0 100644 (file)
@@ -1,8 +1,8 @@
 error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
-  --> $DIR/issue-23122-1.rs:10:5
+  --> $DIR/issue-23122-1.rs:10:17
    |
 LL |     type Next = <GetNext<T> as Next>::Next;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 5008a499986d43510a3c1ff8e11c51af82a6b31f..68a95dc265e821bc155fd880e1d0405336f16f89 100644 (file)
@@ -1,8 +1,8 @@
 error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:9:5
+  --> $DIR/issue-23122-2.rs:9:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
 note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
index 9ff4e3167a11e06d454174ec2004decc26a9635a..0d576909a35692089e8e28eab72812a53ee95c4c 100644 (file)
@@ -22,7 +22,7 @@ LL |     eq::<dyn, Foo>
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0107]: missing generics for trait `Foo`
   --> $DIR/issue-86756.rs:5:15
index 72a1c3cdd35a5c39ac14d0f33422865d05ab4cf7..e9780d9b165c765239b84e22641bf7e8f729ca16 100644 (file)
@@ -6,7 +6,7 @@ LL |     let _: Iter<'_, i32> = array.into_iter();
    |
    = note: `#[warn(array_into_iter)]` on by default
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     let _: Iter<'_, i32> = array.iter();
@@ -23,7 +23,7 @@ LL |     let _: Iter<'_, i32> = Box::new(array).into_iter();
    |                                            ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     let _: Iter<'_, i32> = Box::new(array).iter();
@@ -40,7 +40,7 @@ LL |     for _ in [1, 2, 3].into_iter() {}
    |                        ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     for _ in [1, 2, 3].iter() {}
index 0959d351ece92474a8d21cc33c53cc2a5287801c..138becc4ffe1ea6cca92202c562eb708ce8cc96c 100644 (file)
@@ -6,7 +6,7 @@ LL |     small.into_iter();
    |
    = note: `#[warn(array_into_iter)]` on by default
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     small.iter();
@@ -23,7 +23,7 @@ LL |     [1, 2].into_iter();
    |            ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     [1, 2].iter();
@@ -40,7 +40,7 @@ LL |     big.into_iter();
    |         ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     big.iter();
@@ -57,7 +57,7 @@ LL |     [0u8; 33].into_iter();
    |               ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     [0u8; 33].iter();
@@ -74,7 +74,7 @@ LL |     Box::new(small).into_iter();
    |                     ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(small).iter();
@@ -91,7 +91,7 @@ LL |     Box::new([1, 2]).into_iter();
    |                      ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new([1, 2]).iter();
@@ -108,7 +108,7 @@ LL |     Box::new(big).into_iter();
    |                   ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(big).iter();
@@ -125,7 +125,7 @@ LL |     Box::new([0u8; 33]).into_iter();
    |                         ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new([0u8; 33]).iter();
@@ -142,7 +142,7 @@ LL |     Box::new(Box::new(small)).into_iter();
    |                               ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(Box::new(small)).iter();
@@ -159,7 +159,7 @@ LL |     Box::new(Box::new([1, 2])).into_iter();
    |                                ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(Box::new([1, 2])).iter();
@@ -176,7 +176,7 @@ LL |     Box::new(Box::new(big)).into_iter();
    |                             ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(Box::new(big)).iter();
@@ -193,7 +193,7 @@ LL |     Box::new(Box::new([0u8; 33])).into_iter();
    |                                   ^^^^^^^^^
    |
    = warning: this changes meaning in Rust 2021
-   = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
    |
 LL |     Box::new(Box::new([0u8; 33])).iter();
diff --git a/src/test/ui/layout/thumb-enum.rs b/src/test/ui/layout/thumb-enum.rs
new file mode 100644 (file)
index 0000000..3b43b1b
--- /dev/null
@@ -0,0 +1,34 @@
+// compile-flags: --target thumbv8m.main-none-eabihf
+// needs-llvm-components: arm
+//
+// Verify that thumb targets implement the repr(C) for enums correctly.
+//
+// See #87917
+#![feature(never_type, rustc_attrs, no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum A { Apple } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum B { Banana = 255, } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum C { Chaenomeles = 256, } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of
+
+const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
diff --git a/src/test/ui/layout/thumb-enum.stderr b/src/test/ui/layout/thumb-enum.stderr
new file mode 100644 (file)
index 0000000..898a61b
--- /dev/null
@@ -0,0 +1,442 @@
+error: layout_of(A) = Layout {
+    fields: Arbitrary {
+        offsets: [
+            Size {
+                raw: 0,
+            },
+        ],
+        memory_index: [
+            0,
+        ],
+    },
+    variants: Multiple {
+        tag: Scalar {
+            value: Int(
+                I8,
+                false,
+            ),
+            valid_range: 0..=0,
+        },
+        tag_encoding: Direct,
+        tag_field: 0,
+        variants: [
+            Layout {
+                fields: Arbitrary {
+                    offsets: [],
+                    memory_index: [],
+                },
+                variants: Single {
+                    index: 0,
+                },
+                abi: Aggregate {
+                    sized: true,
+                },
+                largest_niche: None,
+                align: AbiAndPrefAlign {
+                    abi: Align {
+                        pow2: 0,
+                    },
+                    pref: Align {
+                        pow2: 2,
+                    },
+                },
+                size: Size {
+                    raw: 1,
+                },
+            },
+        ],
+    },
+    abi: Scalar(
+        Scalar {
+            value: Int(
+                I8,
+                false,
+            ),
+            valid_range: 0..=0,
+        },
+    ),
+    largest_niche: Some(
+        Niche {
+            offset: Size {
+                raw: 0,
+            },
+            scalar: Scalar {
+                value: Int(
+                    I8,
+                    false,
+                ),
+                valid_range: 0..=0,
+            },
+        },
+    ),
+    align: AbiAndPrefAlign {
+        abi: Align {
+            pow2: 0,
+        },
+        pref: Align {
+            pow2: 2,
+        },
+    },
+    size: Size {
+        raw: 1,
+    },
+}
+  --> $DIR/thumb-enum.rs:16:1
+   |
+LL | enum A { Apple }
+   | ^^^^^^^^^^^^^^^^
+
+error: layout_of(B) = Layout {
+    fields: Arbitrary {
+        offsets: [
+            Size {
+                raw: 0,
+            },
+        ],
+        memory_index: [
+            0,
+        ],
+    },
+    variants: Multiple {
+        tag: Scalar {
+            value: Int(
+                I8,
+                false,
+            ),
+            valid_range: 255..=255,
+        },
+        tag_encoding: Direct,
+        tag_field: 0,
+        variants: [
+            Layout {
+                fields: Arbitrary {
+                    offsets: [],
+                    memory_index: [],
+                },
+                variants: Single {
+                    index: 0,
+                },
+                abi: Aggregate {
+                    sized: true,
+                },
+                largest_niche: None,
+                align: AbiAndPrefAlign {
+                    abi: Align {
+                        pow2: 0,
+                    },
+                    pref: Align {
+                        pow2: 2,
+                    },
+                },
+                size: Size {
+                    raw: 1,
+                },
+            },
+        ],
+    },
+    abi: Scalar(
+        Scalar {
+            value: Int(
+                I8,
+                false,
+            ),
+            valid_range: 255..=255,
+        },
+    ),
+    largest_niche: Some(
+        Niche {
+            offset: Size {
+                raw: 0,
+            },
+            scalar: Scalar {
+                value: Int(
+                    I8,
+                    false,
+                ),
+                valid_range: 255..=255,
+            },
+        },
+    ),
+    align: AbiAndPrefAlign {
+        abi: Align {
+            pow2: 0,
+        },
+        pref: Align {
+            pow2: 2,
+        },
+    },
+    size: Size {
+        raw: 1,
+    },
+}
+  --> $DIR/thumb-enum.rs:20:1
+   |
+LL | enum B { Banana = 255, }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(C) = Layout {
+    fields: Arbitrary {
+        offsets: [
+            Size {
+                raw: 0,
+            },
+        ],
+        memory_index: [
+            0,
+        ],
+    },
+    variants: Multiple {
+        tag: Scalar {
+            value: Int(
+                I16,
+                false,
+            ),
+            valid_range: 256..=256,
+        },
+        tag_encoding: Direct,
+        tag_field: 0,
+        variants: [
+            Layout {
+                fields: Arbitrary {
+                    offsets: [],
+                    memory_index: [],
+                },
+                variants: Single {
+                    index: 0,
+                },
+                abi: Aggregate {
+                    sized: true,
+                },
+                largest_niche: None,
+                align: AbiAndPrefAlign {
+                    abi: Align {
+                        pow2: 1,
+                    },
+                    pref: Align {
+                        pow2: 2,
+                    },
+                },
+                size: Size {
+                    raw: 2,
+                },
+            },
+        ],
+    },
+    abi: Scalar(
+        Scalar {
+            value: Int(
+                I16,
+                false,
+            ),
+            valid_range: 256..=256,
+        },
+    ),
+    largest_niche: Some(
+        Niche {
+            offset: Size {
+                raw: 0,
+            },
+            scalar: Scalar {
+                value: Int(
+                    I16,
+                    false,
+                ),
+                valid_range: 256..=256,
+            },
+        },
+    ),
+    align: AbiAndPrefAlign {
+        abi: Align {
+            pow2: 1,
+        },
+        pref: Align {
+            pow2: 2,
+        },
+    },
+    size: Size {
+        raw: 2,
+    },
+}
+  --> $DIR/thumb-enum.rs:24:1
+   |
+LL | enum C { Chaenomeles = 256, }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(P) = Layout {
+    fields: Arbitrary {
+        offsets: [
+            Size {
+                raw: 0,
+            },
+        ],
+        memory_index: [
+            0,
+        ],
+    },
+    variants: Multiple {
+        tag: Scalar {
+            value: Int(
+                I32,
+                false,
+            ),
+            valid_range: 268435456..=268435456,
+        },
+        tag_encoding: Direct,
+        tag_field: 0,
+        variants: [
+            Layout {
+                fields: Arbitrary {
+                    offsets: [],
+                    memory_index: [],
+                },
+                variants: Single {
+                    index: 0,
+                },
+                abi: Aggregate {
+                    sized: true,
+                },
+                largest_niche: None,
+                align: AbiAndPrefAlign {
+                    abi: Align {
+                        pow2: 2,
+                    },
+                    pref: Align {
+                        pow2: 2,
+                    },
+                },
+                size: Size {
+                    raw: 4,
+                },
+            },
+        ],
+    },
+    abi: Scalar(
+        Scalar {
+            value: Int(
+                I32,
+                false,
+            ),
+            valid_range: 268435456..=268435456,
+        },
+    ),
+    largest_niche: Some(
+        Niche {
+            offset: Size {
+                raw: 0,
+            },
+            scalar: Scalar {
+                value: Int(
+                    I32,
+                    false,
+                ),
+                valid_range: 268435456..=268435456,
+            },
+        },
+    ),
+    align: AbiAndPrefAlign {
+        abi: Align {
+            pow2: 2,
+        },
+        pref: Align {
+            pow2: 2,
+        },
+    },
+    size: Size {
+        raw: 4,
+    },
+}
+  --> $DIR/thumb-enum.rs:28:1
+   |
+LL | enum P { Peach = 0x1000_0000isize, }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(T) = Layout {
+    fields: Arbitrary {
+        offsets: [
+            Size {
+                raw: 0,
+            },
+        ],
+        memory_index: [
+            0,
+        ],
+    },
+    variants: Multiple {
+        tag: Scalar {
+            value: Int(
+                I32,
+                true,
+            ),
+            valid_range: 2164260864..=2164260864,
+        },
+        tag_encoding: Direct,
+        tag_field: 0,
+        variants: [
+            Layout {
+                fields: Arbitrary {
+                    offsets: [],
+                    memory_index: [],
+                },
+                variants: Single {
+                    index: 0,
+                },
+                abi: Aggregate {
+                    sized: true,
+                },
+                largest_niche: None,
+                align: AbiAndPrefAlign {
+                    abi: Align {
+                        pow2: 2,
+                    },
+                    pref: Align {
+                        pow2: 2,
+                    },
+                },
+                size: Size {
+                    raw: 4,
+                },
+            },
+        ],
+    },
+    abi: Scalar(
+        Scalar {
+            value: Int(
+                I32,
+                true,
+            ),
+            valid_range: 2164260864..=2164260864,
+        },
+    ),
+    largest_niche: Some(
+        Niche {
+            offset: Size {
+                raw: 0,
+            },
+            scalar: Scalar {
+                value: Int(
+                    I32,
+                    true,
+                ),
+                valid_range: 2164260864..=2164260864,
+            },
+        },
+    ),
+    align: AbiAndPrefAlign {
+        abi: Align {
+            pow2: 2,
+        },
+        pref: Align {
+            pow2: 2,
+        },
+    },
+    size: Size {
+        raw: 4,
+    },
+}
+  --> $DIR/thumb-enum.rs:34:1
+   |
+LL | enum T { Tangerine = TANGERINE as isize }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
index 40fafc4b3b59b7085334612994de57150f5c2b5f..3477b01b6b567374283133ef3028ee8826973a16 100644 (file)
@@ -12,7 +12,7 @@ LL |     Dyn::func();
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/bare-trait-objects-path.rs:17:5
@@ -21,7 +21,7 @@ LL |     ::Dyn::func();
    |     ^^^^^ help: use `dyn`: `<dyn (::Dyn)>`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/bare-trait-objects-path.rs:20:5
@@ -30,7 +30,7 @@ LL |     Dyn::CONST;
    |     ^^^ help: use `dyn`: `<dyn Dyn>`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to previous error; 3 warnings emitted
 
index 185c0e8e3d0eba88105739eb1e0821a59ba31dd5..c1ebdb9514bd479f8fefa7459ee3f88bccf67b92 100644 (file)
@@ -6,7 +6,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = note: requested on the command line with `--force-warn bare-trait-objects`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 1 warning emitted
 
index a89970587751d3ed94d8c82f8d80911942ec7839..8514956af743ef3852c2d7434c4f65e3353ab4da 100644 (file)
@@ -6,7 +6,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = note: requested on the command line with `--force-warn bare-trait-objects`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 1 warning emitted
 
index 1d5f88086c5c410c97bb0a6d79bcae15e42e27cc..3a0227463e69a564568b9393661df21667b5517e 100644 (file)
@@ -6,7 +6,7 @@ LL |         0...100 => true,
    |
    = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 1 warning emitted
 
index d242ef266b8d1a2e2f36ceeef1dd0225927086fe..29eba6d635f93848c21605743d8d9c8317666338 100644 (file)
@@ -6,7 +6,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 1 warning emitted
 
index 180dff880a65828356280598b923880db57b1045..54bee452cddad28621396e91c07f2c0d1a226fc4 100644 (file)
@@ -6,7 +6,7 @@ LL | pub fn function(_x: Box<SomeTrait>) {}
    |
    = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 1 warning emitted
 
index efa684a24e3d393c5fcba1e45cdc0d03ec21521d..91b8d2b5afc77e60078ca2863eb87dd2a1a060f9 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: `...` range patterns are deprecated
   --> $DIR/inclusive-range-pattern-syntax.rs:16:9
@@ -19,7 +19,7 @@ LL |         &1...2 => {}
    |         ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: 2 warnings emitted
 
index eb6204fa02e69221dc89aee8af589b70bbbc1d97..9a5b8009f32cd095a36f49ad080dc976babbfd16 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(rust_2021_incompatible_or_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
 
 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:13:23
@@ -19,7 +19,7 @@ LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
    |                       ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
 
 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:19:21
@@ -28,7 +28,7 @@ LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
    |                     ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
 
 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:23:26
@@ -37,7 +37,7 @@ LL |     ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
    |                          ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
 
 error: aborting due to 4 previous errors
 
index 77390aae2d688a0d87630bde952525821f62ad95..0de424ce279f3e4cb6cdbc33ebbb5bcc43c66664 100644 (file)
@@ -26,8 +26,8 @@ fn main() {
     fancy_panic::fancy_panic!("test {} 123");
     //~^ WARN panic message contains an unused formatting placeholder
 
-    fancy_panic::fancy_panic!(S);
-    //~^ WARN panic message is not a string literal
+    fancy_panic::fancy_panic!(); // OK
+    fancy_panic::fancy_panic!(S); // OK
 
     macro_rules! a {
         () => { 123 };
index 2c058f1f5a48435e653ebb2f69153c0214862b0b..4b18f5546b9b80121bfbe4bffeece9792f105b93 100644 (file)
@@ -180,15 +180,6 @@ LL |     fancy_panic::fancy_panic!("test {} 123");
    |
    = note: this message is not used as a format string when given without arguments, but will be in Rust 2021
 
-warning: panic message is not a string literal
-  --> $DIR/non-fmt-panic.rs:29:31
-   |
-LL |     fancy_panic::fancy_panic!(S);
-   |                               ^
-   |
-   = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
-
 warning: panic message is not a string literal
   --> $DIR/non-fmt-panic.rs:36:12
    |
@@ -285,5 +276,5 @@ help: or use std::panic::panic_any instead
 LL |     std::panic::panic_any(123);
    |     ~~~~~~~~~~~~~~~~~~~~~~   ~
 
-warning: 20 warnings emitted
+warning: 19 warnings emitted
 
index dce03e1a9635cf5e66b0f937fafdbda442503de8..1a64b9a017d519546c8d33aac3b429ebccaa956f 100644 (file)
@@ -12,7 +12,7 @@ LL | type X<'a> = (?'a) +;
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/issue-68890-2.rs:3:14
index c10037d44e30d9f92b30431fb0dbb6b7e182efdd..6f26f36e7631591aeb17451876e54f5089d351ff 100644 (file)
@@ -35,7 +35,7 @@ LL | fn y<'a>(y: &mut 'a + Send) {
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/issue-73568-lifetime-after-mut.rs:19:23
@@ -44,7 +44,7 @@ LL |     let z = y as &mut 'a + Send;
    |                       ^^ help: use `dyn`: `dyn 'a`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/issue-73568-lifetime-after-mut.rs:14:18
index caca84f695d76d67a52890939974fb867e0bad78..876bfd389cb5dc8800e5e27572b60dce06de1dc6 100644 (file)
@@ -12,7 +12,7 @@ LL |     m!('static);
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0224]: at least one trait is required for an object type
   --> $DIR/trait-object-macro-matcher.rs:11:8
index 2d8088432a257a1890965432224e7851eb9fe537..762066825db29bb4e520ee4fadbb7245cf5b78c1 100644 (file)
@@ -205,7 +205,7 @@ note: the lint level is defined here
 LL | #![deny(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:45:13
@@ -214,7 +214,7 @@ LL |     if let 0...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:48:13
@@ -223,7 +223,7 @@ LL |     if let X...3 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:51:13
@@ -232,7 +232,7 @@ LL |     if let X...Y = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:54:16
@@ -241,7 +241,7 @@ LL |     if let true...Y = 0 {}
    |                ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:57:13
@@ -250,7 +250,7 @@ LL |     if let X...true = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:60:14
@@ -259,7 +259,7 @@ LL |     if let .0...Y = 0 {}
    |              ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:64:13
@@ -268,7 +268,7 @@ LL |     if let X... .0 = 0 {}
    |             ^^^ help: use `..=` for an inclusive range
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: `...` range patterns are deprecated
   --> $DIR/recover-range-pats.rs:138:20
@@ -280,7 +280,7 @@ LL |     mac2!(0, 1);
    |     ------------ in this macro invocation
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
    = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0029]: only `char` and numeric types are allowed in range patterns
index 9bfc4943fe9414c3338a82c66e522f357d885456..b39fe4646a3cc3fe5fc367128491b3a89b1cb628 100644 (file)
@@ -24,7 +24,7 @@ LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/trait-object-trait-parens.rs:13:16
@@ -33,7 +33,7 @@ LL |     let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn ?Sized + (for<'a> Trait<'a>) + (Obj)`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/trait-object-trait-parens.rs:18:16
@@ -42,7 +42,7 @@ LL |     let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn for<'a> Trait<'a> + (Obj) + (?Sized)`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-object-trait-parens.rs:8:35
index 3330ced1ebf341aeebb65ee6b145b741de95542a..8af1a570253a2cb611e7325dcee79f3a76919f10 100644 (file)
@@ -16,7 +16,7 @@ note: the lint level is defined here
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to previous error; 1 warning emitted
 
index 90a4aa68222f64f16a58bd56e3f3d335d2eae893..009273c74350b214d1b70725cfb53f5d81b61df4 100644 (file)
@@ -16,7 +16,7 @@ note: the lint level is defined here
 LL | #![warn(ellipsis_inclusive_range_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to previous error; 1 warning emitted
 
index dfa44008ad7840efe9d5ce0a0c9550899a186703..09b51fe0568707684e4c7d9cd0edf748da12ad8d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:9
+  --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:20
    |
 LL |         type Out = &'a Foo<'b>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
   --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10
index 3561379138b9b2264447a676327d61530f3e46ed..957a9d6dd3c1243876fc9547da9b2a09d6656fef 100644 (file)
@@ -1,8 +1,8 @@
 error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-nominal-type-region.rs:17:9
+  --> $DIR/regions-outlives-nominal-type-region.rs:17:20
    |
 LL |         type Out = &'a Foo<'b>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
   --> $DIR/regions-outlives-nominal-type-region.rs:16:10
index 207686defa1ac6a8c55aca9a2d93be2515f6eec3..1589f93d90c8ea184b08b1bb5287292da796c0ad 100644 (file)
@@ -1,8 +1,8 @@
 error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:9
+  --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:20
    |
 LL |         type Out = &'a Foo<&'b i32>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
   --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10
index c1c4e78f785c35eed291bcac9c688f82ed10cb27..4bfaa1aac782aaa51dd9452cf3fca5e849e3419e 100644 (file)
@@ -1,8 +1,8 @@
 error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-outlives-nominal-type-type.rs:17:9
+  --> $DIR/regions-outlives-nominal-type-type.rs:17:20
    |
 LL |         type Out = &'a Foo<&'b i32>;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
   --> $DIR/regions-outlives-nominal-type-type.rs:16:10
index 71caeefabac3468cb3fc39538c07e8ceca6f3217..1b1a2f7b043b76ea150d981b883303598e6d81ad 100644 (file)
@@ -1,18 +1,18 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-struct-not-wf.rs:13:5
+  --> $DIR/regions-struct-not-wf.rs:13:16
    |
 LL | impl<'a, T> Trait<'a, T> for usize {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a T;
-   |     ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+   |                ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/regions-struct-not-wf.rs:21:5
+  --> $DIR/regions-struct-not-wf.rs:21:16
    |
 LL | impl<'a, T> Trait<'a, T> for u32 {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = RefOk<'a, T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+   |                ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
    |
 note: ...that is required by this bound
   --> $DIR/regions-struct-not-wf.rs:16:20
@@ -21,10 +21,10 @@ LL | struct RefOk<'a, T:'a> {
    |                    ^^
 
 error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-struct-not-wf.rs:25:5
+  --> $DIR/regions-struct-not-wf.rs:25:16
    |
 LL |     type Out = &'a &'b T;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |                ^^^^^^^^^
    |
 note: the pointer is valid for the lifetime `'a` as defined on the impl at 24:6
   --> $DIR/regions-struct-not-wf.rs:24:6
index 2c6a63df42f2ce4b5041c8f099269eb0f6917975..0a722baa185cd60c8722cf1a98f34ae91df603fa 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prelude_collisions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-generic.rs:31:5
@@ -19,7 +19,7 @@ LL |     Generic::<i32, i32>::from_iter(1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-generic.rs:34:5
@@ -28,7 +28,7 @@ LL |     Generic::<_, _>::from_iter(1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: 3 warnings emitted
 
index 61975876819229bfbfc8fbe123f3b10a20eff4ad..fbda5d61f36dc070685b900b09c6e23ad381eb8a 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prelude_collisions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait method `try_into` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-imported.rs:40:22
@@ -19,7 +19,7 @@ LL |         let _: u32 = 3u8.try_into().unwrap();
    |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `crate::m::TryIntoU32::try_into(3u8)`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait method `try_into` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-imported.rs:53:22
@@ -28,7 +28,7 @@ LL |         let _: u32 = 3u8.try_into().unwrap();
    |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `super::m::TryIntoU32::try_into(3u8)`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: 3 warnings emitted
 
index 03b89da00d970c934ece61e64ba817bc7f7eb4c4..889e66de03f9ea541eb70c48437cf0148280e3ca 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prelude_collisions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `try_from` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:61:13
@@ -19,7 +19,7 @@ LL |     let _ = u32::try_from(3u8).unwrap();
    |             ^^^^^^^^^^^^^ help: disambiguate the associated function: `<u32 as TryFromU8>::try_from`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:66:13
@@ -28,7 +28,7 @@ LL |     let _ = <Vec<u8>>::from_iter(vec![1u8, 2, 3, 4, 5, 6].into_iter());
    |             ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<u8> as FromByteIterator>::from_iter`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `try_from` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:74:18
@@ -37,7 +37,7 @@ LL |     let _: u32 = <_>::try_from(3u8).unwrap();
    |                  ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::try_from`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait method `try_into` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:79:18
@@ -46,7 +46,7 @@ LL |     let _: u32 = (&3u8).try_into().unwrap();
    |                  ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(*(&3u8))`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait method `try_into` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:84:18
@@ -55,7 +55,7 @@ LL |     let _: u32 = 3.0.try_into().unwrap();
    |                  ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait method `try_into` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:90:18
@@ -64,7 +64,7 @@ LL |     let _: u32 = mut_ptr.try_into().unwrap();
    |                  ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: trait-associated function `try_from` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision.rs:95:13
@@ -73,7 +73,7 @@ LL |     let _ = U32Alias::try_from(3u8).unwrap();
    |             ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<U32Alias as TryFromU8>::try_from`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: 8 warnings emitted
 
index d4999201c27f962bacb9586e0d7687fe91eb296b..e6ea28d718db81336adb489c4af9a558ccab5299 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prelude_collisions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: 1 warning emitted
 
index 605f9ced9ebb72e559a81c5ae2d35bacdce59010..77b4c385132816b2ec2d32daccd289a2e3b005c3 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prelude_collisions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
 warning: 1 warning emitted
 
index a2ce9d42b675da6a2b0c61ebd86890868d5ed7d1..dc1152679b92094f323edf788a85cc1c62976d59 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![warn(rust_2021_prefixes_incompatible_syntax)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
    |
 LL -     m2!(z"hey");
@@ -24,7 +24,7 @@ LL |     m2!(prefix"hey");
    |         ^^^^^^ unknown prefix
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
    |
 LL -     m2!(prefix"hey");
@@ -38,7 +38,7 @@ LL |     m3!(hey#123);
    |         ^^^ unknown prefix
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
    |
 LL -     m3!(hey#123);
@@ -52,7 +52,7 @@ LL |     m3!(hey#hey);
    |         ^^^ unknown prefix
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
    |
 LL -     m3!(hey#hey);
@@ -66,7 +66,7 @@ LL |     #name = #kind#value
    |              ^^^^ unknown prefix
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
-   = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
 help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
    |
 LL -     #name = #kind#value
index 48a482a13aaa9d47b5eca083994f4dc4b544acbe..b53f19a5b01aa6d2e2024990ef35a3b37b3d9f4b 100644 (file)
@@ -6,7 +6,7 @@
 // run-fail
 // error-pattern: MemorySanitizer: use-of-uninitialized-value
 // error-pattern: Uninitialized value was created by an allocation
-// error-pattern: in the stack frame of function 'random'
+// error-pattern: in the stack frame of function 'main'
 //
 // This test case intentionally limits the usage of the std,
 // since it will be linked with an uninstrumented version of it.
index 2d30164380a8ee6ad1c91328be81113c1a09781d..10a39a4914770d1d7890b2589adaf81cb694716f 100644 (file)
@@ -1,8 +1,8 @@
 error: unconstrained generic constant
-  --> $DIR/issue-51892.rs:15:5
+  --> $DIR/issue-51892.rs:15:17
    |
 LL |     type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:`
 
diff --git a/src/test/ui/str/str-escape.rs b/src/test/ui/str/str-escape.rs
new file mode 100644 (file)
index 0000000..0264632
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+fn main() {
+    let s = "\
+
+             ";
+    //~^^^ WARNING multiple lines skipped by escaped newline
+    let s = "foo\
+  Â           bar
+             ";
+    //~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped
+}
diff --git a/src/test/ui/str/str-escape.stderr b/src/test/ui/str/str-escape.stderr
new file mode 100644 (file)
index 0000000..b2501f1
--- /dev/null
@@ -0,0 +1,21 @@
+warning: multiple lines skipped by escaped newline
+  --> $DIR/str-escape.rs:3:14
+   |
+LL |       let s = "\
+   |  ______________^
+LL | |
+LL | |              ";
+   | |_____________^ skipping everything up to and including this point
+
+warning: non-ASCII whitespace symbol '\u{a0}' is not skipped
+  --> $DIR/str-escape.rs:7:17
+   |
+LL |       let s = "foo\
+   |  _________________^
+LL | |   Â           bar
+   | |   ^ non-ASCII whitespace symbol '\u{a0}' is not skipped
+   | |___|
+   | 
+
+warning: 2 warnings emitted
+
index 223ddf0f0ad2abfc7113ed4891942999c06dad1f..4f2007befffa171471905f9ac14936657df0300a 100644 (file)
@@ -15,4 +15,13 @@ impl Foo {
     }
 }
 
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+    for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
+        return Some(loader);
+    }
+    None
+}
+
 fn main() {}
index 7942698cc8eff3b56dc490a4a689ad3c089cb764..55fc7ad4e373dc4b8430e0a91519b3eac646b688 100644 (file)
@@ -15,4 +15,13 @@ fn bar(&self) {
     }
 }
 
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+    for loader in *LOADERS { //~ ERROR cannot move out of a shared reference
+        return Some(loader);
+    }
+    None
+}
+
 fn main() {}
index 49cee6abc4eb4cfe0dd0f2b8c3ec04e9aa33d580..c39363f762bdd8ee26aab0d62fd8e5e94f905446 100644 (file)
@@ -20,6 +20,17 @@ help: consider iterating over a slice of the `HashMap<i32, i32>`'s content
 LL |         for _ in &self.h {
    |                  +
 
-error: aborting due to 2 previous errors
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/for-i-in-vec.rs:21:19
+   |
+LL |     for loader in *LOADERS {
+   |                   ^^^^^^^^ move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
+   |
+help: consider iterating over a slice of the `Vec<&u8>`'s content
+   |
+LL |     for loader in &*LOADERS {
+   |                   +
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
index 6282a693855af778e1f86fb0ef67f14a37eb034f..bb487920e3bb689ca2ad23c727aeb105fb2fa1f1 100644 (file)
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(bare_trait_objects)]
    |         ^^^^^^^^^^^^^^^^^^
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: trait objects without an explicit `dyn` are deprecated
   --> $DIR/issue-61963.rs:18:1
@@ -19,7 +19,7 @@ LL | pub struct Foo {
    | ^^^ help: use `dyn`: `dyn pub`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to 2 previous errors
 
index 1b8cd6ad078a284a28b2369906908b063d8e6557..0bbf1bffda5101e8072e6de59ed3810a21a2208c 100644 (file)
@@ -6,7 +6,7 @@ LL | fn foo(_x: Foo + Send) {
    |
    = note: `#[warn(bare_trait_objects)]` on by default
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
   --> $DIR/not-on-bare-trait.rs:7:8
index a704754e82a9210f53a765c2e42cb8f14b2ca34c..272a87535d2508126688c102df0b8cc8c10f0197 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `&T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:7:5
+  --> $DIR/hir-wf-check-erase-regions.rs:7:21
    |
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
    |
   ::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
    |
index f3b32ad3f7e85d27399c8e9a574d4aad8789606a..3f324190b7b6bcd1fff6b40646c5feb5c361342f 100644 (file)
@@ -1,10 +1,10 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/wf-impl-associated-type-region.rs:10:5
+  --> $DIR/wf-impl-associated-type-region.rs:10:16
    |
 LL | impl<'a, T> Foo<'a> for T {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Bar = &'a T;
-   |     ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+   |                ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
 
 error: aborting due to previous error
 
index 4c25ab9593958ddf8d26de9dc9da0e548ebc6d21..68c1e9091d753d653d07e8c165a4be0ab1b125ec 100644 (file)
@@ -1,18 +1,18 @@
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16
    |
 LL | impl<'a, T> Trait<'a, T> for usize {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a fn(T);
-   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
+   |                ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
 
 error[E0309]: the parameter type `T` may not live long enough
-  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
+  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16
    |
 LL | impl<'a, T> Trait<'a, T> for u32 {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a dyn Baz<T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
+   |                ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
 
 error: aborting due to 2 previous errors
 
index ae681ba6c9bb5c573fd8f7e3fe555cdd07370e3b..6e2cc8aba4b72d104a97dc891cc3438978223a02 100644 (file)
@@ -1,8 +1,8 @@
 error[E0309]: the associated type `<Self as SomeTrait<'a>>::Type1` may not live long enough
-  --> $DIR/wf-trait-associated-type-region.rs:9:5
+  --> $DIR/wf-trait-associated-type-region.rs:9:18
    |
 LL |     type Type2 = &'a Self::Type1;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`...
    = note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
index cc17afbb0067b1f57d8882640f63b2168d5b7624..b51439fd8b505d4800a257acfecf3c69f81e35cf 160000 (submodule)
@@ -1 +1 @@
-Subproject commit cc17afbb0067b1f57d8882640f63b2168d5b7624
+Subproject commit b51439fd8b505d4800a257acfecf3c69f81e35cf
index e182c99ce06a24318c16a81ea6de1c612f0769f1..2216bb9f293d790506a5d116b4120018a34306a0 100644 (file)
@@ -15,8 +15,9 @@ labels: A-lint
 *What is the advantage of the recommended code over the original code*
 
 For example:
-- Remove bounce checking inserted by ...
-- Remove the need to duplicating/storing/typo ...
+- Remove bounds check inserted by ...
+- Remove the need to duplicate/store ...
+- Remove typo ...
 
 ### Drawbacks
 
index d856c55a41a4b8768b246009e43785a0b21ef6ca..0339de77f3cecf4e3ebad3e91b302398a5da368f 100644 (file)
@@ -49,13 +49,13 @@ jobs:
         echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
 
     - name: Build
-      run: cargo build --features deny-warnings,internal-lints
+      run: cargo build --features deny-warnings,internal-lints,metadata-collector-lint
 
     - name: Test
-      run: cargo test --features deny-warnings,internal-lints
+      run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
 
     - name: Test clippy_lints
-      run: cargo test --features deny-warnings,internal-lints
+      run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
       working-directory: clippy_lints
 
     - name: Test rustc_tools_util
index 146b6fccd0c76e94962ca9260732ce849a535ee0..1f4d666c7a92c1f6761c2288a280c71ad586f2c3 100644 (file)
@@ -112,13 +112,13 @@ jobs:
         echo "$SYSROOT/bin" >> $GITHUB_PATH
 
     - name: Build
-      run: cargo build --features deny-warnings,internal-lints
+      run: cargo build --features deny-warnings,internal-lints,metadata-collector-lint
 
     - name: Test
-      run: cargo test --features deny-warnings,internal-lints
+      run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
 
     - name: Test clippy_lints
-      run: cargo test --features deny-warnings,internal-lints
+      run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
       working-directory: clippy_lints
 
     - name: Test rustc_tools_util
index 77efdec1e50db71b34a533df1d0deb068e3827e7..56c00544c93a7892d7aa80a0ec05e6c70ad0734d 100644 (file)
@@ -20,6 +20,8 @@ jobs:
 
     - name: Setup Node.js
       uses: actions/setup-node@v1.4.4
+      with:
+        node-version: '12.x'
 
     - name: Install remark
       run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm
index acbefc8064ddaece56e268883775df69ea0b341d..2b89170073be513bca6869b916212e05d9fb2935 100644 (file)
@@ -6,11 +6,141 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[3ae8faf...master](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...master)
+[74d1561...master](https://github.com/rust-lang/rust-clippy/compare/74d1561...master)
+
+## Rust 1.55
+
+Current beta, release 2021-09-09
+
+[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
+
+### Important Changes
+
+* Stabilized `cargo clippy --fix` :tada:
+  [#7405](https://github.com/rust-lang/rust-clippy/pull/7405)
+
+### New Lints
+
+* [`rc_mutex`]
+  [#7316](https://github.com/rust-lang/rust-clippy/pull/7316)
+* [`nonstandard_macro_braces`]
+  [#7299](https://github.com/rust-lang/rust-clippy/pull/7299)
+* [`strlen_on_c_strings`]
+  [#7243](https://github.com/rust-lang/rust-clippy/pull/7243)
+* [`self_named_constructors`]
+  [#7403](https://github.com/rust-lang/rust-clippy/pull/7403)
+* [`disallowed_script_idents`]
+  [#7400](https://github.com/rust-lang/rust-clippy/pull/7400)
+* [`disallowed_type`]
+  [#7315](https://github.com/rust-lang/rust-clippy/pull/7315)
+* [`missing_enforced_import_renames`]
+  [#7300](https://github.com/rust-lang/rust-clippy/pull/7300)
+* [`extend_with_drain`]
+  [#7270](https://github.com/rust-lang/rust-clippy/pull/7270)
+
+### Moves and Deprecations
+
+* Moved [`from_iter_instead_of_collect`] to `pedantic`
+  [#7375](https://github.com/rust-lang/rust-clippy/pull/7375)
+* Added `suspicious` as a new lint group for *code that is most likely wrong or useless*
+  [#7350](https://github.com/rust-lang/rust-clippy/pull/7350)
+  * Moved [`blanket_clippy_restriction_lints`] to `suspicious`
+  * Moved [`empty_loop`] to `suspicious`
+  * Moved [`eval_order_dependence`] to `suspicious`
+  * Moved [`float_equality_without_abs`] to `suspicious`
+  * Moved [`for_loops_over_fallibles`] to `suspicious`
+  * Moved [`misrefactored_assign_op`] to `suspicious`
+  * Moved [`mut_range_bound`] to `suspicious`
+  * Moved [`mutable_key_type`] to `suspicious`
+  * Moved [`suspicious_arithmetic_impl`] to `suspicious`
+  * Moved [`suspicious_assignment_formatting`] to `suspicious`
+  * Moved [`suspicious_else_formatting`] to `suspicious`
+  * Moved [`suspicious_map`] to `suspicious`
+  * Moved [`suspicious_op_assign_impl`] to `suspicious`
+  * Moved [`suspicious_unary_op_formatting`] to `suspicious`
+
+### Enhancements
+
+* [`while_let_on_iterator`]: Now suggests `&mut iter` inside closures
+  [#7262](https://github.com/rust-lang/rust-clippy/pull/7262)
+* [`doc_markdown`]:
+  * Now detects unbalanced ticks
+    [#7357](https://github.com/rust-lang/rust-clippy/pull/7357)
+  * Add `FreeBSD` to the default configuration as an allowed identifier
+    [#7334](https://github.com/rust-lang/rust-clippy/pull/7334)
+* [`wildcard_enum_match_arm`], [`match_wildcard_for_single_variants`]: Now allows wildcards for enums with unstable
+  or hidden variants
+  [#7407](https://github.com/rust-lang/rust-clippy/pull/7407)
+* [`redundant_allocation`]: Now additionally supports the `Arc<>` type
+  [#7308](https://github.com/rust-lang/rust-clippy/pull/7308)
+* [`blacklisted_name`]: Now allows blacklisted names in test code
+  [#7379](https://github.com/rust-lang/rust-clippy/pull/7379)
+* [`redundant_closure`]: Suggests `&mut` for `FnMut`
+  [#7437](https://github.com/rust-lang/rust-clippy/pull/7437)
+* [`disallowed_method`], [`disallowed_type`]: The configuration values `disallowed-method` and `disallowed-type`
+  no longer require fully qualified paths
+  [#7345](https://github.com/rust-lang/rust-clippy/pull/7345)
+* [`zst_offset`]: Fixed lint invocation after it was accidentally suppressed
+  [#7396](https://github.com/rust-lang/rust-clippy/pull/7396)
+
+### False Positive Fixes
+
+* [`default_numeric_fallback`]: No longer lints on float literals as function arguments
+  [#7446](https://github.com/rust-lang/rust-clippy/pull/7446)
+* [`use_self`]: No longer lints on type parameters
+  [#7288](https://github.com/rust-lang/rust-clippy/pull/7288)
+* [`unimplemented`]: Now ignores the `assert` and `debug_assert` macros
+  [#7439](https://github.com/rust-lang/rust-clippy/pull/7439)
+* [`branches_sharing_code`]: Now always checks for block expressions
+  [#7462](https://github.com/rust-lang/rust-clippy/pull/7462)
+* [`field_reassign_with_default`]: No longer triggers in macros
+  [#7160](https://github.com/rust-lang/rust-clippy/pull/7160)
+* [`redundant_clone`]: No longer lints on required clones for borrowed data
+  [#7346](https://github.com/rust-lang/rust-clippy/pull/7346)
+* [`default_numeric_fallback`]: No longer triggers in external macros
+  [#7325](https://github.com/rust-lang/rust-clippy/pull/7325)
+* [`needless_bool`]: No longer lints in macros
+  [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
+* [`useless_format`]: No longer triggers when additional text is being appended
+  [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
+* [`assertions_on_constants`]: `cfg!(...)` is no longer considered to be a constant
+  [#7319](https://github.com/rust-lang/rust-clippy/pull/7319)
+
+### Suggestion Fixes/Improvements
+
+* [`needless_collect`]: Now show correct lint messages for shadowed values
+  [#7289](https://github.com/rust-lang/rust-clippy/pull/7289)
+* [`wrong_pub_self_convention`]: The deprecated message now suggest the correct configuration value
+  [#7382](https://github.com/rust-lang/rust-clippy/pull/7382)
+* [`semicolon_if_nothing_returned`]: Allow missing semicolon in blocks with only one expression
+  [#7326](https://github.com/rust-lang/rust-clippy/pull/7326)
+
+### ICE Fixes
+
+* [`zero_sized_map_values`]
+  [#7470](https://github.com/rust-lang/rust-clippy/pull/7470)
+* [`redundant_pattern_matching`]
+  [#7471](https://github.com/rust-lang/rust-clippy/pull/7471)
+* [`modulo_one`]
+  [#7473](https://github.com/rust-lang/rust-clippy/pull/7473)
+* [`use_self`]
+  [#7428](https://github.com/rust-lang/rust-clippy/pull/7428)
+
+### Documentation Improvements
+
+* Reworked Clippy's website:
+  [#7279](https://github.com/rust-lang/rust-clippy/pull/7279)
+  [#7172](https://github.com/rust-lang/rust-clippy/issues/7172)
+  * Added applicability information about lints
+  * Added a link to jump into the implementation
+  * Improved loading times
+  * Adapted some styling
+* Clippy now uses a lint to generate its documentation
+  [#7298](https://github.com/rust-lang/rust-clippy/pull/7298)
 
 ## Rust 1.54
 
-Current beta, release 2021-07-29
+Current stable, released 2021-07-29
 
 [7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf)
 
@@ -29,7 +159,7 @@ Current beta, release 2021-07-29
 ### Moves and Deprecations
 
 - Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of
-  the new `avoid_breaking_exported_api` config option (see
+  the new `avoid-breaking-exported-api` config option (see
   [Enhancements](#1-54-enhancements))
   [#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
 - Move [`inconsistent_struct_constructor`] to `pedantic`
@@ -51,7 +181,7 @@ Current beta, release 2021-07-29
   [#7163](https://github.com/rust-lang/rust-clippy/pull/7163)
 - [`if_then_some_else_none`]: Now works with the MSRV config
   [#7177](https://github.com/rust-lang/rust-clippy/pull/7177)
-- Add `avoid_breaking_exported_api` config option for the lints
+- Add `avoid-breaking-exported-api` config option for the lints
   [`enum_variant_names`], [`large_types_passed_by_value`],
   [`trivially_copy_pass_by_ref`], [`unnecessary_wraps`],
   [`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set
@@ -138,7 +268,7 @@ Current beta, release 2021-07-29
 
 ## Rust 1.53
 
-Current stable, released 2021-06-17
+Released 2021-06-17
 
 [6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c)
 
@@ -2869,6 +2999,7 @@ Released 2018-09-13
 [`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
 [`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
 [`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
+[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default
 [`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
 [`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
 [`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
index 7c39a3e2ce3ded627ced6d63b869cae08b545359..0be460d67a75f3e8bbb248782978eed3ba1a79fb 100644 (file)
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -47,7 +47,7 @@
 
 impl EarlyLintPass for AsConversions {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess, expr.span) {
             return;
         }
 
index a3a3603c4c0ee5617b86c3c2a5e63f4116cce09b..75561cfde369bc73bfd871eebfc42f55671a46bf 100644 (file)
@@ -230,15 +230,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
                         panic_span: None,
                     };
                     fpu.visit_expr(&body.value);
-                    lint_for_missing_headers(
-                        cx,
-                        item.def_id,
-                        item.span,
-                        sig,
-                        headers,
-                        Some(body_id),
-                        fpu.panic_span,
-                    );
+                    lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
                 }
             },
             hir::ItemKind::Impl(ref impl_) => {
@@ -278,15 +270,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<
                 panic_span: None,
             };
             fpu.visit_expr(&body.value);
-            lint_for_missing_headers(
-                cx,
-                item.def_id,
-                item.span,
-                sig,
-                headers,
-                Some(body_id),
-                fpu.panic_span,
-            );
+            lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
         }
     }
 }
index 0541ac5eccca40cdaf91e439494b42d74b9a4b0d..b64246515f34f79fab343e868120c52060605f1e 100644 (file)
@@ -2,7 +2,7 @@
 
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -49,7 +49,7 @@
 
 impl EarlyLintPass for ElseIfWithoutElse {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) {
-        if in_external_macro(cx.sess(), item.span) {
+        if in_external_macro(cx.sess, item.span) {
             return;
         }
 
index ce23c0ce4a0764feaab4139979515157e23eee48..04fc5887e8e8b21123d92d9bde53ed6179151560 100644 (file)
@@ -251,7 +251,7 @@ fn check_fn(
         hir_id: hir::HirId,
     ) {
         too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
-        too_many_lines::check_fn(cx, span, body, self.too_many_lines_threshold);
+        too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
         not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
     }
 
index a666fee1a4ad507a7f1d74dde33fb2d708c44948..008ef661b55f20a31c4e25e1e24e3a0de4b7a94a 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_hir as hir;
+use rustc_hir::intravisit::FnKind;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_span::Span;
@@ -8,8 +9,16 @@
 
 use super::TOO_MANY_LINES;
 
-pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>, too_many_lines_threshold: u64) {
-    if in_external_macro(cx.sess(), span) {
+pub(super) fn check_fn(
+    cx: &LateContext<'_>,
+    kind: FnKind<'tcx>,
+    span: Span,
+    body: &'tcx hir::Body<'_>,
+    too_many_lines_threshold: u64,
+) {
+    // Closures must be contained in a parent body, which will be checked for `too_many_lines`.
+    // Don't check closures for `too_many_lines` to avoid duplicated lints.
+    if matches!(kind, FnKind::Closure) || in_external_macro(cx.sess(), span) {
         return;
     }
 
index 28db7233d70e8c43cde2aa110929be8cd48e4dea..3ce91d421baca8bc9efe4b9ae760c522c7f288ca 100644 (file)
@@ -3,7 +3,7 @@
 
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -48,7 +48,7 @@
 
 impl EarlyLintPass for IfNotElse {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
-        if in_external_macro(cx.sess(), item.span) {
+        if in_external_macro(cx.sess, item.span) {
             return;
         }
         if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind {
index 429c6ed7d2d778ec8a81b10895792b4f5dfc83ac..3736d237642fb61d30b3ddadbb8148fabd2d3ca5 100644 (file)
@@ -2,7 +2,7 @@
 
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast::{Block, ItemKind, StmtKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -54,7 +54,7 @@
 
 impl EarlyLintPass for ItemsAfterStatements {
     fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
-        if in_external_macro(cx.sess(), item.span) {
+        if in_external_macro(cx.sess, item.span) {
             return;
         }
 
@@ -68,7 +68,7 @@ fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
         // lint on all further items
         for stmt in stmts {
             if let StmtKind::Item(ref it) = *stmt {
-                if in_external_macro(cx.sess(), it.span) {
+                if in_external_macro(cx.sess, it.span) {
                     return;
                 }
                 if let ItemKind::MacroDef(..) = it.kind {
index a2cbfb1a05eeaec47f6d5979995dcbd4c3383129..a519ad90df54a2c84b5858e5234fe033cc3b95e7 100644 (file)
@@ -207,8 +207,7 @@ fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) {
         }
     }
 
-    if cx.access_levels.is_exported(visited_trait.def_id)
-        && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
+    if cx.access_levels.is_exported(visited_trait.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
     {
         let mut current_and_super_traits = DefIdSet::default();
         fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
@@ -331,17 +330,15 @@ fn check_for_is_empty(
             None,
             None,
         ),
-        Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => {
-            (
-                format!(
-                    "{} `{}` has a public `len` method, but a private `is_empty` method",
-                    item_kind,
-                    item_name.as_str(),
-                ),
-                Some(cx.tcx.def_span(is_empty.def_id)),
-                None,
-            )
-        },
+        Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => (
+            format!(
+                "{} `{}` has a public `len` method, but a private `is_empty` method",
+                item_kind,
+                item_name.as_str(),
+            ),
+            Some(cx.tcx.def_span(is_empty.def_id)),
+            None,
+        ),
         Some(is_empty)
             if !(is_empty.fn_has_self_parameter
                 && check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind, output)) =>
index f49b382c5ea3bd585936492f43c83e92838453ac..dbdb4251b3bec2358c98cae5878f611b3f6401c9 100644 (file)
@@ -797,6 +797,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         methods::UNNECESSARY_FILTER_MAP,
         methods::UNNECESSARY_FOLD,
         methods::UNNECESSARY_LAZY_EVALUATIONS,
+        methods::UNWRAP_OR_ELSE_DEFAULT,
         methods::UNWRAP_USED,
         methods::USELESS_ASREF,
         methods::WRONG_SELF_CONVENTION,
@@ -1341,6 +1342,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::UNNECESSARY_FILTER_MAP),
         LintId::of(methods::UNNECESSARY_FOLD),
         LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+        LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
         LintId::of(methods::USELESS_ASREF),
         LintId::of(methods::WRONG_SELF_CONVENTION),
         LintId::of(methods::ZST_OFFSET),
@@ -1535,6 +1537,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::STRING_EXTEND_CHARS),
         LintId::of(methods::UNNECESSARY_FOLD),
         LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+        LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
         LintId::of(methods::WRONG_SELF_CONVENTION),
         LintId::of(misc::TOPLEVEL_REF_ARG),
         LintId::of(misc::ZERO_PTR),
index 699ddce0cff905ac2705e3c8d0c37b525b289e6d..0e5121ca3d73a9d0e5e0107aca96ef4c46f91a10 100644 (file)
@@ -10,7 +10,7 @@
 use if_chain::if_chain;
 use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use std::iter;
@@ -222,7 +222,7 @@ pub struct LiteralDigitGrouping {
 
 impl EarlyLintPass for LiteralDigitGrouping {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess, expr.span) {
             return;
         }
 
@@ -415,7 +415,7 @@ pub struct DecimalLiteralRepresentation {
 
 impl EarlyLintPass for DecimalLiteralRepresentation {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess, expr.span) {
             return;
         }
 
index e97b7c9417033d9a9929f7a994fafb5f08f4b0e5..6d9f6215ed418dd95087021c4ee57464ae33b7d0 100644 (file)
@@ -1,13 +1,36 @@
+use super::utils::make_iterator_snippet;
 use super::NEVER_LOOP;
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Stmt, StmtKind};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, LoopSource, Node, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use std::iter::{once, Iterator};
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-    if let ExprKind::Loop(block, _, _, _) = expr.kind {
+    if let ExprKind::Loop(block, _, source, _) = expr.kind {
         match never_loop_block(block, expr.hir_id) {
-            NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
+            NeverLoopResult::AlwaysBreak => {
+                span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| {
+                    if_chain! {
+                        if let LoopSource::ForLoop = source;
+                        if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1);
+                        if let Some((pat, iterator, _, for_span)) = higher::for_loop(parent_match);
+                        then {
+                            // Suggests using an `if let` instead. This is `Unspecified` because the
+                            // loop may (probably) contain `break` statements which would be invalid
+                            // in an `if let`.
+                            diag.span_suggestion_verbose(
+                                for_span.with_hi(iterator.span.hi()),
+                                "if you need the first element of the iterator, try writing",
+                                for_to_if_let_sugg(cx, iterator, pat),
+                                Applicability::Unspecified,
+                            );
+                        }
+                    };
+                });
+            },
             NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
         }
     }
@@ -170,3 +193,14 @@ fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(e: &mut T, main_
     e.map(|e| never_loop_expr(e, main_loop_id))
         .fold(NeverLoopResult::AlwaysBreak, combine_branches)
 }
+
+fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>) -> String {
+    let pat_snippet = snippet(cx, pat.span, "_");
+    let iter_snippet = make_iterator_snippet(cx, iterator, &mut Applicability::Unspecified);
+
+    format!(
+        "if let Some({pat}) = {iter}.next()",
+        pat = pat_snippet,
+        iter = iter_snippet
+    )
+}
index d57588716a5bf16c8f4b28d0b75ceb251718837e..ef822e0cbe540225f9ad4317ecb19110973a70a0 100644 (file)
@@ -7,7 +7,7 @@
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
-use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, MatchSource, Node, PatKind, QPath, UnOp};
+use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, MatchSource, Mutability, Node, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
 use rustc_span::{symbol::sym, Span, Symbol};
 
@@ -48,7 +48,12 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     // borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
     // afterwards a mutable borrow of a field isn't necessary.
     let ref_mut = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
-        "&mut "
+        if cx.typeck_results().node_type(iter_expr.hir_id).ref_mutability() == Some(Mutability::Mut) {
+            // Reborrow for mutable references. It may not be possible to get a mutable reference here.
+            "&mut *"
+        } else {
+            "&mut "
+        }
     } else {
         ""
     };
@@ -69,6 +74,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
 struct IterExpr {
     /// The span of the whole expression, not just the path and fields stored here.
     span: Span,
+    /// The HIR id of the whole expression, not just the path and fields stored here.
+    hir_id: HirId,
     /// The fields used, in order of child to parent.
     fields: Vec<Symbol>,
     /// The path being used.
@@ -78,12 +85,14 @@ struct IterExpr {
 /// the expression might have side effects.
 fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option<IterExpr> {
     let span = e.span;
+    let hir_id = e.hir_id;
     let mut fields = Vec::new();
     loop {
         match e.kind {
             ExprKind::Path(ref path) => {
                 break Some(IterExpr {
                     span,
+                    hir_id,
                     fields,
                     path: cx.qpath_res(path, e.hir_id),
                 });
@@ -137,7 +146,7 @@ fn is_expr_same_child_or_parent_field(cx: &LateContext<'_>, expr: &Expr<'_>, fie
     match expr.kind {
         ExprKind::Field(base, name) => {
             if let Some((head_field, tail_fields)) = fields.split_first() {
-                if name.name == *head_field && is_expr_same_field(cx, base, fields, path_res) {
+                if name.name == *head_field && is_expr_same_field(cx, base, tail_fields, path_res) {
                     return true;
                 }
                 // Check if the expression is a parent field
index 57e10ce42f8bbdc49123989b472347804eb1ba50..8829b8c5f4df45c4fc8bb730dc7b9c7365b87d9b 100644 (file)
@@ -16,7 +16,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
         //check source object
         if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind;
         if src_method.ident.as_str() == "drain";
-        if let src_ty = cx.typeck_results().expr_ty(drain_vec).peel_refs();
+        let src_ty = cx.typeck_results().expr_ty(drain_vec);
+        //check if actual src type is mutable for code suggestion
+        let immutable = src_ty.is_mutable_ptr();
+        let src_ty = src_ty.peel_refs();
         if is_type_diagnostic_item(cx, src_ty, sym::vec_type);
         //check drain range
         if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs();
@@ -30,8 +33,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
                 "use of `extend` instead of `append` for adding the full range of a second vector",
                 "try this",
                 format!(
-                    "{}.append(&mut {})",
+                    "{}.append({}{})",
                     snippet_with_applicability(cx, recv.span, "..", &mut applicability),
+                    if immutable { "" } else { "&mut " },
                     snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability)
                 ),
                 applicability,
index b4188d9ed3095324a415fd7d501dabb97dccbb1c..99c03844f49275e02461ca8a02c0195c81e96772 100644 (file)
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{is_expr_path_def_path, paths, sugg};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 use rustc_span::sym;
 
@@ -43,7 +44,7 @@ fn strip_angle_brackets(s: &str) -> Option<&str> {
 
     let call_site = expr.span.source_callsite();
     if_chain! {
-        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
+        if let Some(snippet) = snippet_opt(cx, call_site);
         let snippet_split = snippet.split("::").collect::<Vec<_>>();
         if let Some((_, elements)) = snippet_split.split_last();
 
index e8ad16bc0def91b6676b11792eaedfb218ee0f2e..08d3a7ce92bbea268cbdae460c78cc43e5bd3733 100644 (file)
@@ -52,18 +52,32 @@ pub(super) fn check<'tcx>(
         );
     }
 
-    // lint if caller of `.map().flatten()` is an Option
-    if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) {
-        let func_snippet = snippet(cx, map_arg.span, "..");
-        let hint = format!(".and_then({})", func_snippet);
-        span_lint_and_sugg(
-            cx,
-            MAP_FLATTEN,
-            expr.span.with_lo(recv.span.hi()),
-            "called `map(..).flatten()` on an `Option`",
-            "try using `and_then` instead",
-            hint,
-            Applicability::MachineApplicable,
-        );
-    }
+    // lint if caller of `.map().flatten()` is an Option or Result
+    let caller_type = match cx.typeck_results().expr_ty(recv).kind() {
+        ty::Adt(adt, _) => {
+            if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) {
+                "Option"
+            } else if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) {
+                "Result"
+            } else {
+                return;
+            }
+        },
+        _ => {
+            return;
+        },
+    };
+
+    let func_snippet = snippet(cx, map_arg.span, "..");
+    let hint = format!(".and_then({})", func_snippet);
+    let lint_info = format!("called `map(..).flatten()` on an `{}`", caller_type);
+    span_lint_and_sugg(
+        cx,
+        MAP_FLATTEN,
+        expr.span.with_lo(recv.span.hi()),
+        &lint_info,
+        "try using `and_then` instead",
+        hint,
+        Applicability::MachineApplicable,
+    );
 }
index 1909fabb22fe77c35785145f963935cd29fbdc8d..91606ed3b2bb0d9bc83dfddb0085208451d78415 100644 (file)
@@ -56,6 +56,7 @@
 mod unnecessary_filter_map;
 mod unnecessary_fold;
 mod unnecessary_lazy_eval;
+mod unwrap_or_else_default;
 mod unwrap_used;
 mod useless_asref;
 mod utils;
     "using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
+    /// `Result` values.
+    ///
+    /// ### Why is this bad?
+    /// Readability, these can be written as `_.unwrap_or_default`, which is
+    /// simpler and more concise.
+    ///
+    /// ### Examples
+    /// ```rust
+    /// # let x = Some(1);
+    ///
+    /// // Bad
+    /// x.unwrap_or_else(Default::default);
+    /// x.unwrap_or_else(u32::default);
+    ///
+    /// // Good
+    /// x.unwrap_or_default();
+    /// ```
+    pub UNWRAP_OR_ELSE_DEFAULT,
+    style,
+    "using `.unwrap_or_else(Default::default)`, which is more succinctly expressed as `.unwrap_or_default()`"
+}
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
@@ -1766,6 +1792,7 @@ pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Sel
     SHOULD_IMPLEMENT_TRAIT,
     WRONG_SELF_CONVENTION,
     OK_EXPECT,
+    UNWRAP_OR_ELSE_DEFAULT,
     MAP_UNWRAP_OR,
     RESULT_MAP_OR_INTO_OPTION,
     OPTION_MAP_OR_NONE,
@@ -2172,7 +2199,10 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
             },
             ("unwrap_or_else", [u_arg]) => match method_call!(recv) {
                 Some(("map", [recv, map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, msrv) => {},
-                _ => unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"),
+                _ => {
+                    unwrap_or_else_default::check(cx, expr, recv, u_arg);
+                    unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
+                },
             },
             _ => {},
         }
index ef615b0aa40a8e61995b4e63692ab9fe86d4cc3e..c1d22e5d72c138d3a9c216eb571686d3a672e4f0 100644 (file)
@@ -1,7 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::eager_or_lazy::is_lazyness_candidate;
+use clippy_utils::is_trait_item;
 use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite};
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use clippy_utils::{contains_return, last_path_segment, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -34,15 +36,23 @@ fn check_unwrap_or_default(
         or_has_args: bool,
         span: Span,
     ) -> bool {
+        let is_default_default = || is_trait_item(cx, fun, sym::Default);
+
+        let implements_default = |arg, default_trait_id| {
+            let arg_ty = cx.typeck_results().expr_ty(arg);
+            implements_trait(cx, arg_ty, default_trait_id, &[])
+        };
+
         if_chain! {
             if !or_has_args;
             if name == "unwrap_or";
             if let hir::ExprKind::Path(ref qpath) = fun.kind;
-            let path = last_path_segment(qpath).ident.name;
-            if matches!(path, kw::Default | sym::new);
-            let arg_ty = cx.typeck_results().expr_ty(arg);
             if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
-            if implements_trait(cx, arg_ty, default_trait_id, &[]);
+            let path = last_path_segment(qpath).ident.name;
+            // needs to target Default::default in particular or be *::new and have a Default impl
+            // available
+            if (matches!(path, kw::Default) && is_default_default())
+                || (matches!(path, sym::new) && implements_default(arg, default_trait_id));
 
             then {
                 let mut applicability = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_or_else_default.rs
new file mode 100644 (file)
index 0000000..677aa80
--- /dev/null
@@ -0,0 +1,45 @@
+//! Lint for `some_result_or_option.unwrap_or_else(Default::default)`
+
+use super::UNWRAP_OR_ELSE_DEFAULT;
+use clippy_utils::{
+    diagnostics::span_lint_and_sugg, is_trait_item, source::snippet_with_applicability, ty::is_type_diagnostic_item,
+};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'_>,
+    recv: &'tcx hir::Expr<'_>,
+    u_arg: &'tcx hir::Expr<'_>,
+) {
+    // something.unwrap_or_else(Default::default)
+    // ^^^^^^^^^- recv          ^^^^^^^^^^^^^^^^- u_arg
+    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr
+    let recv_ty = cx.typeck_results().expr_ty(recv);
+    let is_option = is_type_diagnostic_item(cx, recv_ty, sym::option_type);
+    let is_result = is_type_diagnostic_item(cx, recv_ty, sym::result_type);
+
+    if_chain! {
+        if is_option || is_result;
+        if is_trait_item(cx, u_arg, sym::Default);
+        then {
+            let mut applicability = Applicability::MachineApplicable;
+
+            span_lint_and_sugg(
+                cx,
+                UNWRAP_OR_ELSE_DEFAULT,
+                expr.span,
+                "use of `.unwrap_or_else(..)` to construct default value",
+                "try",
+                format!(
+                    "{}.unwrap_or_default()",
+                    snippet_with_applicability(cx, recv.span, "..", &mut applicability)
+                ),
+                applicability,
+            );
+        }
+    }
+}
index 06fe967dafc409144c300d0f52417d91f9ec1743..b32feab4ee3e7e5506b23875170ca01d6d4920b6 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
 use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
@@ -307,7 +307,7 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: N
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess, expr.span) {
             return;
         }
         double_neg::check(cx, expr);
index 2201cf56d52ab357c287633b45c8e3d0b8dbcc7e..fff533167ede2032d935dbc3edbc4228d51bfba4 100644 (file)
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{Pat, PatKind};
-use rustc_lint::{EarlyContext, LintContext};
+use rustc_lint::EarlyContext;
 
 use super::UNNEEDED_FIELD_PATTERN;
 
@@ -48,7 +49,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
                             match field.pat.kind {
                                 PatKind::Wild => {},
                                 _ => {
-                                    if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
+                                    if let Some(n) = snippet_opt(cx, field.span) {
                                         normal.push(n);
                                     }
                                 },
index 3f0b23ee4d3e45a6106f3a615e5007c0239f3cd1..ba8f9446af85e4a0850fdedffe1996e7d3b1aaf0 100644 (file)
     ///
     /// ### Example
     /// ```rust
+    /// fn fun(_a: &i32) {}
+    ///
     /// // Bad
     /// let x: &i32 = &&&&&&5;
+    /// fun(&x);
     ///
     /// // Good
     /// let x: &i32 = &5;
+    /// fun(x);
     /// ```
     pub NEEDLESS_BORROW,
     style,
index 5088b8bb0d3680ecf08a651d05755730b9602393..5a50cc48d61bfce7e62f03719cdbc2028adb8a57 100644 (file)
@@ -422,7 +422,7 @@ fn check_and_warn<'a>(cx: &EarlyContext<'_>, expr: &'a ast::Expr) {
 ///
 /// is transformed to
 ///
-/// ```ignore
+/// ```text
 ///     {
 ///         let x = 5;
 /// ```
index d9aa42fe8eeb69cfbe7f7dc8cc2fd1621ee2599d..9a6ddc72ce56a04ca17199e8b1baa700763dafcf 100644 (file)
@@ -122,7 +122,7 @@ fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
 /// 2. Detect use of `return` in `Loop` in the closure body.
 ///
 /// NOTE: The functionality of this type is similar to
-/// [`crate::utilts::visitors::find_all_ret_expressions`], but we can't use
+/// [`clippy_utils::visitors::find_all_ret_expressions`], but we can't use
 /// `find_all_ret_expressions` instead of this type. The reasons are:
 /// 1. `find_all_ret_expressions` passes the argument of `ExprKind::Ret` to a callback, but what we
 ///    need here is `ExprKind::Ret` itself.
index e07518b25868795c691291bc01e28b8d9315e59b..28e9e6f438e3de59f8f63ef67acccbee8da82397 100644 (file)
@@ -3,7 +3,7 @@
 use clippy_utils::ty::has_drop;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
+use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use std::ops::Deref;
@@ -68,12 +68,14 @@ fn has_no_effect(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         ExprKind::Call(callee, args) => {
             if let ExprKind::Path(ref qpath) = callee.kind {
                 let res = cx.qpath_res(qpath, callee.hir_id);
-                match res {
-                    Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => {
-                        !has_drop(cx, cx.typeck_results().expr_ty(expr))
-                            && args.iter().all(|arg| has_no_effect(cx, arg))
-                    },
-                    _ => false,
+                let def_matched = matches!(
+                    res,
+                    Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..)
+                );
+                if def_matched || is_range_literal(expr) {
+                    !has_drop(cx, cx.typeck_results().expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg))
+                } else {
+                    false
                 }
             } else {
                 false
index 06c431babc23a34cbf359b38316570d1023bc4a5..f6254aa715a45f5e8b00a174448bc631b434b454 100644 (file)
@@ -127,6 +127,7 @@ fn check_single_char_names(&self) {
     &["qpath", "path"],
     &["lit", "lint"],
     &["wparam", "lparam"],
+    &["iter", "item"],
 ];
 
 struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
index dbe9cbe0ded83c4588c455063f6097e18c60457b..ca660a9250db15f2332a71b44dfad2340c8d1f06 100644 (file)
@@ -7,6 +7,7 @@
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::DefId;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::Span;
@@ -91,13 +92,23 @@ fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
 }
 
 fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option<MacroInfo<'a>> {
+    let unnested_or_local = || {
+        let nested = in_macro(span.ctxt().outer_expn_data().call_site);
+        !nested
+            || span
+                .macro_backtrace()
+                .last()
+                .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
+    };
     if_chain! {
+        // Make sure we are only one level deep otherwise there are to many FP's
         if in_macro(span);
         if let Some((name, braces)) = find_matching_macro(span, &mac_braces.macro_braces);
         if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
         // we must check only invocation sites
         // https://github.com/rust-lang/rust-clippy/issues/7422
-        if snip.starts_with(name);
+        if snip.starts_with(&format!("{}!", name));
+        if unnested_or_local();
         // make formatting consistent
         let c = snip.replace(" ", "");
         if !c.starts_with(&format!("{}!{}", name, braces.0));
index 1222a95d4eaa86852021c60f6cac6bf61dd923ba..157b18c1f6b1fb8a8287c653f54827552aef5cf9 100644 (file)
@@ -2,9 +2,9 @@
 use std::iter;
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_self_ty;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_copy;
+use clippy_utils::{is_self, is_self_ty};
 use if_chain::if_chain;
 use rustc_ast::attr;
 use rustc_errors::Applicability;
@@ -170,7 +170,7 @@ fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &F
                         if size <= self.ref_min_size;
                         if let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind;
                         then {
-                            let value_type = if is_self_ty(decl_ty) {
+                            let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) {
                                 "self".into()
                             } else {
                                 snippet(cx, decl_ty.span, "_").into()
index a79b2fe76e2d57f100996e94239f5fbb1b1a96f1..7314bce83e03867d83c8e6f7e2300d9485360f60 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_hir as hir;
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -63,7 +63,7 @@ fn visit_expr(&mut self, ex: &'ast ast::Expr) {
 
 impl EarlyLintPass for RedundantClosureCall {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        if in_external_macro(cx.sess(), expr.span) {
+        if in_external_macro(cx.sess, expr.span) {
             return;
         }
         if_chain! {
index e0930d69ab9fecc4c39b2fd44b967032cd7d3021..77b6e60d89398e61c55f2377bed0933d1125e20d 100644 (file)
@@ -54,7 +54,8 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
             then {
                 let mut applicability = Applicability::MachineApplicable;
                 let sugg = if e.span.from_expansion() {
-                    if let Ok(macro_source) = cx.sess.source_map().span_to_snippet(e.span) {
+                    #[allow(clippy::option_if_let_else)]
+                    if let Some(macro_source) = snippet_opt(cx, e.span) {
                         // Remove leading whitespace from the given span
                         // e.g: ` $visitor` turns into `$visitor`
                         let trim_leading_whitespaces = |span| {
index 4fa8e77a67b783edb6dcb10fac3f4a6cdb2ad0fe..f126908e84b037716fcca1dfca70d532c6734e4c 100644 (file)
@@ -1,15 +1,16 @@
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{differing_macro_contexts, eq_expr_value};
+use clippy_utils::{can_mut_borrow_both, differing_macro_contexts, eq_expr_value};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
+use rustc_span::source_map::Spanned;
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -70,9 +71,67 @@ impl<'tcx> LateLintPass<'tcx> for Swap {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
         check_manual_swap(cx, block);
         check_suspicious_swap(cx, block);
+        check_xor_swap(cx, block);
     }
 }
 
+fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, span: Span, is_xor_based: bool) {
+    let mut applicability = Applicability::MachineApplicable;
+
+    if !can_mut_borrow_both(cx, e1, e2) {
+        if let ExprKind::Index(lhs1, idx1) = e1.kind {
+            if let ExprKind::Index(lhs2, idx2) = e2.kind {
+                if eq_expr_value(cx, lhs1, lhs2) {
+                    let ty = cx.typeck_results().expr_ty(lhs1).peel_refs();
+
+                    if matches!(ty.kind(), ty::Slice(_))
+                        || matches!(ty.kind(), ty::Array(_, _))
+                        || is_type_diagnostic_item(cx, ty, sym::vec_type)
+                        || is_type_diagnostic_item(cx, ty, sym::vecdeque_type)
+                    {
+                        let slice = Sugg::hir_with_applicability(cx, lhs1, "<slice>", &mut applicability);
+                        span_lint_and_sugg(
+                            cx,
+                            MANUAL_SWAP,
+                            span,
+                            &format!("this looks like you are swapping elements of `{}` manually", slice),
+                            "try",
+                            format!(
+                                "{}.swap({}, {})",
+                                slice.maybe_par(),
+                                snippet_with_applicability(cx, idx1.span, "..", &mut applicability),
+                                snippet_with_applicability(cx, idx2.span, "..", &mut applicability),
+                            ),
+                            applicability,
+                        );
+                    }
+                }
+            }
+        }
+        return;
+    }
+
+    let first = Sugg::hir_with_applicability(cx, e1, "..", &mut applicability);
+    let second = Sugg::hir_with_applicability(cx, e2, "..", &mut applicability);
+    span_lint_and_then(
+        cx,
+        MANUAL_SWAP,
+        span,
+        &format!("this looks like you are swapping `{}` and `{}` manually", first, second),
+        |diag| {
+            diag.span_suggestion(
+                span,
+                "try",
+                format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
+                applicability,
+            );
+            if !is_xor_based {
+                diag.note("or maybe you should use `std::mem::replace`?");
+            }
+        },
+    );
+}
+
 /// Implementation of the `MANUAL_SWAP` lint.
 fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
     for w in block.stmts.windows(3) {
@@ -96,121 +155,11 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
             if eq_expr_value(cx, tmp_init, lhs1);
             if eq_expr_value(cx, rhs1, lhs2);
             then {
-                if let ExprKind::Field(lhs1, _) = lhs1.kind {
-                    if let ExprKind::Field(lhs2, _) = lhs2.kind {
-                        if lhs1.hir_id.owner == lhs2.hir_id.owner {
-                            return;
-                        }
-                    }
-                }
-
-                let mut applicability = Applicability::MachineApplicable;
-
-                let slice = check_for_slice(cx, lhs1, lhs2);
-                let (replace, what, sugg) = if let Slice::NotSwappable = slice {
-                    return;
-                } else if let Slice::Swappable(slice, idx1, idx2) = slice {
-                    if let Some(slice) = Sugg::hir_opt(cx, slice) {
-                        (
-                            false,
-                            format!(" elements of `{}`", slice),
-                            format!(
-                                "{}.swap({}, {})",
-                                slice.maybe_par(),
-                                snippet_with_applicability(cx, idx1.span, "..", &mut applicability),
-                                snippet_with_applicability(cx, idx2.span, "..", &mut applicability),
-                            ),
-                        )
-                    } else {
-                        (false, String::new(), String::new())
-                    }
-                } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
-                    (
-                        true,
-                        format!(" `{}` and `{}`", first, second),
-                        format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
-                    )
-                } else {
-                    (true, String::new(), String::new())
-                };
-
                 let span = w[0].span.to(second.span);
-
-                span_lint_and_then(
-                    cx,
-                    MANUAL_SWAP,
-                    span,
-                    &format!("this looks like you are swapping{} manually", what),
-                    |diag| {
-                        if !sugg.is_empty() {
-                            diag.span_suggestion(
-                                span,
-                                "try",
-                                sugg,
-                                applicability,
-                            );
-
-                            if replace {
-                                diag.note("or maybe you should use `std::mem::replace`?");
-                            }
-                        }
-                    }
-                );
-            }
-        }
-    }
-}
-
-enum Slice<'a> {
-    /// `slice.swap(idx1, idx2)` can be used
-    ///
-    /// ## Example
-    ///
-    /// ```rust
-    /// # let mut a = vec![0, 1];
-    /// let t = a[1];
-    /// a[1] = a[0];
-    /// a[0] = t;
-    /// // can be written as
-    /// a.swap(0, 1);
-    /// ```
-    Swappable(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>),
-    /// The `swap` function cannot be used.
-    ///
-    /// ## Example
-    ///
-    /// ```rust
-    /// # let mut a = [vec![1, 2], vec![3, 4]];
-    /// let t = a[0][1];
-    /// a[0][1] = a[1][0];
-    /// a[1][0] = t;
-    /// ```
-    NotSwappable,
-    /// Not a slice
-    None,
-}
-
-/// Checks if both expressions are index operations into "slice-like" types.
-fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> {
-    if let ExprKind::Index(lhs1, idx1) = lhs1.kind {
-        if let ExprKind::Index(lhs2, idx2) = lhs2.kind {
-            if eq_expr_value(cx, lhs1, lhs2) {
-                let ty = cx.typeck_results().expr_ty(lhs1).peel_refs();
-
-                if matches!(ty.kind(), ty::Slice(_))
-                    || matches!(ty.kind(), ty::Array(_, _))
-                    || is_type_diagnostic_item(cx, ty, sym::vec_type)
-                    || is_type_diagnostic_item(cx, ty, sym::vecdeque_type)
-                {
-                    return Slice::Swappable(lhs1, idx1, idx2);
-                }
-            } else {
-                return Slice::NotSwappable;
+                generate_swap_warning(cx, lhs1, lhs2, span, false);
             }
         }
     }
-
-    Slice::None
 }
 
 /// Implementation of the `ALMOST_SWAPPED` lint.
@@ -262,3 +211,40 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
         }
     }
 }
+
+/// Implementation of the xor case for `MANUAL_SWAP` lint.
+fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) {
+    for window in block.stmts.windows(3) {
+        if_chain! {
+            if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(&window[0]);
+            if let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(&window[1]);
+            if let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(&window[2]);
+            if eq_expr_value(cx, lhs0, rhs1);
+            if eq_expr_value(cx, lhs2, rhs1);
+            if eq_expr_value(cx, lhs1, rhs0);
+            if eq_expr_value(cx, lhs1, rhs2);
+            then {
+                let span = window[0].span.to(window[2].span);
+                generate_swap_warning(cx, lhs0, rhs0, span, true);
+            }
+        };
+    }
+}
+
+/// Returns the lhs and rhs of an xor assignment statement.  
+fn extract_sides_of_xor_assign<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(&'a Expr<'hir>, &'a Expr<'hir>)> {
+    if let StmtKind::Semi(expr) = stmt.kind {
+        if let ExprKind::AssignOp(
+            Spanned {
+                node: BinOpKind::BitXor,
+                ..
+            },
+            lhs,
+            rhs,
+        ) = expr.kind
+        {
+            return Some((lhs, rhs));
+        }
+    }
+    None
+}
index ad7409fe3a9b7d1fe1f67ce589d850b41ae5a664..371bb8b445a718eceba770325edb1a33fce9ce92 100644 (file)
     /// Checks for use of redundant allocations anywhere in the code.
     ///
     /// ### Why is this bad?
-    /// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, Arc<&T>`, `Arc<Rc<T>>`,
+    /// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, `Arc<&T>`, `Arc<Rc<T>>`,
     /// `Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>`, `Box<Rc<T>>`, `Box<Arc<T>>`, `Box<Box<T>>`, add an unnecessary level of indirection.
     ///
     /// ### Example
index 9acfbc994b382f4c886eb27b0eebe5a3b60d7e5d..c8a231341b7e1063828615e67f16678f06c22332 100644 (file)
@@ -35,8 +35,6 @@
     /// ```
     /// Use instead:
     /// ```rust
-    /// #![feature(or_patterns)]
-    ///
     /// fn main() {
     ///     if let Some(0 | 2) = Some(0) {}
     /// }
index 9ed5e585f841d9bb8f92ee8b36507d8c386c1bc3..1164ac4938fb6a28edce06017a0c0082869eaa83 100644 (file)
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::position_before_rarrow;
+use clippy_utils::source::{position_before_rarrow, snippet_opt};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_ast::visit::FnKind;
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 use rustc_span::BytePos;
@@ -125,17 +125,16 @@ fn is_unit_expr(expr: &ast::Expr) -> bool {
 }
 
 fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
-    let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) {
-        position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
-            (
-                #[allow(clippy::cast_possible_truncation)]
-                ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
-                Applicability::MachineApplicable,
-            )
-        })
-    } else {
-        (ty.span, Applicability::MaybeIncorrect)
-    };
+    let (ret_span, appl) =
+        snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| {
+            position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+                (
+                    #[allow(clippy::cast_possible_truncation)]
+                    ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
+                    Applicability::MachineApplicable,
+                )
+            })
+        });
     span_lint_and_sugg(
         cx,
         UNUSED_UNIT,
index 44d3d4563428d4f4de8a937a1e85263d70a4b558..a28b1d78f7d463a90f593306b1343ea0dc417bec 100644 (file)
@@ -36,13 +36,13 @@ fn from_error(error: impl Error) -> Self {
 /// See (rust-clippy#7172)
 macro_rules! define_Conf {
     ($(
-        #[doc = $doc:literal]
+        $(#[doc = $doc:literal])+
         $(#[conf_deprecated($dep:literal)])?
         ($name:ident: $ty:ty = $default:expr),
     )*) => {
         /// Clippy lint configuration
         pub struct Conf {
-            $(#[doc = $doc] pub $name: $ty,)*
+            $($(#[doc = $doc])+ pub $name: $ty,)*
         }
 
         mod defaults {
@@ -119,7 +119,7 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
                                 stringify!($name),
                                 stringify!($ty),
                                 format!("{:?}", super::defaults::$name()),
-                                $doc,
+                                concat!($($doc, '\n',)*),
                                 deprecation_reason,
                             )
                         },
@@ -132,18 +132,30 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
 
 // N.B., this macro is parsed by util/lintlib.py
 define_Conf! {
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. Suppress lints whenever the suggested change would cause breakage for other crates.
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION.
+    ///
+    /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
-    /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports
+    /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE.
+    ///
+    /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
-    /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
+    /// Lint: BLACKLISTED_NAME.
+    ///
+    /// The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
     (blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
-    /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
+    /// Lint: COGNITIVE_COMPLEXITY.
+    ///
+    /// The maximum cognitive complexity a function can have
     (cognitive_complexity_threshold: u64 = 25),
-    /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
+    /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
+    ///
+    /// Use the Cognitive Complexity lint instead.
     #[conf_deprecated("Please use `cognitive-complexity-threshold` instead")]
     (cyclomatic_complexity_threshold: Option<u64> = None),
-    /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks
+    /// Lint: DOC_MARKDOWN.
+    ///
+    /// The list of words this lint should not consider as identifiers needing ticks
     (doc_valid_idents: Vec<String> = [
         "KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
         "DirectX",
@@ -164,55 +176,109 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
         "MinGW",
         "CamelCase",
     ].iter().map(ToString::to_string).collect()),
-    /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have
+    /// Lint: TOO_MANY_ARGUMENTS.
+    ///
+    /// The maximum number of argument a function or method can have
     (too_many_arguments_threshold: u64 = 7),
-    /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have
+    /// Lint: TYPE_COMPLEXITY.
+    ///
+    /// The maximum complexity a type can have
     (type_complexity_threshold: u64 = 250),
-    /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have
+    /// Lint: MANY_SINGLE_CHAR_NAMES.
+    ///
+    /// The maximum number of single char bindings a scope may have
     (single_char_binding_names_threshold: u64 = 4),
-    /// Lint: BOXED_LOCAL, USELESS_VEC. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
+    /// Lint: BOXED_LOCAL, USELESS_VEC.
+    ///
+    /// The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
     (too_large_for_stack: u64 = 200),
-    /// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger
+    /// Lint: ENUM_VARIANT_NAMES.
+    ///
+    /// The minimum number of enum variants for the lints about variant names to trigger
     (enum_variant_name_threshold: u64 = 3),
-    /// Lint: LARGE_ENUM_VARIANT. The maximum size of a enum's variant to avoid box suggestion
+    /// Lint: LARGE_ENUM_VARIANT.
+    ///
+    /// The maximum size of a enum's variant to avoid box suggestion
     (enum_variant_size_threshold: u64 = 200),
-    /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
+    /// Lint: VERBOSE_BIT_MASK.
+    ///
+    /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
     (verbose_bit_mask_threshold: u64 = 1),
-    /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals
+    /// Lint: DECIMAL_LITERAL_REPRESENTATION.
+    ///
+    /// The lower bound for linting decimal literals
     (literal_representation_threshold: u64 = 16384),
-    /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
+    /// Lint: TRIVIALLY_COPY_PASS_BY_REF.
+    ///
+    /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
     (trivial_copy_size_limit: Option<u64> = None),
-    /// Lint: LARGE_TYPE_PASS_BY_MOVE. The minimum size (in bytes) to consider a type for passing by reference instead of by value.
+    /// Lint: LARGE_TYPE_PASS_BY_MOVE.
+    ///
+    /// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
     (pass_by_value_size_limit: u64 = 256),
-    /// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have
+    /// Lint: TOO_MANY_LINES.
+    ///
+    /// The maximum number of lines a function or method can have
     (too_many_lines_threshold: u64 = 100),
-    /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS. The maximum allowed size for arrays on the stack
+    /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS.
+    ///
+    /// The maximum allowed size for arrays on the stack
     (array_size_threshold: u64 = 512_000),
-    /// Lint: VEC_BOX. The size of the boxed type in bytes, where boxing in a `Vec` is allowed
+    /// Lint: VEC_BOX.
+    ///
+    /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
     (vec_box_size_threshold: u64 = 4096),
-    /// Lint: TYPE_REPETITION_IN_BOUNDS. The maximum number of bounds a trait can have to be linted
+    /// Lint: TYPE_REPETITION_IN_BOUNDS.
+    ///
+    /// The maximum number of bounds a trait can have to be linted
     (max_trait_bounds: u64 = 3),
-    /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bool fields a struct can have
+    /// Lint: STRUCT_EXCESSIVE_BOOLS.
+    ///
+    /// The maximum number of bool fields a struct can have
     (max_struct_bools: u64 = 3),
-    /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bool parameters a function can have
+    /// Lint: FN_PARAMS_EXCESSIVE_BOOLS.
+    ///
+    /// The maximum number of bool parameters a function can have
     (max_fn_params_bools: u64 = 3),
-    /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
+    /// Lint: WILDCARD_IMPORTS.
+    ///
+    /// Whether to allow certain wildcard imports (prelude, super in tests).
     (warn_on_all_wildcard_imports: bool = false),
-    /// Lint: DISALLOWED_METHOD. The list of disallowed methods, written as fully qualified paths.
+    /// Lint: DISALLOWED_METHOD.
+    ///
+    /// The list of disallowed methods, written as fully qualified paths.
     (disallowed_methods: Vec<String> = Vec::new()),
-    /// Lint: DISALLOWED_TYPE. The list of disallowed types, written as fully qualified paths.
+    /// Lint: DISALLOWED_TYPE.
+    ///
+    /// The list of disallowed types, written as fully qualified paths.
     (disallowed_types: Vec<String> = Vec::new()),
-    /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators.
+    /// Lint: UNREADABLE_LITERAL.
+    ///
+    /// Should the fraction of a decimal be linted to include separators.
     (unreadable_literal_lint_fractions: bool = true),
-    /// Lint: UPPER_CASE_ACRONYMS. Enables verbose mode. Triggers if there is more than one uppercase char next to each other
+    /// Lint: UPPER_CASE_ACRONYMS.
+    ///
+    /// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
     (upper_case_acronyms_aggressive: bool = false),
-    /// Lint: _CARGO_COMMON_METADATA. For internal testing only, ignores the current `publish` settings in the Cargo manifest.
+    /// Lint: _CARGO_COMMON_METADATA.
+    ///
+    /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
     (cargo_ignore_publish: bool = false),
-    /// Lint: NONSTANDARD_MACRO_BRACES. Enforce the named macros always use the braces specified. <br> A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro is could be used with a full path two `MacroMatcher`s have to be added one with the full path `crate_name::macro_name` and one with just the macro name.
+    /// Lint: NONSTANDARD_MACRO_BRACES.
+    ///
+    /// Enforce the named macros always use the braces specified.
+    ///
+    /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
+    /// is could be used with a full path two `MacroMatcher`s have to be added one with the full path
+    /// `crate_name::macro_name` and one with just the macro name.
     (standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()),
-    /// Lint: MISSING_ENFORCED_IMPORT_RENAMES. The list of imports to always rename, a fully qualified path followed by the rename.
+    /// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
+    ///
+    /// The list of imports to always rename, a fully qualified path followed by the rename.
     (enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
-    /// Lint: RESTRICTED_SCRIPTS. The list of unicode scripts allowed to be used in the scope.
+    /// Lint: RESTRICTED_SCRIPTS.
+    ///
+    /// The list of unicode scripts allowed to be used in the scope.
     (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
 }
 
index 47336459d7da6ce30223cebd93c09d7664652970..a48a53850830f3e41dbd6f61a3ab59a66bab8ff2 100644 (file)
@@ -82,7 +82,7 @@ macro_rules! CONFIGURATION_SECTION_TEMPLATE {
 /// `default`
 macro_rules! CONFIGURATION_VALUE_TEMPLATE {
     () => {
-        "* {name}: {ty}: {doc} (defaults to `{default}`)\n"
+        "* {name}: `{ty}`: {doc} (defaults to `{default}`)\n"
     };
 }
 
@@ -344,11 +344,16 @@ fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
         if let Some(split_pos) = doc_comment.find('.');
         then {
             let mut doc_comment = doc_comment.to_string();
-            let documentation = doc_comment.split_off(split_pos);
+            let mut documentation = doc_comment.split_off(split_pos);
 
+            // Extract lints
             doc_comment.make_ascii_lowercase();
             let lints: Vec<String> = doc_comment.split_off(DOC_START.len()).split(", ").map(str::to_string).collect();
 
+            // Format documentation correctly
+            // split off leading `.` from lint name list and indent for correct formatting
+            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
+
             Some((lints, documentation))
         } else {
             None
index 7c94474cb35d2f8cbee0a217b491df2a13be515a..71cfa196fc335f93d7b62e5d0234e08a08f33780 100644 (file)
@@ -65,7 +65,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
 ///
 /// # Example
 ///
-/// ```ignore
+/// ```text
 /// error: constant division of 0.0 with 0.0 will always result in NaN
 ///   --> $DIR/zero_div_zero.rs:6:25
 ///    |
@@ -103,7 +103,7 @@ pub fn span_lint_and_help<'a, T: LintContext>(
 ///
 /// # Example
 ///
-/// ```ignore
+/// ```text
 /// error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
 ///   --> $DIR/drop_forget_ref.rs:10:5
 ///    |
@@ -189,7 +189,7 @@ pub fn span_lint_hir_and_then(
 ///
 /// # Example
 ///
-/// ```ignore
+/// ```text
 /// error: This `.fold` can be more succinctly expressed as `.any`
 /// --> $DIR/methods.rs:390:13
 ///     |
index f32f1109b08e64ec963dea3b653f120e816d0f0d..884180f0586e38a237d4f7e8561115e6a8f6ea67 100644 (file)
@@ -195,8 +195,8 @@ pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<Ve
 /// - `assert!`, `assert_eq!` and `assert_ne!`
 /// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
 /// For example:
-/// `assert!(expr)` will return Some([expr])
-/// `debug_assert_eq!(a, b)` will return Some([a, b])
+/// `assert!(expr)` will return `Some([expr])`
+/// `debug_assert_eq!(a, b)` will return `Some([a, b])`
 pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx Expr<'tcx>>> {
     /// Try to match the AST for a pattern that contains a match, for example when two args are
     /// compared
@@ -283,7 +283,7 @@ pub struct FormatArgsExpn<'tcx> {
 
     /// String literal expressions which represent the format string split by "{}"
     pub format_string_parts: &'tcx [Expr<'tcx>],
-    /// Symbols corresponding to [`format_string_parts`]
+    /// Symbols corresponding to [`Self::format_string_parts`]
     pub format_string_symbols: Vec<Symbol>,
     /// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
     pub args: &'tcx [Expr<'tcx>],
index 59f878f8b20ab58da70194a9b684dbc2b4b2b931..1d59d6bfea1b9792b314de615677809119efa94b 100644 (file)
@@ -326,6 +326,25 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
         .map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
 }
 
+/// Checks if the given expression is a path referring an item on the trait
+/// that is marked with the given diagnostic item.
+///
+/// For checking method call expressions instead of path expressions, use
+/// [`is_trait_method`].
+///
+/// For example, this can be used to find if an expression like `u64::default`
+/// refers to an item of the trait `Default`, which is associated with the
+/// `diag_item` of `sym::Default`.
+pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
+    if let hir::ExprKind::Path(ref qpath) = expr.kind {
+        cx.qpath_res(qpath, expr.hir_id)
+            .opt_def_id()
+            .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
+    } else {
+        false
+    }
+}
+
 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
     match *path {
         QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
@@ -558,6 +577,54 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
     None
 }
 
+/// This method will return tuple of projection stack and root of the expression,
+/// used in `can_mut_borrow_both`.
+///
+/// For example, if `e` represents the `v[0].a.b[x]`
+/// this method will return a tuple, composed of a `Vec`
+/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
+/// and a `Expr` for root of them, `v`
+fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
+    let mut result = vec![];
+    let root = loop {
+        match e.kind {
+            ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => {
+                result.push(e);
+                e = ep;
+            },
+            _ => break e,
+        };
+    };
+    result.reverse();
+    (result, root)
+}
+
+/// Checks if two expressions can be mutably borrowed simultaneously
+/// and they aren't dependent on borrowing same thing twice
+pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
+    let (s1, r1) = projection_stack(e1);
+    let (s2, r2) = projection_stack(e2);
+    if !eq_expr_value(cx, r1, r2) {
+        return true;
+    }
+    for (x1, x2) in s1.iter().zip(s2.iter()) {
+        match (&x1.kind, &x2.kind) {
+            (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
+                if i1 != i2 {
+                    return true;
+                }
+            },
+            (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => {
+                if !eq_expr_value(cx, i1, i2) {
+                    return false;
+                }
+            },
+            _ => return false,
+        }
+    }
+    false
+}
+
 /// Checks if the top level expression can be moved into a closure as is.
 pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool {
     match expr.kind {
index 4d49b43bde9ecd9751bc825b55afad614e5f1fd7..789079510c5e80fa7251536eeda79336d99e7777 100644 (file)
@@ -168,7 +168,7 @@ pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<
     snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
 }
 
-/// Same as `snippet`, but it adapts the applicability level by following rules:
+/// Same as [`snippet`], but it adapts the applicability level by following rules:
 ///
 /// - Applicability level `Unspecified` will never be changed.
 /// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
index e914dc1c222f681549855fd75bbbd2b6ccbb3202..4f9aaf396b806dbe0b7d56c8eab2298e9af18922 100644 (file)
@@ -114,7 +114,7 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<
 
 /// Checks whether a type implements a trait.
 /// The function returns false in case the type contains an inference variable.
-/// See also `get_trait_def_id`.
+/// See also [`get_trait_def_id`](super::get_trait_def_id).
 pub fn implements_trait<'tcx>(
     cx: &LateContext<'tcx>,
     ty: Ty<'tcx>,
index 43d3792f5952125a80cb1eccb4b9d35213301a60..ff2e0417435bfe72edb635fd725cb476cf47a335 100644 (file)
@@ -166,8 +166,8 @@ rustup component add clippy
 ```
 
 > **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup
-[proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
-`~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
-`rustup update`.
+[proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
+`~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
+`rustup update`.
 
 [glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html
index bff657bc1103815b899341e5476e10286b880c5c..23887f178454972c47b777c305ded39a12d84fbf 100644 (file)
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-07-29"
+channel = "nightly-2021-08-12"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
diff --git a/src/tools/clippy/tests/auxiliary/test_macro.rs b/src/tools/clippy/tests/auxiliary/test_macro.rs
deleted file mode 100644 (file)
index 624ca89..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-pub trait A {}
-
-macro_rules! __implicit_hasher_test_macro {
-    (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => {
-        __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) );
-    };
-
-    (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => {
-        impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { }
-    };
-}
index a47677a1f3a2e02c8bb6a5b3bdf3f742c6954e6c..33a3ef7513631aab7d1fb367d49c9993ab1c44ad 100644 (file)
@@ -1,3 +1,5 @@
+// edition:2018
+
 #![warn(clippy::too_many_lines)]
 
 // This function should be considered one line.
@@ -20,6 +22,20 @@ fn too_many_lines() {
     println!("This is bad.");
 }
 
+// This should only fail once (#7517).
+async fn async_too_many_lines() {
+    println!("This is bad.");
+    println!("This is bad.");
+}
+
+// This should fail only once, without failing on the closure.
+fn closure_too_many_lines() {
+    let _ = {
+        println!("This is bad.");
+        println!("This is bad.");
+    };
+}
+
 // This should be considered one line.
 #[rustfmt::skip]
 fn comment_starts_after_code() {
index a27ce945ca58461cc08fef154aef3ba7c3cc7f23..7551cac9f504b968918e65f3d82ae0ee1b800cf0 100644 (file)
@@ -1,5 +1,5 @@
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:18:1
+  --> $DIR/test.rs:20:1
    |
 LL | / fn too_many_lines() {
 LL | |     println!("This is bad.");
@@ -9,8 +9,28 @@ LL | | }
    |
    = note: `-D clippy::too-many-lines` implied by `-D warnings`
 
+error: this function has too many lines (4/1)
+  --> $DIR/test.rs:26:1
+   |
+LL | / async fn async_too_many_lines() {
+LL | |     println!("This is bad.");
+LL | |     println!("This is bad.");
+LL | | }
+   | |_^
+
+error: this function has too many lines (4/1)
+  --> $DIR/test.rs:32:1
+   |
+LL | / fn closure_too_many_lines() {
+LL | |     let _ = {
+LL | |         println!("This is bad.");
+LL | |         println!("This is bad.");
+LL | |     };
+LL | | }
+   | |_^
+
 error: this function has too many lines (2/1)
-  --> $DIR/test.rs:38:1
+  --> $DIR/test.rs:54:1
    |
 LL | / fn comment_before_code() {
 LL | |     let _ = "test";
@@ -19,5 +39,5 @@ LL | |     the code but this line should still count. */ let _ = 5;
 LL | | }
    | |_^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
index e9f042ddefcde5711e361c3979854c555c2272f5..5b4adc868dff19259611c087a3623dfdacf2d3d0 100644 (file)
@@ -32,13 +32,19 @@ macro_rules! type_pos {
     };
 }
 
+macro_rules! printlnfoo {
+    ($thing:expr) => {
+        println!("{}", $thing)
+    };
+}
+
 #[rustfmt::skip]
 fn main() {
     let _ = vec! {1, 2, 3};
     let _ = format!["ugh {} stop being such a good compiler", "hello"];
     let _ = quote!(let x = 1;);
     let _ = quote::quote!(match match match);
-    let _ = test!();
+    let _ = test!(); // trigger when macro def is inside our own crate
     let _ = vec![1,2,3];
 
     let _ = quote::quote! {true || false};
@@ -49,4 +55,6 @@ fn main() {
     let _: type_pos!(usize) = vec![];
 
     eprint!("test if user config overrides defaults");
+
+    printlnfoo!["test if printlnfoo is triggered by println"];
 }
index 86063a08280867dd59589b58ecf021ad35b608f4..87e962b9228c4b74627e5d7623761b0f5a246141 100644 (file)
@@ -1,48 +1,48 @@
 error: use of irregular braces for `vec!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:43:13
    |
 LL |     let _ = vec! {1, 2, 3};
    |             ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
 help: consider writing `vec![1, 2, 3]`
-  --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:43:13
    |
 LL |     let _ = vec! {1, 2, 3};
    |             ^^^^^^^^^^^^^^
 
 error: use of irregular braces for `format!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:44:13
    |
 LL |     let _ = format!["ugh {} stop being such a good compiler", "hello"];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider writing `format!("ugh () stop being such a good compiler", "hello")`
-  --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:44:13
    |
 LL |     let _ = format!["ugh {} stop being such a good compiler", "hello"];
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of irregular braces for `quote!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:45:13
    |
 LL |     let _ = quote!(let x = 1;);
    |             ^^^^^^^^^^^^^^^^^^
    |
 help: consider writing `quote! {let x = 1;}`
-  --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:45:13
    |
 LL |     let _ = quote!(let x = 1;);
    |             ^^^^^^^^^^^^^^^^^^
 
 error: use of irregular braces for `quote::quote!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:46:13
    |
 LL |     let _ = quote::quote!(match match match);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider writing `quote::quote! {match match match}`
-  --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+  --> $DIR/conf_nonstandard_macro_braces.rs:46:13
    |
 LL |     let _ = quote::quote!(match match match);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ error: use of irregular braces for `vec!` macro
 LL |         vec!{0, 0, 0}
    |         ^^^^^^^^^^^^^
 ...
-LL |     let _ = test!();
+LL |     let _ = test!(); // trigger when macro def is inside our own crate
    |             ------- in this macro invocation
    |
 help: consider writing `vec![0, 0, 0]`
@@ -62,30 +62,30 @@ help: consider writing `vec![0, 0, 0]`
 LL |         vec!{0, 0, 0}
    |         ^^^^^^^^^^^^^
 ...
-LL |     let _ = test!();
+LL |     let _ = test!(); // trigger when macro def is inside our own crate
    |             ------- in this macro invocation
    = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: use of irregular braces for `type_pos!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+  --> $DIR/conf_nonstandard_macro_braces.rs:55:12
    |
 LL |     let _: type_pos!(usize) = vec![];
    |            ^^^^^^^^^^^^^^^^
    |
 help: consider writing `type_pos![usize]`
-  --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+  --> $DIR/conf_nonstandard_macro_braces.rs:55:12
    |
 LL |     let _: type_pos!(usize) = vec![];
    |            ^^^^^^^^^^^^^^^^
 
 error: use of irregular braces for `eprint!` macro
-  --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+  --> $DIR/conf_nonstandard_macro_braces.rs:57:5
    |
 LL |     eprint!("test if user config overrides defaults");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 help: consider writing `eprint!["test if user config overrides defaults"];`
-  --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+  --> $DIR/conf_nonstandard_macro_braces.rs:57:5
    |
 LL |     eprint!("test if user config overrides defaults");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/auxiliary/test_macro.rs b/src/tools/clippy/tests/ui/auxiliary/test_macro.rs
new file mode 100644 (file)
index 0000000..624ca89
--- /dev/null
@@ -0,0 +1,11 @@
+pub trait A {}
+
+macro_rules! __implicit_hasher_test_macro {
+    (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => {
+        __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) );
+    };
+
+    (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => {
+        impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { }
+    };
+}
index 8b2c318acf84e108982231e08c281889057757ba..9a89047f072777cd7f6bf3f5588083be74b7f6b0 100644 (file)
@@ -6,7 +6,7 @@ LL |     for<'a> Dst<A + 'a>: Sized,
    |
    = note: `-D bare-trait-objects` implied by `-D warnings`
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: trait objects without an explicit `dyn` are deprecated
   --> $DIR/ice-3969.rs:27:16
@@ -15,7 +15,7 @@ LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
    |                ^ help: use `dyn`: `dyn A`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: trait objects without an explicit `dyn` are deprecated
   --> $DIR/ice-3969.rs:27:57
@@ -24,7 +24,7 @@ LL |     let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
    |                                                         ^ help: use `dyn`: `dyn A`
    |
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
 
 error: aborting due to 3 previous errors
 
index 00170e649e2516846db199cc75e6f9a473ef24ca..e863870e7d61b01ae9dfe0992264b7707a2d0507 100644 (file)
@@ -41,7 +41,12 @@ fn main() {
 
     let mut heap = BinaryHeap::from(vec![1, 3]);
     let mut heap2 = BinaryHeap::from(vec![]);
-    heap2.extend(heap.drain())
+    heap2.extend(heap.drain());
+
+    let mut x = vec![0, 1, 2, 3, 5];
+    let ref_x = &mut x;
+    let mut y = Vec::new();
+    y.append(ref_x);
 }
 
 fn return_vector() -> Vec<u8> {
index d76458c32891acc7c91ee72172a260e4d62f9729..dcb36b5951cb28285a2b973b5aa19b692a009d9c 100644 (file)
@@ -41,7 +41,12 @@ fn main() {
 
     let mut heap = BinaryHeap::from(vec![1, 3]);
     let mut heap2 = BinaryHeap::from(vec![]);
-    heap2.extend(heap.drain())
+    heap2.extend(heap.drain());
+
+    let mut x = vec![0, 1, 2, 3, 5];
+    let ref_x = &mut x;
+    let mut y = Vec::new();
+    y.extend(ref_x.drain(..));
 }
 
 fn return_vector() -> Vec<u8> {
index 57f344716a16d1d4f8f3ebdda213e933d05940d4..da14ddb25b373754412fe99adb23f80b0a71f60c 100644 (file)
@@ -18,5 +18,11 @@ error: use of `extend` instead of `append` for adding the full range of a second
 LL |     vec11.extend(return_vector().drain(..));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec11.append(&mut return_vector())`
 
-error: aborting due to 3 previous errors
+error: use of `extend` instead of `append` for adding the full range of a second vector
+  --> $DIR/extend_with_drain.rs:49:5
+   |
+LL |     y.extend(ref_x.drain(..));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `y.append(ref_x)`
+
+error: aborting due to 4 previous errors
 
index fdcc9a33f55fe93e2d5989f1757b2233c43c3d78..97c26bc83ad4b4af2b919c4ecf53c30fcd4fd66a 100644 (file)
@@ -89,7 +89,7 @@ pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
 // and should not cause an ICE
 // See #2707
 #[macro_use]
-#[path = "../auxiliary/test_macro.rs"]
+#[path = "auxiliary/test_macro.rs"]
 pub mod test_macro;
 __implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
 
index 773b5914439d39f03ccc5cacd3666f68c0d67eb6..18846c898da051566ee99796f98af0724f91def5 100644 (file)
@@ -5,6 +5,7 @@
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::unnecessary_wraps)]
+#![feature(result_flattening)]
 
 fn main() {
     // mapping to Option on Iterator
@@ -23,4 +24,7 @@ fn main() {
 
     // mapping to Option on Option
     let _: Option<_> = (Some(Some(1))).and_then(|x| x);
+
+    // mapping to Result on Result
+    let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x);
 }
index 578bd877267952da8f126e277a63e9fdc94176ba..01db27876da703a698c4b0da0ccef2dcba2cf790 100644 (file)
@@ -5,6 +5,7 @@
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::unnecessary_wraps)]
+#![feature(result_flattening)]
 
 fn main() {
     // mapping to Option on Iterator
@@ -23,4 +24,7 @@ fn option_id(x: i8) -> Option<i8> {
 
     // mapping to Option on Option
     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
+
+    // mapping to Result on Result
+    let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
 }
index 756e6e818ad4454ee42494add7f11610d078295d..38457c8ea4dd4ad16de7cb16eb7c880c90d176cf 100644 (file)
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:16:46
+  --> $DIR/map_flatten.rs:17:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id)`
@@ -7,34 +7,40 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:17:46
+  --> $DIR/map_flatten.rs:18:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:18:46
+  --> $DIR/map_flatten.rs:19:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:19:46
+  --> $DIR/map_flatten.rs:20:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on an `Iterator`
-  --> $DIR/map_flatten.rs:22:46
+  --> $DIR/map_flatten.rs:23:46
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `.flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on an `Option`
-  --> $DIR/map_flatten.rs:25:39
+  --> $DIR/map_flatten.rs:26:39
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                       ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)`
 
-error: aborting due to 6 previous errors
+error: called `map(..).flatten()` on an `Result`
+  --> $DIR/map_flatten.rs:29:41
+   |
+LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
+   |                                         ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)`
+
+error: aborting due to 7 previous errors
 
index c00b4c78cf28b49182ec4441d84bcc9b10230ea9..f49b23924efe8b5c52fb807098bf3fd5760c570b 100644 (file)
@@ -75,6 +75,11 @@ LL | |             _ => return,
 LL | |         }
 LL | |     }
    | |_____^
+   |
+help: if you need the first element of the iterator, try writing
+   |
+LL |     if let Some(x) = (0..10).next() {
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: this loop never actually loops
   --> $DIR/never_loop.rs:157:5
index 834b9056e311df0c0847e6c2e7afb79f6647d9f5..6b24675ac2d42a8a934a85989394ca2920c44895 100644 (file)
@@ -108,6 +108,12 @@ error: statement with no effect
 LL |     5..6;
    |     ^^^^^
 
+error: statement with no effect
+  --> $DIR/no_effect.rs:83:5
+   |
+LL |     5..=6;
+   |     ^^^^^^
+
 error: statement with no effect
   --> $DIR/no_effect.rs:84:5
    |
@@ -150,5 +156,5 @@ error: statement with no effect
 LL |     FooString { s: s };
    |     ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: aborting due to 26 previous errors
 
index 4390ff7dc30443ad89e792acca983a79b5deb211..c2f94d0e8575650272656acba755013a0de37ddb 100644 (file)
@@ -18,6 +18,19 @@ fn or_fun_call() {
         }
     }
 
+    struct FakeDefault;
+    impl FakeDefault {
+        fn default() -> Self {
+            FakeDefault
+        }
+    }
+
+    impl Default for FakeDefault {
+        fn default() -> Self {
+            FakeDefault
+        }
+    }
+
     enum Enum {
         A(i32),
     }
@@ -53,6 +66,12 @@ fn or_fun_call() {
     let with_default_type = Some(1);
     with_default_type.unwrap_or_default();
 
+    let self_default = None::<FakeDefault>;
+    self_default.unwrap_or_else(<FakeDefault>::default);
+
+    let real_default = None::<FakeDefault>;
+    real_default.unwrap_or_default();
+
     let with_vec = Some(vec![1]);
     with_vec.unwrap_or_default();
 
index 75908c974cc9dee899caba732b0cb72cd118e982..afaf92961b0274f75d9e5ffbbd2f40b606fb876a 100644 (file)
@@ -18,6 +18,19 @@ fn new() -> Foo {
         }
     }
 
+    struct FakeDefault;
+    impl FakeDefault {
+        fn default() -> Self {
+            FakeDefault
+        }
+    }
+
+    impl Default for FakeDefault {
+        fn default() -> Self {
+            FakeDefault
+        }
+    }
+
     enum Enum {
         A(i32),
     }
@@ -53,6 +66,12 @@ fn make<T>() -> T {
     let with_default_type = Some(1);
     with_default_type.unwrap_or(u64::default());
 
+    let self_default = None::<FakeDefault>;
+    self_default.unwrap_or(<FakeDefault>::default());
+
+    let real_default = None::<FakeDefault>;
+    real_default.unwrap_or(<FakeDefault as Default>::default());
+
     let with_vec = Some(vec![1]);
     with_vec.unwrap_or(vec![]);
 
index 9905029ce91fa9f56bf95c356019af250e31576d..b2bcbd38c2df36061eefebf4f788821471955d6f 100644 (file)
@@ -1,5 +1,5 @@
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:33:19
+  --> $DIR/or_fun_call.rs:46:19
    |
 LL |     with_const_fn.unwrap_or(Duration::from_secs(5));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Duration::from_secs(5))`
@@ -7,130 +7,142 @@ LL |     with_const_fn.unwrap_or(Duration::from_secs(5));
    = note: `-D clippy::or-fun-call` implied by `-D warnings`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:36:22
+  --> $DIR/or_fun_call.rs:49:22
    |
 LL |     with_constructor.unwrap_or(make());
    |                      ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
 
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:39:5
+  --> $DIR/or_fun_call.rs:52:5
    |
 LL |     with_new.unwrap_or(Vec::new());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:42:21
+  --> $DIR/or_fun_call.rs:55:21
    |
 LL |     with_const_args.unwrap_or(Vec::with_capacity(12));
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:45:14
+  --> $DIR/or_fun_call.rs:58:14
    |
 LL |     with_err.unwrap_or(make());
    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:48:19
+  --> $DIR/or_fun_call.rs:61:19
    |
 LL |     with_err_args.unwrap_or(Vec::with_capacity(12));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:51:5
+  --> $DIR/or_fun_call.rs:64:5
    |
 LL |     with_default_trait.unwrap_or(Default::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a call to `default`
-  --> $DIR/or_fun_call.rs:54:5
+  --> $DIR/or_fun_call.rs:67:5
    |
 LL |     with_default_type.unwrap_or(u64::default());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()`
 
+error: use of `unwrap_or` followed by a function call
+  --> $DIR/or_fun_call.rs:70:18
+   |
+LL |     self_default.unwrap_or(<FakeDefault>::default());
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(<FakeDefault>::default)`
+
+error: use of `unwrap_or` followed by a call to `default`
+  --> $DIR/or_fun_call.rs:73:5
+   |
+LL |     real_default.unwrap_or(<FakeDefault as Default>::default());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `real_default.unwrap_or_default()`
+
 error: use of `unwrap_or` followed by a call to `new`
-  --> $DIR/or_fun_call.rs:57:5
+  --> $DIR/or_fun_call.rs:76:5
    |
 LL |     with_vec.unwrap_or(vec![]);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:60:21
+  --> $DIR/or_fun_call.rs:79:21
    |
 LL |     without_default.unwrap_or(Foo::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:63:19
+  --> $DIR/or_fun_call.rs:82:19
    |
 LL |     map.entry(42).or_insert(String::new());
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:66:23
+  --> $DIR/or_fun_call.rs:85:23
    |
 LL |     map_vec.entry(42).or_insert(vec![]);
    |                       ^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(Vec::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:69:21
+  --> $DIR/or_fun_call.rs:88:21
    |
 LL |     btree.entry(42).or_insert(String::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
 
 error: use of `or_insert` followed by a function call
-  --> $DIR/or_fun_call.rs:72:25
+  --> $DIR/or_fun_call.rs:91:25
    |
 LL |     btree_vec.entry(42).or_insert(vec![]);
    |                         ^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(Vec::new)`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:75:21
+  --> $DIR/or_fun_call.rs:94:21
    |
 LL |     let _ = stringy.unwrap_or("".to_owned());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:83:21
+  --> $DIR/or_fun_call.rs:102:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:85:21
+  --> $DIR/or_fun_call.rs:104:21
    |
 LL |     let _ = Some(1).unwrap_or(map[&1]);
    |                     ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:109:35
+  --> $DIR/or_fun_call.rs:128:35
    |
 LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:113:10
+  --> $DIR/or_fun_call.rs:132:10
    |
 LL |         .or(Some(Bar(b, Duration::from_secs(2))));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:141:14
+  --> $DIR/or_fun_call.rs:160:14
    |
 LL |         None.unwrap_or(s.as_mut_vec());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| s.as_mut_vec())`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:146:14
+  --> $DIR/or_fun_call.rs:165:14
    |
 LL |         None.unwrap_or(unsafe { s.as_mut_vec() });
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
 
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:148:14
+  --> $DIR/or_fun_call.rs:167:14
    |
 LL |         None.unwrap_or( unsafe { s.as_mut_vec() }    );
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
 
-error: aborting due to 22 previous errors
+error: aborting due to 24 previous errors
 
index 2b1bc1f48595977245d7de1c62932ff2cc2eda8c..daa073414577c8bfd897f37fe8b9a944eb063fe3 100644 (file)
@@ -76,6 +76,9 @@ fn main() {
     // names often used in win32 code (for example WindowProc)
     let wparam: i32;
     let lparam: i32;
+
+    let iter: i32;
+    let item: i32;
 }
 
 fn foo() {
index b24accd962a7f006d42862f7b4c55395cbbae5a6..f621595abaea2ee295423dbcb04b990f63b7184c 100644 (file)
@@ -72,13 +72,13 @@ LL |     let parser: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:85:16
+  --> $DIR/similar_names.rs:88:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:84:16
+  --> $DIR/similar_names.rs:87:16
    |
 LL |         apple: spring,
    |                ^^^^^^
index 0f8f839a0d5426fa808fbe2384875ee427ff18ed..ef518359ec5f373614727442c65526c05a5c1899 100644 (file)
@@ -6,6 +6,7 @@
     clippy::no_effect,
     clippy::redundant_clone,
     redundant_semicolons,
+    dead_code,
     unused_assignments
 )]
 
@@ -20,9 +21,7 @@ struct Bar {
 fn field() {
     let mut bar = Bar { a: 1, b: 2 };
 
-    let temp = bar.a;
-    bar.a = bar.b;
-    bar.b = temp;
+    std::mem::swap(&mut bar.a, &mut bar.b);
 
     let mut baz = vec![bar.clone(), bar.clone()];
     let temp = baz[0].a;
@@ -51,6 +50,7 @@ fn unswappable_slice() {
     foo[1][0] = temp;
 
     // swap(foo[0][1], foo[1][0]) would fail
+    // this could use split_at_mut and mem::swap, but that is not much simpler.
 }
 
 fn vec() {
@@ -60,13 +60,54 @@ fn vec() {
     foo.swap(0, 1);
 }
 
+fn xor_swap_locals() {
+    // This is an xor-based swap of local variables.
+    let mut a = 0;
+    let mut b = 1;
+    std::mem::swap(&mut a, &mut b)
+}
+
+fn xor_field_swap() {
+    // This is an xor-based swap of fields in a struct.
+    let mut bar = Bar { a: 0, b: 1 };
+    std::mem::swap(&mut bar.a, &mut bar.b)
+}
+
+fn xor_slice_swap() {
+    // This is an xor-based swap of a slice
+    let foo = &mut [1, 2];
+    foo.swap(0, 1)
+}
+
+fn xor_no_swap() {
+    // This is a sequence of xor-assignment statements that doesn't result in a swap.
+    let mut a = 0;
+    let mut b = 1;
+    let mut c = 2;
+    a ^= b;
+    b ^= c;
+    a ^= c;
+    c ^= a;
+}
+
+fn xor_unswappable_slice() {
+    let foo = &mut [vec![1, 2], vec![3, 4]];
+    foo[0][1] ^= foo[1][0];
+    foo[1][0] ^= foo[0][0];
+    foo[0][1] ^= foo[1][0];
+
+    // swap(foo[0][1], foo[1][0]) would fail
+    // this could use split_at_mut and mem::swap, but that is not much simpler.
+}
+
+fn distinct_slice() {
+    let foo = &mut [vec![1, 2], vec![3, 4]];
+    let bar = &mut [vec![1, 2], vec![3, 4]];
+    std::mem::swap(&mut foo[0][1], &mut bar[1][0]);
+}
+
 #[rustfmt::skip]
 fn main() {
-    field();
-    array();
-    slice();
-    unswappable_slice();
-    vec();
 
     let mut a = 42;
     let mut b = 1337;
index 5763d9e82d486779f12c1d4b9ba11f684229b33c..8518659ccf316dbbf41ce2e9941b3874c5878092 100644 (file)
@@ -6,6 +6,7 @@
     clippy::no_effect,
     clippy::redundant_clone,
     redundant_semicolons,
+    dead_code,
     unused_assignments
 )]
 
@@ -55,6 +56,7 @@ fn unswappable_slice() {
     foo[1][0] = temp;
 
     // swap(foo[0][1], foo[1][0]) would fail
+    // this could use split_at_mut and mem::swap, but that is not much simpler.
 }
 
 fn vec() {
@@ -66,13 +68,62 @@ fn vec() {
     foo.swap(0, 1);
 }
 
+fn xor_swap_locals() {
+    // This is an xor-based swap of local variables.
+    let mut a = 0;
+    let mut b = 1;
+    a ^= b;
+    b ^= a;
+    a ^= b;
+}
+
+fn xor_field_swap() {
+    // This is an xor-based swap of fields in a struct.
+    let mut bar = Bar { a: 0, b: 1 };
+    bar.a ^= bar.b;
+    bar.b ^= bar.a;
+    bar.a ^= bar.b;
+}
+
+fn xor_slice_swap() {
+    // This is an xor-based swap of a slice
+    let foo = &mut [1, 2];
+    foo[0] ^= foo[1];
+    foo[1] ^= foo[0];
+    foo[0] ^= foo[1];
+}
+
+fn xor_no_swap() {
+    // This is a sequence of xor-assignment statements that doesn't result in a swap.
+    let mut a = 0;
+    let mut b = 1;
+    let mut c = 2;
+    a ^= b;
+    b ^= c;
+    a ^= c;
+    c ^= a;
+}
+
+fn xor_unswappable_slice() {
+    let foo = &mut [vec![1, 2], vec![3, 4]];
+    foo[0][1] ^= foo[1][0];
+    foo[1][0] ^= foo[0][0];
+    foo[0][1] ^= foo[1][0];
+
+    // swap(foo[0][1], foo[1][0]) would fail
+    // this could use split_at_mut and mem::swap, but that is not much simpler.
+}
+
+fn distinct_slice() {
+    let foo = &mut [vec![1, 2], vec![3, 4]];
+    let bar = &mut [vec![1, 2], vec![3, 4]];
+    let temp = foo[0][1];
+    foo[0][1] = bar[1][0];
+    bar[1][0] = temp;
+}
+
 #[rustfmt::skip]
 fn main() {
-    field();
-    array();
-    slice();
-    unswappable_slice();
-    vec();
 
     let mut a = 42;
     let mut b = 1337;
index f49bcfedf3a1970b59751afe03ef8bf400d5cc23..614d16ced40f1b5fd02cf899f86f5a0f38a9b6a5 100644 (file)
@@ -1,15 +1,24 @@
+error: this looks like you are swapping `bar.a` and `bar.b` manually
+  --> $DIR/swap.rs:24:5
+   |
+LL | /     let temp = bar.a;
+LL | |     bar.a = bar.b;
+LL | |     bar.b = temp;
+   | |________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
+   |
+   = note: `-D clippy::manual-swap` implied by `-D warnings`
+   = note: or maybe you should use `std::mem::replace`?
+
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:35:5
+  --> $DIR/swap.rs:36:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
 LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
-   |
-   = note: `-D clippy::manual-swap` implied by `-D warnings`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:44:5
+  --> $DIR/swap.rs:45:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -17,7 +26,7 @@ LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:62:5
+  --> $DIR/swap.rs:64:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -25,7 +34,41 @@ LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping `a` and `b` manually
-  --> $DIR/swap.rs:83:7
+  --> $DIR/swap.rs:75:5
+   |
+LL | /     a ^= b;
+LL | |     b ^= a;
+LL | |     a ^= b;
+   | |___________^ help: try: `std::mem::swap(&mut a, &mut b)`
+
+error: this looks like you are swapping `bar.a` and `bar.b` manually
+  --> $DIR/swap.rs:83:5
+   |
+LL | /     bar.a ^= bar.b;
+LL | |     bar.b ^= bar.a;
+LL | |     bar.a ^= bar.b;
+   | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
+
+error: this looks like you are swapping elements of `foo` manually
+  --> $DIR/swap.rs:91:5
+   |
+LL | /     foo[0] ^= foo[1];
+LL | |     foo[1] ^= foo[0];
+LL | |     foo[0] ^= foo[1];
+   | |_____________________^ help: try: `foo.swap(0, 1)`
+
+error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
+  --> $DIR/swap.rs:120:5
+   |
+LL | /     let temp = foo[0][1];
+LL | |     foo[0][1] = bar[1][0];
+LL | |     bar[1][0] = temp;
+   | |____________________^ help: try: `std::mem::swap(&mut foo[0][1], &mut bar[1][0])`
+   |
+   = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are swapping `a` and `b` manually
+  --> $DIR/swap.rs:134:7
    |
 LL |       ; let t = a;
    |  _______^
@@ -36,7 +79,7 @@ LL | |     b = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `c.0` and `a` manually
-  --> $DIR/swap.rs:92:7
+  --> $DIR/swap.rs:143:7
    |
 LL |       ; let t = c.0;
    |  _______^
@@ -47,7 +90,7 @@ LL | |     a = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `a` and `b`
-  --> $DIR/swap.rs:80:5
+  --> $DIR/swap.rs:131:5
    |
 LL | /     a = b;
 LL | |     b = a;
@@ -57,7 +100,7 @@ LL | |     b = a;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are trying to swap `c.0` and `a`
-  --> $DIR/swap.rs:89:5
+  --> $DIR/swap.rs:140:5
    |
 LL | /     c.0 = a;
 LL | |     a = c.0;
@@ -65,5 +108,5 @@ LL | |     a = c.0;
    |
    = note: or maybe you should use `std::mem::replace`?
 
-error: aborting due to 7 previous errors
+error: aborting due to 12 previous errors
 
index e7e0a31febc45919ca44408c7772a83cc162126c..1a0123803a3ee9f482baf3d7141630a143d766fc 100644 (file)
@@ -58,6 +58,8 @@ fn good2(&mut self) {}
     fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
 
     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
+
+    fn bad_issue7518(self, other: &Self) {}
 }
 
 impl AsRef<u32> for Foo {
index 2b0005bbff1db6911305327e40e40799a604ede9..9c4c49ceac476f5f31ab13e24bef29d696ba3dc8 100644 (file)
@@ -65,40 +65,46 @@ LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:72:16
+  --> $DIR/trivially_copy_pass_by_ref.rs:62:35
+   |
+LL |     fn bad_issue7518(self, other: &Self) {}
+   |                                   ^^^^^ help: consider passing by value instead: `Self`
+
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:16
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                ^^^^ help: consider passing by value instead: `u32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:72:25
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:25
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                         ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:72:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:74:34
    |
 LL |     fn bad2(x: &u32, y: &Foo, z: &Baz) {}
    |                                  ^^^^ help: consider passing by value instead: `Baz`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:76:34
+  --> $DIR/trivially_copy_pass_by_ref.rs:78:34
    |
 LL |     fn trait_method(&self, _foo: &Foo);
    |                                  ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:108:21
+  --> $DIR/trivially_copy_pass_by_ref.rs:110:21
    |
 LL |     fn foo_never(x: &i32) {
    |                     ^^^^ help: consider passing by value instead: `i32`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:113:15
+  --> $DIR/trivially_copy_pass_by_ref.rs:115:15
    |
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
-error: aborting due to 16 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed b/src/tools/clippy/tests/ui/unwrap_or_else_default.fixed
new file mode 100644 (file)
index 0000000..7ac3f42
--- /dev/null
@@ -0,0 +1,71 @@
+// run-rustfix
+
+#![warn(clippy::unwrap_or_else_default)]
+#![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
+
+/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
+fn unwrap_or_else_default() {
+    struct Foo;
+
+    impl Foo {
+        fn new() -> Foo {
+            Foo
+        }
+
+        // fake default, we should not trigger on this
+        fn default() -> Foo {
+            Foo
+        }
+    }
+
+    struct HasDefaultAndDuplicate;
+
+    impl HasDefaultAndDuplicate {
+        fn default() -> Self {
+            HasDefaultAndDuplicate
+        }
+    }
+
+    impl Default for HasDefaultAndDuplicate {
+        fn default() -> Self {
+            HasDefaultAndDuplicate
+        }
+    }
+
+    enum Enum {
+        A(),
+    }
+
+    fn make<T, V>(_: V) -> T {
+        unimplemented!();
+    }
+
+    let with_enum = Some(Enum::A());
+    with_enum.unwrap_or_else(Enum::A);
+
+    let with_new = Some(vec![1]);
+    with_new.unwrap_or_else(Vec::new);
+
+    let with_err: Result<_, ()> = Ok(vec![1]);
+    with_err.unwrap_or_else(make);
+
+    // should not be changed
+    let with_fake_default = None::<Foo>;
+    with_fake_default.unwrap_or_else(Foo::default);
+
+    // should not be changed
+    let with_fake_default2 = None::<HasDefaultAndDuplicate>;
+    with_fake_default2.unwrap_or_else(<HasDefaultAndDuplicate>::default);
+
+    let with_real_default = None::<HasDefaultAndDuplicate>;
+    with_real_default.unwrap_or_default();
+
+    let with_default_trait = Some(1);
+    with_default_trait.unwrap_or_default();
+
+    let with_default_type = Some(1);
+    with_default_type.unwrap_or_default();
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.rs b/src/tools/clippy/tests/ui/unwrap_or_else_default.rs
new file mode 100644 (file)
index 0000000..82b727a
--- /dev/null
@@ -0,0 +1,71 @@
+// run-rustfix
+
+#![warn(clippy::unwrap_or_else_default)]
+#![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
+
+/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
+fn unwrap_or_else_default() {
+    struct Foo;
+
+    impl Foo {
+        fn new() -> Foo {
+            Foo
+        }
+
+        // fake default, we should not trigger on this
+        fn default() -> Foo {
+            Foo
+        }
+    }
+
+    struct HasDefaultAndDuplicate;
+
+    impl HasDefaultAndDuplicate {
+        fn default() -> Self {
+            HasDefaultAndDuplicate
+        }
+    }
+
+    impl Default for HasDefaultAndDuplicate {
+        fn default() -> Self {
+            HasDefaultAndDuplicate
+        }
+    }
+
+    enum Enum {
+        A(),
+    }
+
+    fn make<T, V>(_: V) -> T {
+        unimplemented!();
+    }
+
+    let with_enum = Some(Enum::A());
+    with_enum.unwrap_or_else(Enum::A);
+
+    let with_new = Some(vec![1]);
+    with_new.unwrap_or_else(Vec::new);
+
+    let with_err: Result<_, ()> = Ok(vec![1]);
+    with_err.unwrap_or_else(make);
+
+    // should not be changed
+    let with_fake_default = None::<Foo>;
+    with_fake_default.unwrap_or_else(Foo::default);
+
+    // should not be changed
+    let with_fake_default2 = None::<HasDefaultAndDuplicate>;
+    with_fake_default2.unwrap_or_else(<HasDefaultAndDuplicate>::default);
+
+    let with_real_default = None::<HasDefaultAndDuplicate>;
+    with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
+
+    let with_default_trait = Some(1);
+    with_default_trait.unwrap_or_else(Default::default);
+
+    let with_default_type = Some(1);
+    with_default_type.unwrap_or_else(u64::default);
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/unwrap_or_else_default.stderr b/src/tools/clippy/tests/ui/unwrap_or_else_default.stderr
new file mode 100644 (file)
index 0000000..feb215b
--- /dev/null
@@ -0,0 +1,22 @@
+error: use of `.unwrap_or_else(..)` to construct default value
+  --> $DIR/unwrap_or_else_default.rs:62:5
+   |
+LL |     with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_real_default.unwrap_or_default()`
+   |
+   = note: `-D clippy::unwrap-or-else-default` implied by `-D warnings`
+
+error: use of `.unwrap_or_else(..)` to construct default value
+  --> $DIR/unwrap_or_else_default.rs:65:5
+   |
+LL |     with_default_trait.unwrap_or_else(Default::default);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_trait.unwrap_or_default()`
+
+error: use of `.unwrap_or_else(..)` to construct default value
+  --> $DIR/unwrap_or_else_default.rs:68:5
+   |
+LL |     with_default_type.unwrap_or_else(u64::default);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()`
+
+error: aborting due to 3 previous errors
+
index 52e80ceee83cf31439c07cfff967fc46a03e09fd..cdcdd808c94445f2d33b2771ded4f95db9091644 100644 (file)
@@ -334,6 +334,38 @@ fn issue7249() {
     x();
 }
 
+fn issue7510() {
+    let mut it = 0..10;
+    let it = &mut it;
+    // Needs to reborrow `it` as the binding isn't mutable
+    for x in &mut *it {
+        if x % 2 == 0 {
+            break;
+        }
+    }
+    println!("{}", it.next().unwrap());
+
+    struct S<T>(T);
+    let mut it = 0..10;
+    let it = S(&mut it);
+    // Needs to reborrow `it.0` as the binding isn't mutable
+    for x in &mut *it.0 {
+        if x % 2 == 0 {
+            break;
+        }
+    }
+    println!("{}", it.0.next().unwrap());
+}
+
+fn exact_match_with_single_field() {
+    struct S<T>(T);
+    let mut s = S(0..10);
+    // Don't lint. `s.0` is used inside the loop.
+    while let Some(_) = s.0.next() {
+        let _ = &mut s.0;
+    }
+}
+
 fn main() {
     let mut it = 0..20;
     for _ in it {
index 5078a3c9028c4762f9d7ea09e3b1baf5c837c7c5..72f34257d1f46a631cf7596876dded1da71beedd 100644 (file)
@@ -334,6 +334,38 @@ fn issue7249() {
     x();
 }
 
+fn issue7510() {
+    let mut it = 0..10;
+    let it = &mut it;
+    // Needs to reborrow `it` as the binding isn't mutable
+    while let Some(x) = it.next() {
+        if x % 2 == 0 {
+            break;
+        }
+    }
+    println!("{}", it.next().unwrap());
+
+    struct S<T>(T);
+    let mut it = 0..10;
+    let it = S(&mut it);
+    // Needs to reborrow `it.0` as the binding isn't mutable
+    while let Some(x) = it.0.next() {
+        if x % 2 == 0 {
+            break;
+        }
+    }
+    println!("{}", it.0.next().unwrap());
+}
+
+fn exact_match_with_single_field() {
+    struct S<T>(T);
+    let mut s = S(0..10);
+    // Don't lint. `s.0` is used inside the loop.
+    while let Some(_) = s.0.next() {
+        let _ = &mut s.0;
+    }
+}
+
 fn main() {
     let mut it = 0..20;
     while let Some(..) = it.next() {
index cb0afeae15ee0ead89f0bbe769e7af04660ccd72..ff9b08996da5316dc807b48e9d8175a1370aa05d 100644 (file)
@@ -111,10 +111,22 @@ LL |         while let Some(x) = it.next() {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut it`
 
 error: this loop could be written as a `for` loop
-  --> $DIR/while_let_on_iterator.rs:339:5
+  --> $DIR/while_let_on_iterator.rs:341:5
+   |
+LL |     while let Some(x) = it.next() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it`
+
+error: this loop could be written as a `for` loop
+  --> $DIR/while_let_on_iterator.rs:352:5
+   |
+LL |     while let Some(x) = it.0.next() {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it.0`
+
+error: this loop could be written as a `for` loop
+  --> $DIR/while_let_on_iterator.rs:371:5
    |
 LL |     while let Some(..) = it.next() {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
 
-error: aborting due to 19 previous errors
+error: aborting due to 21 previous errors
 
index ea105f9396a9dab68e71efb06016b7c76c83ba7c..5664a2b0b31403024ce5ab927760d630d5ddc9a4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ea105f9396a9dab68e71efb06016b7c76c83ba7c
+Subproject commit 5664a2b0b31403024ce5ab927760d630d5ddc9a4
index 86b16f8b0e60d8bba1d879c66fe6b37db9ed88c6..bb9cd00f3f5829196df0a2a93d12274d82702f8a 100644 (file)
@@ -20,15 +20,17 @@ function getNextStep(content, pos, stop) {
 // will blow up. Template strings are not tested and might also be
 // broken.
 function extractFunction(content, functionName) {
-    var indent = 0;
+    var level = 0;
     var splitter = "function " + functionName + "(";
+    var stop;
+    var pos, start;
 
     while (true) {
-        var start = content.indexOf(splitter);
+        start = content.indexOf(splitter);
         if (start === -1) {
             break;
         }
-        var pos = start;
+        pos = start;
         while (pos < content.length && content[pos] !== ')') {
             pos += 1;
         }
@@ -44,30 +46,33 @@ function extractFunction(content, functionName) {
         }
         while (pos < content.length) {
             // Eat single-line comments
-            if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') {
+            if (content[pos] === '/' && pos > 0 && content[pos - 1] === '/') {
                 do {
                     pos += 1;
                 } while (pos < content.length && content[pos] !== '\n');
 
+            // Eat multiline comment.
+            } else if (content[pos] === '*' && pos > 0 && content[pos - 1] === '/') {
+                do {
+                    pos += 1;
+                } while (pos < content.length && content[pos] !== '/' && content[pos - 1] !== '*');
+
             // Eat quoted strings
             } else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
-                var stop = content[pos];
-                var is_escaped = false;
+                stop = content[pos];
                 do {
                     if (content[pos] === '\\') {
-                        pos += 2;
-                    } else {
                         pos += 1;
                     }
-                } while (pos < content.length &&
-                         (content[pos] !== stop || content[pos - 1] === '\\'));
+                    pos += 1;
+                } while (pos < content.length && content[pos] !== stop);
 
-            // Otherwise, check for indent
+            // Otherwise, check for block level.
             } else if (content[pos] === '{') {
-                indent += 1;
+                level += 1;
             } else if (content[pos] === '}') {
-                indent -= 1;
-                if (indent === 0) {
+                level -= 1;
+                if (level === 0) {
                     return content.slice(start, pos + 1);
                 }
             }