]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #88648 - kpreid:option, r=Mark-Simulacrum
authorJack Huey <31162821+jackh726@users.noreply.github.com>
Wed, 8 Sep 2021 16:24:18 +0000 (12:24 -0400)
committerGitHub <noreply@github.com>
Wed, 8 Sep 2021 16:24:18 +0000 (12:24 -0400)
Correct “copies” to “moves” in `<Option<T> as From<T>>::from` doc, and other copyediting

The `impl<T> From<T> for Option<T>` has no `Copy` or `Clone` bound, so its operation is guaranteed to be a move. The call site might copy, but the function itself cannot.

Since that would have been a rather small PR, I also reviewed the other documentation in the file and made other improvements (in separate commits): adding periods and commas, linking `Deref::Target`, and clarifying what "a container" is in `FromIterator`.

267 files changed:
Cargo.lock
Cargo.toml
compiler/rustc_ast/src/token.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_codegen_cranelift/src/archive.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/common.rs
compiler/rustc_codegen_llvm/src/consts.rs
compiler/rustc_codegen_llvm/src/context.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/mono_item.rs
compiler/rustc_codegen_llvm/src/type_of.rs
compiler/rustc_codegen_llvm/src/va_arg.rs
compiler/rustc_codegen_ssa/src/back/archive.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/base.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/operand.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_codegen_ssa/src/mir/rvalue.rs
compiler/rustc_codegen_ssa/src/mono_item.rs
compiler/rustc_codegen_ssa/src/traits/backend.rs
compiler/rustc_data_structures/src/thin_vec.rs
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/diagnostic_builder.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_incremental/src/persist/file_format.rs
compiler/rustc_incremental/src/persist/load.rs
compiler/rustc_incremental/src/persist/save.rs
compiler/rustc_infer/src/infer/fudge.rs
compiler/rustc_infer/src/infer/type_variable.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/diagnostics.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_mir/src/const_eval/eval_queries.rs
compiler/rustc_mir/src/interpret/cast.rs
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs
compiler/rustc_mir/src/interpret/operand.rs
compiler/rustc_mir/src/interpret/operator.rs
compiler/rustc_mir/src/interpret/place.rs
compiler/rustc_mir/src/interpret/step.rs
compiler/rustc_mir/src/interpret/terminator.rs
compiler/rustc_mir/src/interpret/validity.rs
compiler/rustc_mir/src/transform/const_prop.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_parse/src/parser/attr.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_passes/src/hir_stats.rs
compiler/rustc_passes/src/layout_test.rs
compiler/rustc_passes/src/lib_features.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/keys.rs
compiler/rustc_query_impl/src/on_disk_cache.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_session/src/session.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/mod.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_type_ir/src/lib.rs
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/item_bounds.rs
compiler/rustc_typeck/src/collect/type_of.rs
library/alloc/benches/btree/map.rs
library/alloc/src/collections/btree/dedup_sorted_iter.rs [new file with mode: 0644]
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/mod.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/raw_vec.rs
library/core/src/array/mod.rs
library/core/src/bool.rs
library/core/src/char/methods.rs
library/core/src/cmp.rs
library/core/src/hash/mod.rs
library/core/src/marker.rs
library/core/src/num/int_log10.rs
library/core/src/num/int_macros.rs
library/core/src/num/uint_macros.rs
library/core/src/ops/bit.rs
library/core/tests/num/int_log.rs
library/std/src/keyword_docs.rs
library/std/src/os/windows/fs.rs
library/std/src/primitive_docs.rs
src/bootstrap/bootstrap.py
src/bootstrap/bootstrap_test.py
src/bootstrap/builder.rs
src/bootstrap/check.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/run.rs
src/bootstrap/sanity.rs
src/bootstrap/tool.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/doctest.rs
src/librustdoc/html/format.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/span_map.rs
src/librustdoc/json/conversions.rs
src/librustdoc/json/mod.rs
src/librustdoc/lib.rs
src/llvm-project
src/rustdoc-json-types/lib.rs
src/stage0.json [new file with mode: 0644]
src/stage0.txt [deleted file]
src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
src/test/run-make/native-link-modifier-whole-archive/Makefile [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs [new file with mode: 0644]
src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs [new file with mode: 0644]
src/test/rustdoc-json/structs/with_primitives.rs
src/test/rustdoc-ui/bounded-hr-lifetime.rs [new file with mode: 0644]
src/test/rustdoc-ui/bounded-hr-lifetime.stderr [new file with mode: 0644]
src/test/rustdoc/type-layout.rs
src/test/ui/associated-types/issue-36499.stderr
src/test/ui/closures/2229_closure_analysis/issue-88476.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/issue-88476.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs [new file with mode: 0644]
src/test/ui/coherence/coherence_inherent.stderr
src/test/ui/coherence/coherence_inherent_cc.stderr
src/test/ui/const-generics/issues/issue-82956.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-82956.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-84659.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-84659.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86530.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86530.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86535-2.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86535.rs [new file with mode: 0644]
src/test/ui/const-generics/sneaky-array-repeat-expr.rs [new file with mode: 0644]
src/test/ui/const-generics/sneaky-array-repeat-expr.stderr [new file with mode: 0644]
src/test/ui/derives/derive-assoc-type-not-impl.stderr
src/test/ui/editions/dyn-trait-sugg-2021.rs [new file with mode: 0644]
src/test/ui/editions/dyn-trait-sugg-2021.stderr [new file with mode: 0644]
src/test/ui/error-codes/e0119/complex-impl.stderr
src/test/ui/generics/wrong-number-of-args.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr [new file with mode: 0644]
src/test/ui/hygiene/no_implicit_prelude.stderr
src/test/ui/hygiene/trait_items.stderr
src/test/ui/issues/issue-10465.stderr
src/test/ui/issues/issue-4736.stderr
src/test/ui/issues/issue-80607.stderr
src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr [new file with mode: 0644]
src/test/ui/lifetimes/lifetime-errors/issue_74400.rs [new file with mode: 0644]
src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr [new file with mode: 0644]
src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
src/test/ui/lint/outer-forbid.rs
src/test/ui/lint/outer-forbid.stderr
src/test/ui/maybe-bounds-where.rs
src/test/ui/maybe-bounds-where.stderr
src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
src/test/ui/moves/move-guard-same-consts.rs
src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs [new file with mode: 0644]
src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr [new file with mode: 0644]
src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs [new file with mode: 0644]
src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr [new file with mode: 0644]
src/test/ui/numeric/numeric-fields.stderr
src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
src/test/ui/parser/attr.stderr
src/test/ui/parser/doc-comment-in-if-statement.stderr
src/test/ui/parser/expr-as-stmt.fixed
src/test/ui/parser/expr-as-stmt.rs
src/test/ui/parser/expr-as-stmt.stderr
src/test/ui/parser/inner-attr-after-doc-comment.stderr
src/test/ui/parser/inner-attr.stderr
src/test/ui/parser/issue-30318.fixed [new file with mode: 0644]
src/test/ui/parser/issue-30318.rs
src/test/ui/parser/issue-30318.stderr
src/test/ui/parser/issue-45296.rs
src/test/ui/parser/issue-45296.stderr
src/test/ui/parser/issue-88276-unary-plus.fixed [new file with mode: 0644]
src/test/ui/parser/issue-88276-unary-plus.rs [new file with mode: 0644]
src/test/ui/parser/issue-88276-unary-plus.stderr [new file with mode: 0644]
src/test/ui/parser/stmt_expr_attrs_placement.stderr
src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed [new file with mode: 0644]
src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs
src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr
src/test/ui/rust-2018/trait-import-suggestions.stderr
src/test/ui/rust-2021/future-prelude-collision-shadow.stderr
src/test/ui/suggestions/derive-trait-for-method-call.rs [new file with mode: 0644]
src/test/ui/suggestions/derive-trait-for-method-call.stderr [new file with mode: 0644]
src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs [new file with mode: 0644]
src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-non-object-safe.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-non-object-safe.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-vacant.rs
src/test/ui/traits/vtable/vtable-vacant.stderr
src/test/ui/underscore-imports/shadow.stderr
src/test/ui/union/union-derive-clone.mirunsafeck.stderr
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
src/test/ui/unique-pinned-nocopy.stderr
src/tools/bump-stage0/Cargo.toml [new file with mode: 0644]
src/tools/bump-stage0/src/main.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
src/tools/clippy/clippy_lints/src/escape.rs
src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
src/tools/clippy/clippy_lints/src/large_const_arrays.rs
src/tools/clippy/clippy_lints/src/large_enum_variant.rs
src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
src/tools/clippy/clippy_lints/src/types/vec_box.rs
src/tools/clippy/clippy_lints/src/vec.rs
src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
src/tools/clippy/tests/ui/match_same_arms.stderr
src/tools/clippy/tests/ui/modulo_one.stderr
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
src/tools/miri
src/tools/rls
src/tools/rust-analyzer
src/tools/rustfmt/src/syntux/session.rs

index 5b8d28752b4dada9e53b75e8910873dae58a2d1a..5000b1e051fa5c39841d7786910196ffa382d635 100644 (file)
@@ -220,6 +220,18 @@ dependencies = [
 name = "build_helper"
 version = "0.1.0"
 
+[[package]]
+name = "bump-stage0"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "curl",
+ "indexmap",
+ "serde",
+ "serde_json",
+ "toml",
+]
+
 [[package]]
 name = "byte-tools"
 version = "0.3.1"
@@ -546,7 +558,7 @@ version = "0.1.56"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_lints",
- "compiletest_rs",
+ "compiletest_rs 0.6.0",
  "derive-new",
  "filetime",
  "quote",
@@ -699,6 +711,29 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "compiletest_rs"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
+dependencies = [
+ "diff",
+ "filetime",
+ "getopts",
+ "lazy_static",
+ "libc",
+ "log",
+ "miow",
+ "regex",
+ "rustfix 0.5.1",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tempfile",
+ "tester",
+ "winapi",
+]
+
 [[package]]
 name = "core"
 version = "0.0.0"
@@ -1663,6 +1698,7 @@ checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
 dependencies = [
  "autocfg",
  "hashbrown",
+ "serde",
 ]
 
 [[package]]
@@ -2237,7 +2273,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "colored",
- "compiletest_rs",
+ "compiletest_rs 0.7.0",
  "env_logger 0.8.1",
  "getrandom 0.2.0",
  "hex 0.4.2",
index dedfe45aca49bd807af07a9b573d245375e98bbd..3822da2ccd5e4694756480493eb2ff55afcce26e 100644 (file)
@@ -35,6 +35,7 @@ members = [
   "src/tools/expand-yaml-anchors",
   "src/tools/jsondocck",
   "src/tools/html-checker",
+  "src/tools/bump-stage0",
 ]
 
 exclude = [
index 710a592e258b43d1ec067d6562e9c705ebee05b8..3a65ffe41ae87cbf4c17622dc4b1556c2b231ccf 100644 (file)
@@ -586,6 +586,13 @@ pub fn is_bool_lit(&self) -> bool {
         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
     }
 
+    pub fn is_numeric_lit(&self) -> bool {
+        matches!(
+            self.kind,
+            Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
+        )
+    }
+
     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
     pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
         match self.ident() {
index 80633e141fc6de85e78bcaa9b8d67c434f8add9f..16cd7a0bcdd394af214d0a0235fab976fb3c3636 100644 (file)
@@ -1186,9 +1186,7 @@ fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hi
                 }
             }
             None => self
-                .loop_scopes
-                .last()
-                .cloned()
+                .loop_scope
                 .map(|id| Ok(self.lower_node_id(id)))
                 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
         };
@@ -1208,18 +1206,9 @@ fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hi
     }
 
     fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
-        let len = self.catch_scopes.len();
-        self.catch_scopes.push(catch_id);
-
+        let old_scope = self.catch_scope.replace(catch_id);
         let result = f(self);
-        assert_eq!(
-            len + 1,
-            self.catch_scopes.len(),
-            "catch scopes should be added and removed in stack order"
-        );
-
-        self.catch_scopes.pop().unwrap();
-
+        self.catch_scope = old_scope;
         result
     }
 
@@ -1228,17 +1217,9 @@ fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
-        let len = self.loop_scopes.len();
-        self.loop_scopes.push(loop_id);
-
+        let old_scope = self.loop_scope.replace(loop_id);
         let result = f(self);
-        assert_eq!(
-            len + 1,
-            self.loop_scopes.len(),
-            "loop scopes should be added and removed in stack order"
-        );
-
-        self.loop_scopes.pop().unwrap();
+        self.loop_scope = old_scope;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
@@ -1565,8 +1546,7 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                 unstable_span,
             );
             let thin_attrs = ThinVec::from(attrs);
-            let catch_scope = self.catch_scopes.last().copied();
-            let ret_expr = if let Some(catch_node) = catch_scope {
+            let ret_expr = if let Some(catch_node) = self.catch_scope {
                 let target_id = Ok(self.lower_node_id(catch_node));
                 self.arena.alloc(self.expr(
                     try_span,
index e0d4095d76907362e7b3ecb02dabc85f81b2438b..b7497c713f3df32d76a8f04ce0e6e98b0a4720c4 100644 (file)
@@ -2,7 +2,6 @@
 use super::{ImplTraitContext, ImplTraitPosition};
 use crate::Arena;
 
-use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
@@ -1351,8 +1350,11 @@ pub(super) fn lower_generics_mut(
         generics: &Generics,
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> GenericsCtor<'hir> {
-        // Collect `?Trait` bounds in where clause and move them to parameter definitions.
-        let mut add_bounds: NodeMap<Vec<_>> = Default::default();
+        // Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
+        // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
+        // these into hir when we lower thee where clauses), but this makes it quite difficult to
+        // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
+        // where clauses for `?Sized`.
         for pred in &generics.where_clause.predicates {
             if let WherePredicate::BoundPredicate(ref bound_pred) = *pred {
                 'next_bound: for bound in &bound_pred.bounds {
@@ -1368,7 +1370,6 @@ pub(super) fn lower_generics_mut(
                             {
                                 for param in &generics.params {
                                     if def_id == self.resolver.local_def_id(param.id).to_def_id() {
-                                        add_bounds.entry(param.id).or_default().push(bound.clone());
                                         continue 'next_bound;
                                     }
                                 }
@@ -1386,7 +1387,7 @@ pub(super) fn lower_generics_mut(
         }
 
         GenericsCtor {
-            params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
+            params: self.lower_generic_params_mut(&generics.params, itctx).collect(),
             where_clause: self.lower_where_clause(&generics.where_clause),
             span: self.lower_span(generics.span),
         }
@@ -1419,32 +1420,17 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                 ref bounded_ty,
                 ref bounds,
                 span,
-            }) => {
-                self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
-                    hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                        bound_generic_params: this.lower_generic_params(
-                            bound_generic_params,
-                            &NodeMap::default(),
-                            ImplTraitContext::disallowed(),
-                        ),
-                        bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
-                        bounds: this.arena.alloc_from_iter(bounds.iter().map(
-                            |bound| match bound {
-                                // We used to ignore `?Trait` bounds, as they were copied into type
-                                // parameters already, but we need to keep them around only for
-                                // diagnostics when we suggest removal of `?Sized` bounds. See
-                                // `suggest_constraining_type_param`. This will need to change if
-                                // we ever allow something *other* than `?Sized`.
-                                GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
-                                    hir::GenericBound::Unsized(this.lower_span(p.span))
-                                }
-                                _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
-                            },
-                        )),
-                        span: this.lower_span(span),
-                    })
+            }) => self.with_in_scope_lifetime_defs(&bound_generic_params, |this| {
+                hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                    bound_generic_params: this
+                        .lower_generic_params(bound_generic_params, ImplTraitContext::disallowed()),
+                    bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::disallowed()),
+                    bounds: this.arena.alloc_from_iter(bounds.iter().map(|bound| {
+                        this.lower_param_bound(bound, ImplTraitContext::disallowed())
+                    })),
+                    span: this.lower_span(span),
                 })
-            }
+            }),
             WherePredicate::RegionPredicate(WhereRegionPredicate {
                 ref lifetime,
                 ref bounds,
index 8fd8075725b48c292ddb1dbcbd5d69c7c3012357..fa14764c42a73f1707ac51729632769601f83de1 100644 (file)
@@ -64,7 +64,6 @@
 
 use smallvec::SmallVec;
 use std::collections::BTreeMap;
-use std::mem;
 use tracing::{debug, trace};
 
 macro_rules! arena_vec {
@@ -117,8 +116,8 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// outside of an `async fn`.
     current_item: Option<Span>,
 
-    catch_scopes: Vec<NodeId>,
-    loop_scopes: Vec<NodeId>,
+    catch_scope: Option<NodeId>,
+    loop_scope: Option<NodeId>,
     is_in_loop_condition: bool,
     is_in_trait_impl: bool,
     is_in_dyn_type: bool,
@@ -323,8 +322,8 @@ pub fn lower_crate<'a, 'hir>(
         bodies: BTreeMap::new(),
         modules: BTreeMap::new(),
         attrs: BTreeMap::default(),
-        catch_scopes: Vec::new(),
-        loop_scopes: Vec::new(),
+        catch_scope: None,
+        loop_scope: None,
         is_in_loop_condition: false,
         is_in_trait_impl: false,
         is_in_dyn_type: false,
@@ -911,11 +910,11 @@ fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
-        let catch_scopes = mem::take(&mut self.catch_scopes);
-        let loop_scopes = mem::take(&mut self.loop_scopes);
+        let catch_scope = self.catch_scope.take();
+        let loop_scope = self.loop_scope.take();
         let ret = f(self);
-        self.catch_scopes = catch_scopes;
-        self.loop_scopes = loop_scopes;
+        self.catch_scope = catch_scope;
+        self.loop_scope = loop_scope;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
@@ -1314,7 +1313,6 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                     hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
-                            &NodeMap::default(),
                             ImplTraitContext::disallowed(),
                         ),
                         unsafety: this.lower_unsafety(f.unsafety),
@@ -1497,20 +1495,50 @@ fn lower_opaque_impl_trait(
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
-        let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
+        let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
+            let hir_bounds = lower_bounds(lctx);
 
-        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
-            opaque_ty_node_id,
-            opaque_ty_def_id,
-            &hir_bounds,
-            capturable_lifetimes,
-        );
+            let collected_lifetimes = lifetimes_from_impl_trait_bounds(
+                opaque_ty_node_id,
+                &hir_bounds,
+                capturable_lifetimes,
+            );
 
-        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
+            let lifetime_defs =
+                lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(name, span)| {
+                    let def_node_id = lctx.resolver.next_node_id();
+                    let hir_id = lctx.lower_node_id(def_node_id);
+                    lctx.resolver.create_def(
+                        opaque_ty_def_id,
+                        def_node_id,
+                        DefPathData::LifetimeNs(name.ident().name),
+                        ExpnId::root(),
+                        span,
+                    );
 
-        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
+                    let (name, kind) = match name {
+                        hir::LifetimeName::Underscore => (
+                            hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
+                            hir::LifetimeParamKind::Elided,
+                        ),
+                        hir::LifetimeName::Param(param_name) => {
+                            (param_name, hir::LifetimeParamKind::Explicit)
+                        }
+                        _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"),
+                    };
+
+                    hir::GenericParam {
+                        hir_id,
+                        name,
+                        span,
+                        pure_wrt_drop: false,
+                        bounds: &[],
+                        kind: hir::GenericParamKind::Lifetime { kind },
+                    }
+                }));
+
+            debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
 
-        self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
                     params: lifetime_defs,
@@ -1525,9 +1553,18 @@ fn lower_opaque_impl_trait(
             trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
             lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
 
-            // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-            hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
-        })
+            collected_lifetimes
+        });
+
+        let lifetimes =
+            self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(name, span)| {
+                hir::GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span, name })
+            }));
+
+        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
+
+        // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
+        hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
     }
 
     /// Registers a new opaque type with the proper `NodeId`s and
@@ -1556,193 +1593,6 @@ fn generate_opaque_type(
         self.insert_item(opaque_ty_item);
     }
 
-    fn lifetimes_from_impl_trait_bounds(
-        &mut self,
-        opaque_ty_id: NodeId,
-        parent_def_id: LocalDefId,
-        bounds: hir::GenericBounds<'hir>,
-        lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
-    ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
-        debug!(
-            "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
-             parent_def_id={:?}, \
-             bounds={:#?})",
-            opaque_ty_id, parent_def_id, bounds,
-        );
-
-        // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
-        // appear in the bounds, excluding lifetimes that are created within the bounds.
-        // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
-        struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            context: &'r mut LoweringContext<'a, 'hir>,
-            parent: LocalDefId,
-            opaque_ty_id: NodeId,
-            collect_elided_lifetimes: bool,
-            currently_bound_lifetimes: Vec<hir::LifetimeName>,
-            already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
-            output_lifetimes: Vec<hir::GenericArg<'hir>>,
-            output_lifetime_params: Vec<hir::GenericParam<'hir>>,
-            lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
-        }
-
-        impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            type Map = intravisit::ErasedMap<'v>;
-
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-                intravisit::NestedVisitorMap::None
-            }
-
-            fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
-                // Don't collect elided lifetimes used inside of `Fn()` syntax.
-                if parameters.parenthesized {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-                    intravisit::walk_generic_args(self, span, parameters);
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    intravisit::walk_generic_args(self, span, parameters);
-                }
-            }
-
-            fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
-                // Don't collect elided lifetimes used inside of `fn()` syntax.
-                if let hir::TyKind::BareFn(_) = t.kind {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-
-                    // Record the "stack height" of `for<'a>` lifetime bindings
-                    // to be able to later fully undo their introduction.
-                    let old_len = self.currently_bound_lifetimes.len();
-                    intravisit::walk_ty(self, t);
-                    self.currently_bound_lifetimes.truncate(old_len);
-
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    intravisit::walk_ty(self, t)
-                }
-            }
-
-            fn visit_poly_trait_ref(
-                &mut self,
-                trait_ref: &'v hir::PolyTraitRef<'v>,
-                modifier: hir::TraitBoundModifier,
-            ) {
-                // Record the "stack height" of `for<'a>` lifetime bindings
-                // to be able to later fully undo their introduction.
-                let old_len = self.currently_bound_lifetimes.len();
-                intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
-                self.currently_bound_lifetimes.truncate(old_len);
-            }
-
-            fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
-                // Record the introduction of 'a in `for<'a> ...`.
-                if let hir::GenericParamKind::Lifetime { .. } = param.kind {
-                    // Introduce lifetimes one at a time so that we can handle
-                    // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
-                    let lt_name = hir::LifetimeName::Param(param.name);
-                    self.currently_bound_lifetimes.push(lt_name);
-                }
-
-                intravisit::walk_generic_param(self, param);
-            }
-
-            fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
-                let name = match lifetime.name {
-                    hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
-                        if self.collect_elided_lifetimes {
-                            // Use `'_` for both implicit and underscore lifetimes in
-                            // `type Foo<'_> = impl SomeTrait<'_>;`.
-                            hir::LifetimeName::Underscore
-                        } else {
-                            return;
-                        }
-                    }
-                    hir::LifetimeName::Param(_) => lifetime.name,
-
-                    // Refers to some other lifetime that is "in
-                    // scope" within the type.
-                    hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
-
-                    hir::LifetimeName::Error | hir::LifetimeName::Static => return,
-                };
-
-                if !self.currently_bound_lifetimes.contains(&name)
-                    && !self.already_defined_lifetimes.contains(&name)
-                    && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
-                {
-                    self.already_defined_lifetimes.insert(name);
-
-                    self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime {
-                        hir_id: self.context.next_id(),
-                        span: self.context.lower_span(lifetime.span),
-                        name,
-                    }));
-
-                    let def_node_id = self.context.resolver.next_node_id();
-                    let hir_id =
-                        self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id);
-                    self.context.resolver.create_def(
-                        self.parent,
-                        def_node_id,
-                        DefPathData::LifetimeNs(name.ident().name),
-                        ExpnId::root(),
-                        lifetime.span,
-                    );
-
-                    let (name, kind) = match name {
-                        hir::LifetimeName::Underscore => (
-                            hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
-                            hir::LifetimeParamKind::Elided,
-                        ),
-                        hir::LifetimeName::Param(param_name) => {
-                            (param_name, hir::LifetimeParamKind::Explicit)
-                        }
-                        _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"),
-                    };
-                    let name = match name {
-                        hir::ParamName::Plain(ident) => {
-                            hir::ParamName::Plain(self.context.lower_ident(ident))
-                        }
-                        name => name,
-                    };
-
-                    self.output_lifetime_params.push(hir::GenericParam {
-                        hir_id,
-                        name,
-                        span: self.context.lower_span(lifetime.span),
-                        pure_wrt_drop: false,
-                        bounds: &[],
-                        kind: hir::GenericParamKind::Lifetime { kind },
-                    });
-                }
-            }
-        }
-
-        let mut lifetime_collector = ImplTraitLifetimeCollector {
-            context: self,
-            parent: parent_def_id,
-            opaque_ty_id,
-            collect_elided_lifetimes: true,
-            currently_bound_lifetimes: Vec::new(),
-            already_defined_lifetimes: FxHashSet::default(),
-            output_lifetimes: Vec::new(),
-            output_lifetime_params: Vec::new(),
-            lifetimes_to_include,
-        };
-
-        for bound in bounds {
-            intravisit::walk_param_bound(&mut lifetime_collector, &bound);
-        }
-
-        let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } =
-            lifetime_collector;
-
-        (
-            self.arena.alloc_from_iter(output_lifetimes),
-            self.arena.alloc_from_iter(output_lifetime_params),
-        )
-    }
-
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         // Skip the `...` (`CVarArgs`) trailing arguments from the AST,
         // as they are not explicit in HIR/Ty function signatures.
@@ -2147,30 +1997,25 @@ fn new_named_lifetime(
     fn lower_generic_params_mut<'s>(
         &'s mut self,
         params: &'s [GenericParam],
-        add_bounds: &'s NodeMap<Vec<GenericBound>>,
         mut itctx: ImplTraitContext<'s, 'hir>,
     ) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
-        params
-            .iter()
-            .map(move |param| self.lower_generic_param(param, add_bounds, itctx.reborrow()))
+        params.iter().map(move |param| self.lower_generic_param(param, itctx.reborrow()))
     }
 
     fn lower_generic_params(
         &mut self,
         params: &[GenericParam],
-        add_bounds: &NodeMap<Vec<GenericBound>>,
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> &'hir [hir::GenericParam<'hir>] {
-        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, add_bounds, itctx))
+        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, itctx))
     }
 
     fn lower_generic_param(
         &mut self,
         param: &GenericParam,
-        add_bounds: &NodeMap<Vec<GenericBound>>,
         mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::GenericParam<'hir> {
-        let mut bounds: Vec<_> = self
+        let bounds: Vec<_> = self
             .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
                 this.lower_param_bounds_mut(&param.bounds, itctx.reborrow()).collect()
             });
@@ -2206,12 +2051,6 @@ fn lower_generic_param(
                 (param_name, kind)
             }
             GenericParamKind::Type { ref default, .. } => {
-                let add_bounds = add_bounds.get(&param.id).map_or(&[][..], |x| &x);
-                if !add_bounds.is_empty() {
-                    let params = self.lower_param_bounds_mut(add_bounds, itctx.reborrow());
-                    bounds.extend(params);
-                }
-
                 let kind = hir::GenericParamKind::Type {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(x, ImplTraitContext::Disallowed(ImplTraitPosition::Other))
@@ -2272,11 +2111,8 @@ fn lower_poly_trait_ref(
         p: &PolyTraitRef,
         mut itctx: ImplTraitContext<'_, 'hir>,
     ) -> hir::PolyTraitRef<'hir> {
-        let bound_generic_params = self.lower_generic_params(
-            &p.bound_generic_params,
-            &NodeMap::default(),
-            itctx.reborrow(),
-        );
+        let bound_generic_params =
+            self.lower_generic_params(&p.bound_generic_params, itctx.reborrow());
 
         let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
             // Any impl Trait types defined within this scope can capture
@@ -2723,3 +2559,132 @@ fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::Gener
         this.arena.alloc(ga)
     }
 }
+
+fn lifetimes_from_impl_trait_bounds(
+    opaque_ty_id: NodeId,
+    bounds: hir::GenericBounds<'_>,
+    lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
+) -> Vec<(hir::LifetimeName, Span)> {
+    debug!(
+        "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
+             bounds={:#?})",
+        opaque_ty_id, bounds,
+    );
+
+    // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
+    // appear in the bounds, excluding lifetimes that are created within the bounds.
+    // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
+    struct ImplTraitLifetimeCollector<'r> {
+        collect_elided_lifetimes: bool,
+        currently_bound_lifetimes: Vec<hir::LifetimeName>,
+        already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
+        lifetimes: Vec<(hir::LifetimeName, Span)>,
+        lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
+    }
+
+    impl<'r, 'v> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r> {
+        type Map = intravisit::ErasedMap<'v>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::None
+        }
+
+        fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
+            // Don't collect elided lifetimes used inside of `Fn()` syntax.
+            if parameters.parenthesized {
+                let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                self.collect_elided_lifetimes = false;
+                intravisit::walk_generic_args(self, span, parameters);
+                self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+            } else {
+                intravisit::walk_generic_args(self, span, parameters);
+            }
+        }
+
+        fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
+            // Don't collect elided lifetimes used inside of `fn()` syntax.
+            if let hir::TyKind::BareFn(_) = t.kind {
+                let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                self.collect_elided_lifetimes = false;
+
+                // Record the "stack height" of `for<'a>` lifetime bindings
+                // to be able to later fully undo their introduction.
+                let old_len = self.currently_bound_lifetimes.len();
+                intravisit::walk_ty(self, t);
+                self.currently_bound_lifetimes.truncate(old_len);
+
+                self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+            } else {
+                intravisit::walk_ty(self, t)
+            }
+        }
+
+        fn visit_poly_trait_ref(
+            &mut self,
+            trait_ref: &'v hir::PolyTraitRef<'v>,
+            modifier: hir::TraitBoundModifier,
+        ) {
+            // Record the "stack height" of `for<'a>` lifetime bindings
+            // to be able to later fully undo their introduction.
+            let old_len = self.currently_bound_lifetimes.len();
+            intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
+            self.currently_bound_lifetimes.truncate(old_len);
+        }
+
+        fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
+            // Record the introduction of 'a in `for<'a> ...`.
+            if let hir::GenericParamKind::Lifetime { .. } = param.kind {
+                // Introduce lifetimes one at a time so that we can handle
+                // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
+                let lt_name = hir::LifetimeName::Param(param.name);
+                self.currently_bound_lifetimes.push(lt_name);
+            }
+
+            intravisit::walk_generic_param(self, param);
+        }
+
+        fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
+            let name = match lifetime.name {
+                hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+                    if self.collect_elided_lifetimes {
+                        // Use `'_` for both implicit and underscore lifetimes in
+                        // `type Foo<'_> = impl SomeTrait<'_>;`.
+                        hir::LifetimeName::Underscore
+                    } else {
+                        return;
+                    }
+                }
+                hir::LifetimeName::Param(_) => lifetime.name,
+
+                // Refers to some other lifetime that is "in
+                // scope" within the type.
+                hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
+
+                hir::LifetimeName::Error | hir::LifetimeName::Static => return,
+            };
+
+            if !self.currently_bound_lifetimes.contains(&name)
+                && !self.already_defined_lifetimes.contains(&name)
+                && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
+            {
+                self.already_defined_lifetimes.insert(name);
+
+                self.lifetimes.push((name, lifetime.span));
+            }
+        }
+    }
+
+    let mut lifetime_collector = ImplTraitLifetimeCollector {
+        collect_elided_lifetimes: true,
+        currently_bound_lifetimes: Vec::new(),
+        already_defined_lifetimes: FxHashSet::default(),
+        lifetimes: Vec::new(),
+        lifetimes_to_include,
+    };
+
+    for bound in bounds {
+        intravisit::walk_param_bound(&mut lifetime_collector, &bound);
+    }
+
+    lifetime_collector.lifetimes
+}
index 22897c43e7ef917cdc456010c9129d35aca97c1e..0fa228fc944a160c226f21c2ebec660c1192ba7c 100644 (file)
@@ -4,8 +4,7 @@
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
-use rustc_codegen_ssa::METADATA_FILENAME;
+use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_session::Session;
 
 use object::{Object, ObjectSymbol, SymbolKind};
@@ -19,7 +18,6 @@ enum ArchiveEntry {
 pub(crate) struct ArArchiveBuilder<'a> {
     sess: &'a Session,
     dst: PathBuf,
-    lib_search_paths: Vec<PathBuf>,
     use_gnu_style_archive: bool,
     no_builtin_ranlib: bool,
 
@@ -31,8 +29,6 @@ pub(crate) struct ArArchiveBuilder<'a> {
 
 impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
-        use rustc_codegen_ssa::back::link::archive_search_paths;
-
         let (src_archives, entries) = if let Some(input) = input {
             let mut archive = ar::Archive::new(File::open(input).unwrap());
             let mut entries = Vec::new();
@@ -55,7 +51,6 @@ fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
         ArArchiveBuilder {
             sess,
             dst: output.to_path_buf(),
-            lib_search_paths: archive_search_paths(sess),
             use_gnu_style_archive: sess.target.archive_format == "gnu",
             // FIXME fix builtin ranlib on macOS
             no_builtin_ranlib: sess.target.is_like_osx,
@@ -85,42 +80,27 @@ fn add_file(&mut self, file: &Path) {
         ));
     }
 
-    fn add_native_library(&mut self, name: rustc_span::symbol::Symbol, verbatim: bool) {
-        let location = find_library(name, verbatim, &self.lib_search_paths, self.sess);
-        self.add_archive(location.clone(), |_| false).unwrap_or_else(|e| {
-            panic!("failed to add native library {}: {}", location.to_string_lossy(), e);
-        });
-    }
-
-    fn add_rlib(
-        &mut self,
-        rlib: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> std::io::Result<()> {
-        let obj_start = name.to_owned();
-
-        self.add_archive(rlib.to_owned(), move |fname: &str| {
-            // Ignore metadata files, no matter the name.
-            if fname == METADATA_FILENAME {
-                return true;
-            }
-
-            // Don't include Rust objects if LTO is enabled
-            if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") {
-                return true;
-            }
+    fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static,
+    {
+        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
+        let archive_index = self.src_archives.len();
 
-            // Otherwise if this is *not* a rust object and we're skipping
-            // objects then skip this file
-            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                return true;
+        let mut i = 0;
+        while let Some(entry) = archive.next_entry() {
+            let entry = entry?;
+            let file_name = String::from_utf8(entry.header().identifier().to_vec())
+                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
+            if !skip(&file_name) {
+                self.entries
+                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
             }
+            i += 1;
+        }
 
-            // ok, don't skip this
-            false
-        })
+        self.src_archives.push((archive_path.to_owned(), archive));
+        Ok(())
     }
 
     fn update_symbols(&mut self) {}
@@ -264,28 +244,3 @@ fn inject_dll_import_lib(
         bug!("injecting dll imports is not supported");
     }
 }
-
-impl<'a> ArArchiveBuilder<'a> {
-    fn add_archive<F>(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
-        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
-        let archive_index = self.src_archives.len();
-
-        let mut i = 0;
-        while let Some(entry) = archive.next_entry() {
-            let entry = entry?;
-            let file_name = String::from_utf8(entry.header().identifier().to_vec())
-                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
-            if !skip(&file_name) {
-                self.entries
-                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
-            }
-            i += 1;
-        }
-
-        self.src_archives.push((archive_path, archive));
-        Ok(())
-    }
-}
index 03f462a63b31bf211a33fcdee3323c4764054d3e..6f7ca51d038c0155233e9ad8dcea64cfa70a6b47 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_index::vec::IndexVec;
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers};
 use rustc_middle::ty::SymbolName;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
@@ -256,12 +257,12 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) inline_asm_index: u32,
 }
 
-impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
-        RevealAllLayoutCx(self.tcx).layout_of(ty)
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
     }
 }
 
@@ -364,19 +365,16 @@ pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
 
 pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
 
-impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
-        assert!(!ty.still_further_specializable());
-        self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| {
-            if let layout::LayoutError::SizeOverflow(_) = e {
-                self.0.sess.fatal(&e.to_string())
-            } else {
-                bug!("failed to get layout for `{}`: {}", ty, e)
-            }
-        })
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        if let layout::LayoutError::SizeOverflow(_) = err {
+            self.0.sess.span_fatal(span, &err.to_string())
+        } else {
+            span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+        }
     }
 }
 
index 6c7c8cbc311f9f3fabe798685ff895b9d614980b..2e5e8f683cdaaad47aa2e75c1ef4775345a9ba10 100644 (file)
@@ -79,12 +79,12 @@ mod prelude {
     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
     pub(crate) use rustc_middle::bug;
     pub(crate) use rustc_middle::mir::{self, *};
-    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
+    pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
     pub(crate) use rustc_middle::ty::{
         self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
         TypeFoldable, UintTy,
     };
-    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
+    pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};
 
     pub(crate) use rustc_data_structures::fx::FxHashMap;
 
index abf0ea8cc0a65b05c4329b1312e507a17eb2a698..cd55a61cbaf9d7b4c7675d73ff985a4478cf9fcf 100644 (file)
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::MemFlags;
 use rustc_middle::bug;
+use rustc_middle::ty::layout::LayoutOf;
 pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc_middle::ty::Ty;
 use rustc_target::abi::call::ArgAbi;
 pub use rustc_target::abi::call::*;
-use rustc_target::abi::{self, HasDataLayout, Int, LayoutOf};
+use rustc_target::abi::{self, HasDataLayout, Int};
 pub use rustc_target::spec::abi::Abi;
 
 use libc::c_uint;
index 6ac7093b7dee833870d4568529293b088950f62f..4e86946219fb151676c38889abe6a7b560ec0ad3 100644 (file)
@@ -9,18 +9,15 @@
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
-use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
-use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
+use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_session::Session;
-use rustc_span::symbol::Symbol;
 
 struct ArchiveConfig<'a> {
     pub sess: &'a Session,
     pub dst: PathBuf,
     pub src: Option<PathBuf>,
-    pub lib_search_paths: Vec<PathBuf>,
 }
 
 /// Helper for adding many files to an archive.
@@ -54,13 +51,7 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
 }
 
 fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> {
-    use rustc_codegen_ssa::back::link::archive_search_paths;
-    ArchiveConfig {
-        sess,
-        dst: output.to_path_buf(),
-        src: input.map(|p| p.to_path_buf()),
-        lib_search_paths: archive_search_paths(sess),
-    }
+    ArchiveConfig { sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()) }
 }
 
 /// Map machine type strings to values of LLVM's MachineTypes enum.
@@ -111,57 +102,23 @@ fn src_files(&mut self) -> Vec<String> {
             .collect()
     }
 
-    /// Adds all of the contents of a native library to this archive. This will
-    /// search in the relevant locations for a library named `name`.
-    fn add_native_library(&mut self, name: Symbol, verbatim: bool) {
-        let location =
-            find_library(name, verbatim, &self.config.lib_search_paths, self.config.sess);
-        self.add_archive(&location, |_| false).unwrap_or_else(|e| {
-            self.config.sess.fatal(&format!(
-                "failed to add native library {}: {}",
-                location.to_string_lossy(),
-                e
-            ));
+    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static,
+    {
+        let archive_ro = match ArchiveRO::open(archive) {
+            Ok(ar) => ar,
+            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
+        };
+        if self.additions.iter().any(|ar| ar.path() == archive) {
+            return Ok(());
+        }
+        self.additions.push(Addition::Archive {
+            path: archive.to_path_buf(),
+            archive: archive_ro,
+            skip: Box::new(skip),
         });
-    }
-
-    /// Adds all of the contents of the rlib at the specified path to this
-    /// archive.
-    ///
-    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
-    /// then the object file also isn't added.
-    fn add_rlib(
-        &mut self,
-        rlib: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> io::Result<()> {
-        // Ignoring obj file starting with the crate name
-        // as simple comparison is not enough - there
-        // might be also an extra name suffix
-        let obj_start = name.to_owned();
-
-        self.add_archive(rlib, move |fname: &str| {
-            // Ignore metadata files, no matter the name.
-            if fname == METADATA_FILENAME {
-                return true;
-            }
-
-            // Don't include Rust objects if LTO is enabled
-            if lto && looks_like_rust_object_file(fname) {
-                return true;
-            }
-
-            // Otherwise if this is *not* a rust object and we're skipping
-            // objects then skip this file
-            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                return true;
-            }
-
-            // ok, don't skip this
-            false
-        })
+        Ok(())
     }
 
     /// Adds an arbitrary file to this archive
@@ -270,25 +227,6 @@ fn src_archive(&mut self) -> Option<&ArchiveRO> {
         self.src_archive.as_ref().unwrap().as_ref()
     }
 
-    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
-        let archive_ro = match ArchiveRO::open(archive) {
-            Ok(ar) => ar,
-            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
-        };
-        if self.additions.iter().any(|ar| ar.path() == archive) {
-            return Ok(());
-        }
-        self.additions.push(Addition::Archive {
-            path: archive.to_path_buf(),
-            archive: archive_ro,
-            skip: Box::new(skip),
-        });
-        Ok(())
-    }
-
     fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
         let kind = &*self.config.sess.target.archive_format;
         kind.parse().map_err(|_| kind)
index 47529f719b514a880a1409d8d42120680186e832..da24fe08f0dfd6b7349e5290c27b216671de7678 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_target::abi::{self, Align, Size};
@@ -88,12 +88,12 @@ fn target_spec(&self) -> &Target {
     }
 }
 
-impl abi::LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.cx.layout_of(ty)
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        self.cx.handle_layout_err(err, span, ty)
     }
 }
 
index 5532f53e40823fc0ede2a3e56ed85206001637e7..cee582aec95ebf077b818093c990d77044451c07 100644 (file)
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
-use rustc_middle::ty::{layout::TyAndLayout, ScalarInt};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::ScalarInt;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};
+use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size};
 
 use libc::{c_char, c_uint};
 use tracing::debug;
index a4e4fc4fffb8f500ea14c6599e10383de80fd4f6..e673b06f1552795b6b65ec64abf335a9ba20ded7 100644 (file)
     Scalar as InterpScalar,
 };
 use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_target::abi::{
-    AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size, WrappingRange,
+    AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
 };
 use std::ops::Range;
 use tracing::debug;
index 45da18d4a24f3e003c06a301d274d395bd3a9622..2d397dc58353402fe76e6b4925e376176376a071 100644 (file)
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_middle::bug;
 use rustc_middle::mir::mono::CodegenUnit;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CFGuard, CrateType, DebugInfo};
 use rustc_session::Session;
-use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
 use smallvec::SmallVec;
 
@@ -835,22 +835,16 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
-impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.spanned_layout_of(ty, DUMMY_SP)
-    }
-
-    fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyAndLayout {
-        self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| {
-            if let LayoutError::SizeOverflow(_) = e {
-                self.sess().span_fatal(span, &e.to_string())
-            } else {
-                bug!("failed to get layout for `{}`: {}", ty, e)
-            }
-        })
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        if let LayoutError::SizeOverflow(_) = err {
+            self.sess().span_fatal(span, &err.to_string())
+        } else {
+            span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+        }
     }
 }
 
index 346c51c5426d84b589cce74e3482ecf2340e29d6..9a6391443dd010a2c383ceaf3479eb477c02ad8b 100644 (file)
@@ -28,7 +28,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::ich::NodeIdHashingMode;
 use rustc_middle::mir::{self, GeneratorLayout};
-use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
@@ -37,7 +37,7 @@
 use rustc_span::symbol::{Interner, Symbol};
 use rustc_span::FileNameDisplayPreference;
 use rustc_span::{self, SourceFile, SourceFileHash, Span};
-use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
+use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
 use tracing::debug;
index f6953b8b50ae98f6c03f1496e514d707eda9f530..fbaf8c8bdf63ddf33468227d37532995c0e05e55 100644 (file)
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
 use rustc_session::config::{self, DebugInfo};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
-use rustc_target::abi::{LayoutOf, Primitive, Size};
+use rustc_target::abi::{Primitive, Size};
 
 use libc::c_uint;
 use smallvec::SmallVec;
index e30c49295ba8c2b7054d5812651cc0a99ffb87ad..1aa52d975e9a015854dedef358b1c9e67955661f 100644 (file)
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
-use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
+use rustc_target::abi::{self, HasDataLayout, Primitive};
 use rustc_target::spec::PanicStrategy;
 
 use std::cmp::Ordering;
index 8a8ece640fcc71ccc2d05d7738013191c09fa46f..8ba3e870fbb71ca231968d12fbae82e27c91ff68 100644 (file)
@@ -8,10 +8,9 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 pub use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
 use rustc_session::config::CrateType;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::RelocModel;
 use tracing::debug;
 
index 9818905464dce4e8ba8b0d2e6d29f7d233737e99..d615d230ea0d19a45dc5fca07233cc39cbb67526 100644 (file)
@@ -4,12 +4,12 @@
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F32, F64};
-use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
+use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
 use smallvec::{smallvec, SmallVec};
 use tracing::debug;
 
index 2208ec37a423551539391ea47ba4ab10e883e2d2..caafae6c26750aaa9a7114bbe1fab3f65095f63e 100644 (file)
@@ -7,9 +7,9 @@
     common::IntPredicate,
     traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
 };
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, Endian, HasDataLayout, Size};
 
 fn round_pointer_up_to_alignment(
     bx: &mut Builder<'a, 'll, 'tcx>,
index 63f457bb979e3ff693f0702c228ca693545a9553..5188abdbe628632e8be71bd203ee52bf2141513c 100644 (file)
@@ -6,7 +6,7 @@
 use std::io;
 use std::path::{Path, PathBuf};
 
-pub fn find_library(
+pub(super) fn find_library(
     name: Symbol,
     verbatim: bool,
     search_paths: &[PathBuf],
@@ -48,14 +48,9 @@ pub trait ArchiveBuilder<'a> {
     fn remove_file(&mut self, name: &str);
     fn src_files(&mut self) -> Vec<String>;
 
-    fn add_rlib(
-        &mut self,
-        path: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> io::Result<()>;
-    fn add_native_library(&mut self, name: Symbol, verbatim: bool);
+    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static;
     fn update_symbols(&mut self);
 
     fn build(self);
index f5463bca3384c4c5e5d4934eea86c93b2e90fc6a..4fb51ecc1d347db0789d6e6de2fd03f73f6b6e8e 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
 use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
 
-use super::archive::ArchiveBuilder;
+use super::archive::{find_library, ArchiveBuilder};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::rpath::{self, RPathConfig};
@@ -36,6 +36,7 @@
 use tempfile::Builder as TempFileBuilder;
 
 use std::ffi::OsString;
+use std::lazy::OnceCell;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
 use std::{ascii, char, env, fmt, fs, io, mem, str};
@@ -230,6 +231,9 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     tmpdir: &MaybeTempDir,
 ) -> Result<B, ErrorReported> {
     info!("preparing rlib to {:?}", out_filename);
+
+    let lib_search_paths = archive_search_paths(sess);
+
     let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
 
     for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
@@ -254,6 +258,19 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     // metadata of the rlib we're generating somehow.
     for lib in codegen_results.crate_info.used_libraries.iter() {
         match lib.kind {
+            NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) }
+                if flavor == RlibFlavor::Normal =>
+            {
+                // Don't allow mixing +bundle with +whole_archive since an rlib may contain
+                // multiple native libs, some of which are +whole-archive and some of which are
+                // -whole-archive and it isn't clear how we can currently handle such a
+                // situation correctly.
+                // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
+                sess.err(
+                    "the linking modifiers `+bundle` and `+whole-archive` are not compatible \
+                        with each other when generating rlibs",
+                );
+            }
             NativeLibKind::Static { bundle: None | Some(true), .. } => {}
             NativeLibKind::Static { bundle: Some(false), .. }
             | NativeLibKind::Dylib { .. }
@@ -262,7 +279,15 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             | NativeLibKind::Unspecified => continue,
         }
         if let Some(name) = lib.name {
-            ab.add_native_library(name, lib.verbatim.unwrap_or(false));
+            let location =
+                find_library(name, lib.verbatim.unwrap_or(false), &lib_search_paths, sess);
+            ab.add_archive(&location, |_| false).unwrap_or_else(|e| {
+                sess.fatal(&format!(
+                    "failed to add native library {}: {}",
+                    location.to_string_lossy(),
+                    e
+                ));
+            });
         }
     }
 
@@ -541,13 +566,35 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
             matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
                 && !relevant_lib(sess, lib)
         });
-        ab.add_rlib(
-            path,
-            &name.as_str(),
-            are_upstream_rust_objects_already_included(sess)
-                && !ignored_for_lto(sess, &codegen_results.crate_info, cnum),
-            skip_object_files,
-        )
+
+        let lto = are_upstream_rust_objects_already_included(sess)
+            && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
+
+        // Ignoring obj file starting with the crate name
+        // as simple comparison is not enough - there
+        // might be also an extra name suffix
+        let obj_start = name.as_str().to_owned();
+
+        ab.add_archive(path, move |fname: &str| {
+            // Ignore metadata files, no matter the name.
+            if fname == METADATA_FILENAME {
+                return true;
+            }
+
+            // Don't include Rust objects if LTO is enabled
+            if lto && looks_like_rust_object_file(fname) {
+                return true;
+            }
+
+            // Otherwise if this is *not* a rust object and we're skipping
+            // objects then skip this file
+            if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
+                return true;
+            }
+
+            // ok, don't skip this
+            false
+        })
         .unwrap();
 
         all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
@@ -1218,10 +1265,11 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     sess.split_debuginfo() == SplitDebuginfo::Unpacked
 }
 
-pub fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
+fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
     sess.target_filesearch(PathKind::Native).search_path_dirs()
 }
 
+#[derive(PartialEq)]
 enum RlibFlavor {
     Normal,
     StaticlibBase,
@@ -2001,7 +2049,7 @@ fn add_local_native_libraries(
     let relevant_libs =
         codegen_results.crate_info.used_libraries.iter().filter(|l| relevant_lib(sess, l));
 
-    let search_path = archive_search_paths(sess);
+    let search_path = OnceCell::new();
     let mut last = (NativeLibKind::Unspecified, None);
     for lib in relevant_libs {
         let name = match lib.name {
@@ -2023,7 +2071,11 @@ fn add_local_native_libraries(
             }
             NativeLibKind::Static { bundle: None | Some(true), .. }
             | NativeLibKind::Static { whole_archive: Some(true), .. } => {
-                cmd.link_whole_staticlib(name, verbatim, &search_path);
+                cmd.link_whole_staticlib(
+                    name,
+                    verbatim,
+                    &search_path.get_or_init(|| archive_search_paths(sess)),
+                );
             }
             NativeLibKind::Static { .. } => cmd.link_staticlib(name, verbatim),
             NativeLibKind::RawDylib => {
@@ -2116,6 +2168,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     }
 
     let mut compiler_builtins = None;
+    let search_path = OnceCell::new();
 
     for &cnum in deps.iter() {
         if group_start == Some(cnum) {
@@ -2149,16 +2202,35 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
                 // external build system already has the native dependencies defined, and it
                 // will provide them to the linker itself.
                 if sess.opts.debugging_opts.link_native_libraries {
-                    // Skip if this library is the same as the last.
                     let mut last = None;
                     for lib in &codegen_results.crate_info.native_libraries[&cnum] {
-                        if lib.name.is_some()
-                            && relevant_lib(sess, lib)
-                            && matches!(lib.kind, NativeLibKind::Static { bundle: Some(false), .. })
-                            && last != lib.name
-                        {
-                            cmd.link_staticlib(lib.name.unwrap(), lib.verbatim.unwrap_or(false));
-                            last = lib.name;
+                        if !relevant_lib(sess, lib) {
+                            // Skip libraries if they are disabled by `#[link(cfg=...)]`
+                            continue;
+                        }
+
+                        // Skip if this library is the same as the last.
+                        if last == lib.name {
+                            continue;
+                        }
+
+                        if let Some(static_lib_name) = lib.name {
+                            if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
+                                lib.kind
+                            {
+                                let verbatim = lib.verbatim.unwrap_or(false);
+                                if whole_archive == Some(true) {
+                                    cmd.link_whole_staticlib(
+                                        static_lib_name,
+                                        verbatim,
+                                        search_path.get_or_init(|| archive_search_paths(sess)),
+                                    );
+                                } else {
+                                    cmd.link_staticlib(static_lib_name, verbatim);
+                                }
+
+                                last = lib.name;
+                            }
                         }
                     }
                 }
index f427dd7669399eb58690a1da07fe68aaeee13ac6..a6bf1d8d1e51a2ef596dc6e2c4532b13a75df1ad 100644 (file)
 use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::middle::lang_items;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, EntryFnType};
 use rustc_session::Session;
 use rustc_span::symbol::sym;
-use rustc_target::abi::{Align, LayoutOf, VariantIdx};
+use rustc_target::abi::{Align, VariantIdx};
 
 use std::convert::TryFrom;
 use std::ops::{Deref, DerefMut};
index b6ee70c419b160e224a8dcb60067c8ff9e240e06..634286770d1f92ccb45a27cfc815d02dcff298e2 100644 (file)
@@ -3,6 +3,7 @@
 #![feature(box_patterns)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
+#![feature(once_cell)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
 #![recursion_limit = "256"]
index b6def164fac631002bc920ed071bf2fb10eba5a2..8d75b2e7a3d4c62a92519e00cf503310c9cc0a75 100644 (file)
@@ -9,8 +9,7 @@
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
-use rustc_middle::ty::layout::HasTyCtxt;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 
 pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
index 2a76ad0fb1356ebb1b244e19ba413444a1fcb6b5..2ca7e8fd7e8e377e05a8a89a52a6c276137625ed 100644 (file)
 use rustc_index::vec::Idx;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::{self, SwitchTargets};
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, HasDataLayout, LayoutOf};
+use rustc_target::abi::{self, HasDataLayout};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
index cfb2befdf913752ffe89b4acd0faf8538badf4e0..5cee25b5cca3b5f9fa5362341f4617aaa21f15b5 100644 (file)
@@ -8,9 +8,9 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar};
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Abi, Align, LayoutOf, Size};
+use rustc_target::abi::{Abi, Align, Size};
 
 use std::fmt;
 
index 20be46606a0aad771c585580ccfeaa0f881843a6..b48d6d42b43577d62242d06c0d2fc12b8d396815 100644 (file)
@@ -8,10 +8,10 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::tcx::PlaceTy;
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding};
-use rustc_target::abi::{LayoutOf, VariantIdx, Variants};
+use rustc_target::abi::{VariantIdx, Variants};
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceRef<'tcx, V> {
index 02e2db54e741b38b77c71dc24604b7478cc753ec..3d8ea29160bd0941785274fa746c2883fb2fbae3 100644 (file)
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir;
 use rustc_middle::ty::cast::{CastTy, IntTy};
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
-use rustc_target::abi::{Abi, Int, LayoutOf, Variants};
+use rustc_target::abi::{Abi, Int, Variants};
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_rvalue(
index 48d753e0d843564f7d110c16d0ecad2f14206974..5f0f50ae2df1d2c046b44a29a8bbff1add56bf26 100644 (file)
@@ -4,8 +4,7 @@
 use rustc_hir as hir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::HasTyCtxt;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 
 pub trait MonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
index 96e53f51dac8f019f94398066cbb14c642d46bf0..dbb7e1ee8b17fd68e573850a13a7b427ffaf5e93 100644 (file)
@@ -8,15 +8,14 @@
 use rustc_errors::ErrorReported;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
     Session,
 };
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::Target;
 
 pub use rustc_data_structures::sync::MetadataRef;
@@ -39,17 +38,12 @@ pub trait BackendTypes {
 }
 
 pub trait Backend<'tcx>:
-    Sized
-    + BackendTypes
-    + HasTyCtxt<'tcx>
-    + LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
+    Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
 {
 }
 
 impl<'tcx, T> Backend<'tcx> for T where
-    Self: BackendTypes
-        + HasTyCtxt<'tcx>
-        + LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
+    Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
 {
 }
 
index 00e304734983ff15a0cb3e78dd76a8649f692508..b5d2d24736cdc4b89d30e9dc4a84e83a84abebc2 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::iter::FromIterator;
 
-/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
+/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
 /// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
 /// which uses only a single (null) pointer.
 #[derive(Clone, Encodable, Decodable, Debug)]
index 8199c44ee2aed21f64697b757d9ac8a560b7eb98..550c1c43530df6090c08f33d5f711f213e641c21 100644 (file)
@@ -9,9 +9,10 @@
 use rustc_serialize::json::Json;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
+use std::hash::{Hash, Hasher};
 
 #[must_use]
-#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
@@ -24,6 +25,10 @@ pub struct Diagnostic {
     /// as a sort key to sort a buffer of diagnostics.  By default, it is the primary span of
     /// `span` if there is one.  Otherwise, it is `DUMMY_SP`.
     pub sort_span: Span,
+
+    /// If diagnostic is from Lint, custom hash function ignores notes
+    /// otherwise hash is based on the all the fields
+    pub is_lint: bool,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
@@ -91,6 +96,7 @@ pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) ->
             children: vec![],
             suggestions: vec![],
             sort_span: DUMMY_SP,
+            is_lint: false,
         }
     }
 
@@ -558,6 +564,11 @@ pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
         self
     }
 
+    pub fn set_is_lint(&mut self) -> &mut Self {
+        self.is_lint = true;
+        self
+    }
+
     pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
         self.code = Some(s);
         self
@@ -617,6 +628,42 @@ fn sub_with_highlights(
         let sub = SubDiagnostic { level, message, span, render_span };
         self.children.push(sub);
     }
+
+    /// Fields used for Hash, and PartialEq trait
+    fn keys(
+        &self,
+    ) -> (
+        &Level,
+        &Vec<(String, Style)>,
+        &Option<DiagnosticId>,
+        &MultiSpan,
+        &Vec<CodeSuggestion>,
+        Option<&Vec<SubDiagnostic>>,
+    ) {
+        (
+            &self.level,
+            &self.message,
+            &self.code,
+            &self.span,
+            &self.suggestions,
+            (if self.is_lint { None } else { Some(&self.children) }),
+        )
+    }
+}
+
+impl Hash for Diagnostic {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.keys().hash(state);
+    }
+}
+
+impl PartialEq for Diagnostic {
+    fn eq(&self, other: &Self) -> bool {
+        self.keys() == other.keys()
+    }
 }
 
 impl SubDiagnostic {
index d35b29248033fd75ac3dd6bc4b59f7fad2fe0dd1..c498ce7dbe426aaed3a4396265d9fa61cd3255b5 100644 (file)
@@ -242,6 +242,7 @@ pub fn span_labels(
         sp: S,
         msg: &str,
     ) -> &mut Self);
+    forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
 
     /// See [`Diagnostic::multipart_suggestion()`].
     pub fn multipart_suggestion(
index 21fe894c6fcd3d12838e94bc7f4b3d7981dce5e2..84bc37170c6346d1bd819d54bacb17972cd0c900 100644 (file)
@@ -441,10 +441,12 @@ pub enum GenericBound<'hir> {
     Trait(PolyTraitRef<'hir>, TraitBoundModifier),
     // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
     LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
-    Unsized(Span),
     Outlives(Lifetime),
 }
 
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
+
 impl GenericBound<'_> {
     pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
         match self {
@@ -458,7 +460,6 @@ pub fn span(&self) -> Span {
             GenericBound::Trait(t, ..) => t.span,
             GenericBound::LangItemTrait(_, span, ..) => *span,
             GenericBound::Outlives(l) => l.span,
-            GenericBound::Unsized(span) => *span,
         }
     }
 }
index f4fbfd2692ca58866fa87f1bb223a8cdb8bac8f2..137782a6dc78dcf809b196cd9dc0b447017d7eb4 100644 (file)
@@ -32,7 +32,6 @@
 //! example generator inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use crate::hir_id::CRATE_HIR_ID;
 use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_ast::walk_list;
 use rustc_ast::{Attribute, Label};
@@ -477,17 +476,6 @@ fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
     }
 }
 
-/// Walks the contents of a crate. See also `Crate::visit_all_items`.
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
-    let top_mod = krate.module();
-    visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
-    for (&id, attrs) in krate.attrs.iter() {
-        for a in *attrs {
-            visitor.visit_attribute(id, a)
-        }
-    }
-}
-
 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
     visitor.visit_id(mod_hir_id);
     for &item_id in module.item_ids {
@@ -883,7 +871,6 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
             visitor.visit_generic_args(span, args);
         }
         GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
-        GenericBound::Unsized(_) => {}
     }
 }
 
index 42e51f4bb48c74e76de9980647dd249290e57ec2..36054c0484782016fd0bb57c1f151d383a76d610 100644 (file)
@@ -2232,9 +2232,6 @@ pub fn print_bounds<'b>(
                 GenericBound::Outlives(lt) => {
                     self.print_lifetime(lt);
                 }
-                GenericBound::Unsized(_) => {
-                    self.s.word("?Sized");
-                }
             }
         }
     }
index c4dc0fbadc813d885f4ff9b775d9fa060cc81319..c190391d2118098e18bbd0df6b5450f75ae10f7e 100644 (file)
@@ -142,7 +142,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
         krate.visit_all_item_likes(&mut dirty_clean_visitor);
 
         let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
-        intravisit::walk_crate(&mut all_attrs, krate);
+        tcx.hir().walk_attributes(&mut all_attrs);
 
         // Note that we cannot use the existing "unused attribute"-infrastructure
         // here, since that is running before codegen. This is also the reason why
index b821ed6cff9f83f2706f378f8ef953e823a323f9..572a4fc69717380aa6a8867a175425fd270da670 100644 (file)
 use std::env;
 use std::fs;
 use std::io::{self, Read};
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
+use rustc_data_structures::memmap::Mmap;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_serialize::Encoder;
+use rustc_session::Session;
 
 /// The first few bytes of files generated by incremental compilation.
 const FILE_MAGIC: &[u8] = b"RSIC";
@@ -28,7 +30,7 @@
 /// the Git commit hash.
 const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
-pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
+pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileEncodeResult {
     stream.emit_raw_bytes(FILE_MAGIC)?;
     stream.emit_raw_bytes(&[
         (HEADER_FORMAT_VERSION >> 0) as u8,
@@ -41,6 +43,61 @@ pub fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) -> FileE
     stream.emit_raw_bytes(rustc_version.as_bytes())
 }
 
+pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
+where
+    F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
+{
+    debug!("save: storing data in {}", path_buf.display());
+
+    // Delete the old file, if any.
+    // Note: It's important that we actually delete the old file and not just
+    // truncate and overwrite it, since it might be a shared hard-link, the
+    // underlying data of which we don't want to modify.
+    //
+    // We have to ensure we have dropped the memory maps to this file
+    // before performing this removal.
+    match fs::remove_file(&path_buf) {
+        Ok(()) => {
+            debug!("save: remove old file");
+        }
+        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
+        Err(err) => {
+            sess.err(&format!(
+                "unable to delete old {} at `{}`: {}",
+                name,
+                path_buf.display(),
+                err
+            ));
+            return;
+        }
+    }
+
+    let mut encoder = match FileEncoder::new(&path_buf) {
+        Ok(encoder) => encoder,
+        Err(err) => {
+            sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
+            return;
+        }
+    };
+
+    if let Err(err) = write_file_header(&mut encoder, sess.is_nightly_build()) {
+        sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    if let Err(err) = encode(&mut encoder) {
+        sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    if let Err(err) = encoder.flush() {
+        sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
+        return;
+    }
+
+    debug!("save: data written to disk successfully");
+}
+
 /// Reads the contents of a file with a file header as defined in this module.
 ///
 /// - Returns `Ok(Some(data, pos))` if the file existed and was generated by a
@@ -54,14 +111,21 @@ pub fn read_file(
     report_incremental_info: bool,
     path: &Path,
     nightly_build: bool,
-) -> io::Result<Option<(Vec<u8>, usize)>> {
-    let data = match fs::read(path) {
-        Ok(data) => data,
+) -> io::Result<Option<(Mmap, usize)>> {
+    let file = match fs::File::open(path) {
+        Ok(file) => file,
         Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
         Err(err) => return Err(err),
     };
+    // SAFETY: This process must not modify nor remove the backing file while the memory map lives.
+    // For the dep-graph and the work product index, it is as soon as the decoding is done.
+    // For the query result cache, the memory map is dropped in save_dep_graph before calling
+    // save_in and trying to remove the backing file.
+    //
+    // There is no way to prevent another process from modifying this file.
+    let mmap = unsafe { Mmap::map(file) }?;
 
-    let mut file = io::Cursor::new(data);
+    let mut file = io::Cursor::new(&*mmap);
 
     // Check FILE_MAGIC
     {
@@ -103,7 +167,7 @@ pub fn read_file(
     }
 
     let post_header_start_pos = file.position() as usize;
-    Ok(Some((file.into_inner(), post_header_start_pos)))
+    Ok(Some((mmap, post_header_start_pos)))
 }
 
 fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &str) {
index 437d5596447d7a050dbd9949c990298123ecd80a..4d38556e5d2145aa4ee34f275b88b6f4a739d368 100644 (file)
@@ -1,6 +1,7 @@
 //! Code to save/load the dep-graph from files.
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::memmap::Mmap;
 use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::OnDiskCache;
 use rustc_serialize::opaque::Decoder;
@@ -48,7 +49,7 @@ fn load_data(
     report_incremental_info: bool,
     path: &Path,
     nightly_build: bool,
-) -> LoadResult<(Vec<u8>, usize)> {
+) -> LoadResult<(Mmap, usize)> {
     match file_format::read_file(report_incremental_info, path, nightly_build) {
         Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
         Ok(None) => {
index a8455854ebb5fd97809e26f170c29c13beb4cfca..6c683058b12d668945278790ed3e26ed76e10168 100644 (file)
@@ -6,8 +6,6 @@
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_session::Session;
 use std::fs;
-use std::io;
-use std::path::PathBuf;
 
 use super::data::*;
 use super::dirty_clean;
@@ -44,7 +42,14 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
         join(
             move || {
                 sess.time("incr_comp_persist_result_cache", || {
-                    save_in(sess, query_cache_path, "query cache", |e| encode_query_cache(tcx, e));
+                    // Drop the memory map so that we can remove the file and write to it.
+                    if let Some(odc) = &tcx.on_disk_cache {
+                        odc.drop_serialized_data(tcx);
+                    }
+
+                    file_format::save_in(sess, query_cache_path, "query cache", |e| {
+                        encode_query_cache(tcx, e)
+                    });
                 });
             },
             move || {
@@ -86,7 +91,9 @@ pub fn save_work_product_index(
     debug!("save_work_product_index()");
     dep_graph.assert_ignored();
     let path = work_products_path(sess);
-    save_in(sess, path, "work product index", |e| encode_work_product_index(&new_work_products, e));
+    file_format::save_in(sess, path, "work product index", |e| {
+        encode_work_product_index(&new_work_products, e)
+    });
 
     // We also need to clean out old work-products, as not all of them are
     // deleted during invalidation. Some object files don't change their
@@ -113,58 +120,6 @@ pub fn save_work_product_index(
     });
 }
 
-pub(crate) fn save_in<F>(sess: &Session, path_buf: PathBuf, name: &str, encode: F)
-where
-    F: FnOnce(&mut FileEncoder) -> FileEncodeResult,
-{
-    debug!("save: storing data in {}", path_buf.display());
-
-    // Delete the old file, if any.
-    // Note: It's important that we actually delete the old file and not just
-    // truncate and overwrite it, since it might be a shared hard-link, the
-    // underlying data of which we don't want to modify
-    match fs::remove_file(&path_buf) {
-        Ok(()) => {
-            debug!("save: remove old file");
-        }
-        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
-        Err(err) => {
-            sess.err(&format!(
-                "unable to delete old {} at `{}`: {}",
-                name,
-                path_buf.display(),
-                err
-            ));
-            return;
-        }
-    }
-
-    let mut encoder = match FileEncoder::new(&path_buf) {
-        Ok(encoder) => encoder,
-        Err(err) => {
-            sess.err(&format!("failed to create {} at `{}`: {}", name, path_buf.display(), err));
-            return;
-        }
-    };
-
-    if let Err(err) = file_format::write_file_header(&mut encoder, sess.is_nightly_build()) {
-        sess.err(&format!("failed to write {} header to `{}`: {}", name, path_buf.display(), err));
-        return;
-    }
-
-    if let Err(err) = encode(&mut encoder) {
-        sess.err(&format!("failed to write {} to `{}`: {}", name, path_buf.display(), err));
-        return;
-    }
-
-    if let Err(err) = encoder.flush() {
-        sess.err(&format!("failed to flush {} to `{}`: {}", name, path_buf.display(), err));
-        return;
-    }
-
-    debug!("save: data written to disk successfully");
-}
-
 fn encode_work_product_index(
     work_products: &FxHashMap<WorkProductId, WorkProduct>,
     encoder: &mut FileEncoder,
index c292b2bdb30403077f27d6e430ea206c83b5a56d..35ebe92c59246d9fd9f585696fc3634f691018d7 100644 (file)
@@ -187,7 +187,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 if self.type_vars.0.contains(&vid) {
                     // This variable was created during the fudging.
                     // Recreate it with a fresh variable here.
-                    let idx = (vid.index - self.type_vars.0.start.index) as usize;
+                    let idx = (vid.as_usize() - self.type_vars.0.start.as_usize()) as usize;
                     let origin = self.type_vars.1[idx];
                     self.infcx.next_ty_var(origin)
                 } else {
index d2b0bdaf9780292ae613391470556199ca775968..f15268f6895efa8b92dba07373fc30057997abff 100644 (file)
@@ -196,7 +196,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
     /// Note that this function does not return care whether
     /// `vid` has been unified with something else or not.
     pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
-        self.storage.values.get(vid.index as usize).diverging
+        self.storage.values.get(vid.index()).diverging
     }
 
     /// Returns the origin that was given when `vid` was created.
@@ -204,7 +204,7 @@ pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
     /// Note that this function does not return care whether
     /// `vid` has been unified with something else or not.
     pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin {
-        &self.storage.values.get(vid.index as usize).origin
+        &self.storage.values.get(vid.as_usize()).origin
     }
 
     /// Records that `a == b`, depending on `dir`.
@@ -269,7 +269,7 @@ pub fn new_var(
         assert_eq!(eq_key.vid, sub_key);
 
         let index = self.values().push(TypeVariableData { origin, diverging });
-        assert_eq!(eq_key.vid.index, index as u32);
+        assert_eq!(eq_key.vid.as_u32(), index as u32);
 
         debug!(
             "new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}",
@@ -357,11 +357,11 @@ pub fn vars_since_snapshot(
         &mut self,
         value_count: usize,
     ) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
-        let range = TyVid { index: value_count as u32 }..TyVid { index: self.num_vars() as u32 };
+        let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars());
         (
             range.start..range.end,
-            (range.start.index..range.end.index)
-                .map(|index| self.storage.values.get(index as usize).origin)
+            (range.start.as_usize()..range.end.as_usize())
+                .map(|index| self.storage.values.get(index).origin)
                 .collect(),
         )
     }
@@ -371,7 +371,7 @@ pub fn vars_since_snapshot(
     pub fn unsolved_variables(&mut self) -> Vec<ty::TyVid> {
         (0..self.storage.values.len())
             .filter_map(|i| {
-                let vid = ty::TyVid { index: i as u32 };
+                let vid = ty::TyVid::from_usize(i);
                 match self.probe(vid) {
                     TypeVariableValue::Unknown { .. } => Some(vid),
                     TypeVariableValue::Known { .. } => None,
@@ -424,10 +424,10 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
     type Value = TypeVariableValue<'tcx>;
     #[inline(always)]
     fn index(&self) -> u32 {
-        self.vid.index
+        self.vid.as_u32()
     }
     fn from_index(i: u32) -> Self {
-        TyVidEqKey::from(ty::TyVid { index: i })
+        TyVidEqKey::from(ty::TyVid::from_u32(i))
     }
     fn tag() -> &'static str {
         "TyVidEqKey"
index 7127ec57c08c32f7ff2da687e45bd29e0af9c5d6..1d542db9b69c3eef068d2f40b1707f3038a0f5d9 100644 (file)
@@ -464,10 +464,6 @@ pub fn lower_to_hir<'res, 'tcx>(
         arena,
     );
 
-    if sess.opts.debugging_opts.hir_stats {
-        hir_stats::print_hir_stats(&hir_crate);
-    }
-
     sess.time("early_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
index 88b9e92119f60831c3cbef937c4bb1cfd68d98de..2850e7a6b44e95a485046701b98911e75a897ca3 100644 (file)
 use rustc_hir::{HirId, Node};
 use rustc_index::vec::Idx;
 use rustc_middle::lint::LintDiagnosticBuilder;
+use rustc_middle::ty::layout::{LayoutError, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
-use rustc_target::abi::{LayoutOf, VariantIdx};
+use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
index 7dbc3d60439c4e64881e645197f6eaebf01180ea..4c45e33db79c73976ddb1f07dc78eea6bde5d886 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::middle::stability;
-use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
 use rustc_serialize::json::Json;
@@ -41,7 +41,7 @@
 use rustc_session::SessionLintStore;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
-use rustc_target::abi::{self, LayoutOf};
+use rustc_target::abi;
 use tracing::debug;
 
 use std::cell::Cell;
@@ -1080,12 +1080,12 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
     }
 }
 
-impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
index 30400da86b4b0b042e93496fda12993057e650ba..2070fd69d3f8eb7f59e75683e735b5ea2a774aba 100644 (file)
@@ -451,9 +451,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         lint_callback!(cx, check_crate, krate);
-
-        hir_visit::walk_crate(cx, krate);
-
+        tcx.hir().walk_toplevel_module(cx);
+        tcx.hir().walk_attributes(cx);
         lint_callback!(cx, check_crate_post, krate);
     })
 }
index 90bf34ee863b874226f5b300943f939d6e433337..66966e589e48a5e234d7f80e0d00fea78671e2c5 100644 (file)
@@ -37,7 +37,7 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
 
     let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
     builder.levels.register_id(hir::CRATE_HIR_ID);
-    intravisit::walk_crate(&mut builder, krate);
+    tcx.hir().walk_toplevel_module(&mut builder);
     builder.levels.pop(push);
 
     builder.levels.build_map()
index 5d25578163976b75f6e2abcd0043a6ef2cb72f31..480f7756db3fe60476d766bc46ebffd852c38cf6 100644 (file)
@@ -6,14 +6,14 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
-use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::Abi;
-use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants};
+use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
 use if_chain::if_chain;
index 62d0374fb52e1a135a50e124c8810a1964da6bb0..e0b6039fe348f4bd0e24ed5581000ee9dec978b9 100644 (file)
@@ -7,9 +7,9 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
-use rustc_hir::intravisit;
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::*;
 use rustc_index::vec::Idx;
@@ -519,6 +519,22 @@ pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
         }
     }
 
+    /// Walks the contents of a crate. See also `Crate::visit_all_items`.
+    pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
+        let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
+        visitor.visit_mod(top_mod, span, hir_id);
+    }
+
+    /// Walks the attributes in a crate.
+    pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
+        let krate = self.krate();
+        for (&id, attrs) in krate.attrs.iter() {
+            for a in *attrs {
+                visitor.visit_attribute(id, a)
+            }
+        }
+    }
+
     pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
     where
         V: ItemLikeVisitor<'hir>,
@@ -934,7 +950,8 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc
         &tcx.untracked_resolutions.definitions,
         hcx,
     );
-    intravisit::walk_crate(&mut collector, tcx.untracked_crate);
+    let top_mod = tcx.untracked_crate.module();
+    collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
 
     let map = collector.finalize_and_compute_crate_hash();
     tcx.arena.alloc(map)
index 573fa913d680a177148417bf2bfa48cab5996d30..6868be50f1d068d458a3f7568d9992881501345e 100644 (file)
@@ -31,6 +31,7 @@
 #![feature(box_patterns)]
 #![feature(core_intrinsics)]
 #![feature(discriminant_kind)]
+#![feature(exhaustive_patterns)]
 #![feature(if_let_guard)]
 #![feature(never_type)]
 #![feature(extern_types)]
index 6ad68877235dc7d6453c65be964d44e5b278f05a..60cb78d902ee60f9dd49c6dab680907be6f2c758 100644 (file)
@@ -192,6 +192,7 @@ impl<'a> LintDiagnosticBuilder<'a> {
     /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
     pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
         self.0.set_primary_message(msg);
+        self.0.set_is_lint();
         self.0
     }
 
index dada94edc95ff12f9157d3772208ae8e50eace82..c93996162e3e372b491ce58f55d3927a39fe67d2 100644 (file)
         desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
     }
 
+    query own_existential_vtable_entries(
+        key: ty::PolyExistentialTraitRef<'tcx>
+    ) -> &'tcx [DefId] {
+        desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
+    }
+
     query vtable_entries(key: ty::PolyTraitRef<'tcx>)
                         -> &'tcx [ty::VtblEntry<'tcx>] {
         desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
index de7c6d9e095303a9f0d4bd7463852f335eff390e..1f5057d1da22ff9c73bc66f79eb2f13b919ed801 100644 (file)
@@ -27,6 +27,7 @@
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -71,7 +72,7 @@
 
 pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
-    fn new(sess: &'tcx Session, data: Vec<u8>, start_pos: usize) -> Self
+    fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
     where
         Self: Sized;
 
@@ -100,6 +101,8 @@ fn def_path_hash_to_def_id(
     fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode);
     fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash);
 
+    fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
+
     fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult;
 }
 
index 4cfb104bee3a49473d7981fcf345705e3c89d108..092eae0fc5c236bbd3bb91ed99b767a7f2994a72 100644 (file)
@@ -2,7 +2,6 @@
 
 use crate::ty::TyKind::*;
 use crate::ty::{InferTy, TyCtxt, TyS};
-use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -114,10 +113,8 @@ fn suggest_removing_unsized_bound(
     def_id: Option<DefId>,
 ) {
     // See if there's a `?Sized` bound that can be removed to suggest that.
-    // First look at the `where` clause because we can have `where T: ?Sized`, but that
-    // `?Sized` bound is *also* included in the `GenericParam` as a bound, which breaks
-    // the spans. Hence the somewhat involved logic that follows.
-    let mut where_unsized_bounds = FxHashSet::default();
+    // First look at the `where` clause because we can have `where T: ?Sized`,
+    // then look at params.
     for (where_pos, predicate) in generics.where_clause.predicates.iter().enumerate() {
         match predicate {
             WherePredicate::BoundPredicate(WhereBoundPredicate {
@@ -140,7 +137,6 @@ fn suggest_removing_unsized_bound(
             }) if segment.ident.as_str() == param_name => {
                 for (pos, bound) in bounds.iter().enumerate() {
                     match bound {
-                        hir::GenericBound::Unsized(_) => {}
                         hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
                             if poly.trait_ref.trait_def_id() == def_id => {}
                         _ => continue,
@@ -173,7 +169,6 @@ fn suggest_removing_unsized_bound(
                         //             ^^^^^^^^^
                         (_, pos, _, _) => bounds[pos - 1].span().shrink_to_hi().to(bound.span()),
                     };
-                    where_unsized_bounds.insert(bound.span());
                     err.span_suggestion_verbose(
                         sp,
                         "consider removing the `?Sized` bound to make the \
@@ -189,8 +184,7 @@ fn suggest_removing_unsized_bound(
     for (pos, bound) in param.bounds.iter().enumerate() {
         match bound {
             hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe)
-                if poly.trait_ref.trait_def_id() == def_id
-                    && !where_unsized_bounds.contains(&bound.span()) =>
+                if poly.trait_ref.trait_def_id() == def_id =>
             {
                 let sp = match (param.bounds.len(), pos) {
                     // T: ?Sized,
index 5e5902abe662f9063d4b96cb7d005bf4179e3e87..f7ab9dd82ac738971450a43ea912ba456ea56a8e 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
 };
@@ -2062,29 +2062,113 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
+pub trait MaybeResult<T> {
+    type Error;
+
+    fn from(x: Result<T, Self::Error>) -> Self;
+    fn to_result(self) -> Result<T, Self::Error>;
+}
+
+impl<T> MaybeResult<T> for T {
+    type Error = !;
+
+    fn from(Ok(x): Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        Ok(self)
+    }
+}
+
+impl<T, E> MaybeResult<T> for Result<T, E> {
+    type Error = E;
+
+    fn from(x: Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        self
+    }
+}
+
 pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
 
-impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+/// Trait for contexts that want to be able to compute layouts of types.
+/// This automatically gives access to `LayoutOf`, through a blanket `impl`.
+pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
+    /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
+    /// returned from `layout_of` (see also `handle_layout_err`).
+    type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
 
+    /// `Span` to use for `tcx.at(span)`, from `layout_of`.
+    // FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
+    #[inline]
+    fn layout_tcx_at_span(&self) -> Span {
+        DUMMY_SP
+    }
+
+    /// Helper used for `layout_of`, to adapt `tcx.layout_of(...)` into a
+    /// `Self::LayoutOfResult` (which does not need to be a `Result<...>`).
+    ///
+    /// Most `impl`s, which propagate `LayoutError`s, should simply return `err`,
+    /// but this hook allows e.g. codegen to return only `TyAndLayout` from its
+    /// `cx.layout_of(...)`, without any `Result<...>` around it to deal with
+    /// (and any `LayoutError`s are turned into fatal errors or ICEs).
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        span: Span,
+        ty: Ty<'tcx>,
+    ) -> <Self::LayoutOfResult as MaybeResult<TyAndLayout<'tcx>>>::Error;
+}
+
+/// Blanket extension trait for contexts that can compute layouts of types.
+pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode, and will normalize the input type.
     #[inline]
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
+        self.spanned_layout_of(ty, DUMMY_SP)
+    }
+
+    /// Computes the layout of a type, at `span`. Note that this implicitly
+    /// executes in "reveal all" mode, and will normalize the input type.
+    // FIXME(eddyb) avoid passing information like this, and instead add more
+    // `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
+    #[inline]
+    fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
+        let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
+        MaybeResult::from(
+            self.tcx()
+                .at(span)
+                .layout_of(self.param_env().and(ty))
+                .map_err(|err| self.handle_layout_err(err, span, ty)),
+        )
     }
 }
 
-impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
+
+impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
+    }
+}
+
+impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+
+    #[inline]
+    fn layout_tcx_at_span(&self) -> Span {
+        self.tcx.span
+    }
 
-    /// Computes the layout of a type. Note that this implicitly
-    /// executes in "reveal all" mode, and will normalize the input type.
     #[inline]
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
@@ -2559,11 +2643,7 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 
 pub trait FnAbiExt<'tcx, C>
 where
-    C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
-        + HasDataLayout
-        + HasTargetSpec
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
+    C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
 {
     /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
     ///
@@ -2746,11 +2826,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
 
 impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
 where
-    C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
-        + HasDataLayout
-        + HasTargetSpec
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
+    C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
 {
     fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
         call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
index d01ca27b8511895b78102b6c087c1cd496e33fb1..fddfd6e435c0550e586f0ffa732a35784ab33f99 100644 (file)
@@ -137,6 +137,9 @@ pub struct ResolverOutputs {
     /// A list of proc macro LocalDefIds, written out in the order in which
     /// they are declared in the static array generated by proc_macro_harness.
     pub proc_macros: Vec<LocalDefId>,
+    /// Mapping from ident span to path span for paths that don't exist as written, but that
+    /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
+    pub confused_type_with_std_module: FxHashMap<Span, Span>,
 }
 
 #[derive(Clone, Copy, Debug)]
index dc6a6b0b9f3d8bca119dcd52d4dde902e5ac5a29..3e8a93e08c29d9c6739735e0f70d023f10f2efb9 100644 (file)
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::traits::Reveal;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, subst::Subst, TyCtxt};
 use rustc_span::source_map::Span;
-use rustc_target::abi::{Abi, LayoutOf};
+use rustc_target::abi::Abi;
 use std::borrow::Cow;
 use std::convert::TryInto;
 
index 6f18009cf47304c5d615f4cbe57e8e25df094e3d..4c4b0bd2d1f271c215d8e6b9591e9f3ee077e851 100644 (file)
@@ -5,9 +5,9 @@
 use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
 use rustc_middle::mir::CastKind;
 use rustc_middle::ty::adjustment::PointerCast;
-use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
-use rustc_target::abi::{Integer, LayoutOf, Variants};
+use rustc_target::abi::{Integer, Variants};
 
 use super::{
     util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
index c6003d87f3ac6236674f8d3270f679e6bf3c4edb..05502d8b21f1ce7a5026d4d74927c1b4db41c495 100644 (file)
@@ -8,18 +8,18 @@
 use rustc_macros::HashStable;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::{self, TyAndLayout};
+use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_session::Limit;
 use rustc_span::{Pos, Span};
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
-    AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory,
-    MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit,
-    StackPopJump,
+    AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
+    MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar,
+    ScalarMaybeUninit, StackPopJump,
 };
 use crate::transform::validate::equal_up_to_regions;
 use crate::util::storage::AlwaysLiveLocals;
@@ -313,15 +313,22 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf<'tcx> for InterpCx<'mir, 'tcx, M> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
+    type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
 
     #[inline]
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx
-            .layout_of(self.param_env.and(ty))
-            .map_err(|layout| err_inval!(Layout(layout)).into())
+    fn layout_tcx_at_span(&self) -> Span {
+        self.tcx.span
+    }
+
+    #[inline]
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        _: Span,
+        _: Ty<'tcx>,
+    ) -> InterpErrorInfo<'tcx> {
+        err_inval!(Layout(err)).into()
     }
 }
 
index bfab886b6ee4f9fd2ab9c40b62099c287170884f..07e974b72664bbefc7103a91f80532ea3135ec6e 100644 (file)
     BinOp,
 };
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size};
+use rustc_target::abi::{Abi, Align, Primitive, Size};
 
 use super::{
     util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
index 022129b2a22046a04806c4dbb893cbd4555aa5a1..d4cbba18029311bff2079acb73220ddb4d42bf62 100644 (file)
@@ -3,9 +3,9 @@
 use rustc_ast::Mutability;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::subst::Subst;
 use rustc_span::{Span, Symbol};
-use rustc_target::abi::LayoutOf;
 
 use crate::interpret::{
     intrinsics::{InterpCx, Machine},
index 4afce2b6b80f2477f82b5eb46cb4011c0cf58523..e67a6690836ad2a9ed8f12599369a07099775d3c 100644 (file)
@@ -7,11 +7,11 @@
 use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
-use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
 use rustc_middle::ty::{ConstInt, Ty};
 use rustc_middle::{mir, ty};
-use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding};
+use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 
 use super::{
index 79b493d74e19b47006653f8bbd6fb0ccad7012e0..ac000b1bb566fe7ea9c037167da15e730073085e 100644 (file)
@@ -3,8 +3,8 @@
 use rustc_apfloat::Float;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
-use rustc_middle::ty::{self, layout::TyAndLayout, FloatTy, Ty};
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, FloatTy, Ty};
 
 use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
 
index afad9716b3fe1ca712fcff8d2ca13a066072cdb6..95a44e3fecf3d19b249c1f81924f123b5ebc010b 100644 (file)
@@ -8,10 +8,10 @@
 use rustc_ast::Mutability;
 use rustc_macros::HashStable;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
-use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
+use rustc_target::abi::{HasDataLayout, Size, VariantIdx, Variants};
 
 use super::{
     alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
index f2a8a067dfac2a11287515d4a2e927aec3c62946..1e96581c392d25e31d1d688494f0a865eddc8c1a 100644 (file)
@@ -4,7 +4,7 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::LayoutOf;
 
 use super::{InterpCx, Machine};
 
index 63496045e0d73cf69f826e823986a94a971eed8d..1c8e5e9e23c3caefab88cd27f834bd67c5b8db48 100644 (file)
@@ -2,13 +2,13 @@
 use std::convert::TryFrom;
 
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::ty::layout::{self, TyAndLayout};
+use rustc_middle::ty::layout::{self, LayoutOf as _, TyAndLayout};
 use rustc_middle::ty::Instance;
 use rustc_middle::{
     mir,
     ty::{self, Ty},
 };
-use rustc_target::abi::{self, LayoutOf as _};
+use rustc_target::abi;
 use rustc_target::spec::abi::Abi;
 
 use super::{
index 2bb2f88725784f30186729c866eb728db7dffaeb..03e0a8e7901d94c86f2077dd026e207e1aaea148 100644 (file)
 use rustc_hir as hir;
 use rustc_middle::mir::interpret::InterpError;
 use rustc_middle::ty;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{
-    Abi, LayoutOf, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
-};
+use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
 
 use std::hash::Hash;
 
index 5c51aa4ed679b8bb449d32be6795b67270b14425..71c07be4c6d8de860919f58a7e51f38cc4d19e95 100644 (file)
     Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
     StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
 };
-use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{
     self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_session::lint;
 use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 
@@ -330,12 +330,12 @@ struct ConstPropagator<'mir, 'tcx> {
     source_info: Option<SourceInfo>,
 }
 
-impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
index 22c44beb350ae9234339ea51c2b60c74f4836564..e30e758e63779db24c094a481e44e7672586c761 100644 (file)
@@ -68,7 +68,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                     let then_blk = unpack!(this.then_else_break(
                                         block,
                                         &this.thir[cond],
-                                        condition_scope,
+                                        Some(condition_scope),
                                         condition_scope,
                                         then_expr.span,
                                     ));
index ec54a2a0ec4eeefebd99d1ecad3dfe6268f28865..ba94e15444a1905f5c7efcd3da76cca26eab0edd 100644 (file)
@@ -39,7 +39,7 @@ pub(crate) fn then_else_break(
         &mut self,
         mut block: BasicBlock,
         expr: &Expr<'tcx>,
-        temp_scope: region::Scope,
+        temp_scope_override: Option<region::Scope>,
         break_scope: region::Scope,
         variable_scope_span: Span,
     ) -> BlockAnd<()> {
@@ -53,7 +53,7 @@ pub(crate) fn then_else_break(
                     this.then_else_break(
                         block,
                         &this.thir[value],
-                        temp_scope,
+                        temp_scope_override,
                         break_scope,
                         variable_scope_span,
                     )
@@ -63,6 +63,7 @@ pub(crate) fn then_else_break(
                 this.lower_let_expr(block, &this.thir[expr], pat, break_scope, variable_scope_span)
             }
             _ => {
+                let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
                 let mutability = Mutability::Mut;
                 let place =
                     unpack!(block = this.as_temp(block, Some(temp_scope), expr, mutability));
@@ -1948,7 +1949,6 @@ fn bind_and_guard_matched_candidate<'pat>(
             }
 
             let arm_span = arm_span.unwrap();
-            let arm_scope = self.local_scope();
             let match_scope = match_scope.unwrap();
             let mut guard_span = rustc_span::DUMMY_SP;
 
@@ -1957,7 +1957,7 @@ fn bind_and_guard_matched_candidate<'pat>(
                     Guard::If(e) => {
                         let e = &this.thir[e];
                         guard_span = e.span;
-                        this.then_else_break(block, e, arm_scope, match_scope, arm_span)
+                        this.then_else_break(block, e, None, match_scope, arm_span)
                     }
                     Guard::IfLet(ref pat, scrutinee) => {
                         let s = &this.thir[scrutinee];
index e9f0038b2d65dc9d09b763c3ae596d4fb8212e6d..b402b8ba53ada3b3a0a96e3307e6185f5b2ccbf1 100644 (file)
@@ -1,10 +1,10 @@
-use super::{AttrWrapper, Capturing, Parser, PathStyle};
+use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle};
 use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{error_code, PResult};
-use rustc_span::{sym, Span};
+use rustc_errors::{error_code, DiagnosticBuilder, PResult};
+use rustc_span::{sym, BytePos, Span};
 use std::convert::TryInto;
 
 use tracing::debug;
@@ -25,6 +25,12 @@ pub enum InnerAttrPolicy<'a> {
     prev_attr_sp: None,
 };
 
+enum OuterAttributeType {
+    DocComment,
+    DocBlockComment,
+    Attribute,
+}
+
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
@@ -49,18 +55,32 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
                 Some(self.parse_attribute(inner_parse_policy)?)
             } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                 if attr_style != ast::AttrStyle::Outer {
-                    self.sess
-                        .span_diagnostic
-                        .struct_span_err_with_code(
-                            self.token.span,
-                            "expected outer doc comment",
-                            error_code!(E0753),
-                        )
-                        .note(
-                            "inner doc comments like this (starting with \
-                         `//!` or `/*!`) can only appear before items",
-                        )
-                        .emit();
+                    let span = self.token.span;
+                    let mut err = self.sess.span_diagnostic.struct_span_err_with_code(
+                        span,
+                        "expected outer doc comment",
+                        error_code!(E0753),
+                    );
+                    if let Some(replacement_span) = self.annotate_following_item_if_applicable(
+                        &mut err,
+                        span,
+                        match comment_kind {
+                            token::CommentKind::Line => OuterAttributeType::DocComment,
+                            token::CommentKind::Block => OuterAttributeType::DocBlockComment,
+                        },
+                    ) {
+                        err.note(
+                            "inner doc comments like this (starting with `//!` or `/*!`) can \
+                            only appear before items",
+                        );
+                        err.span_suggestion_verbose(
+                            replacement_span,
+                            "you might have meant to write a regular comment",
+                            String::new(),
+                            rustc_errors::Applicability::MachineApplicable,
+                        );
+                    }
+                    err.emit();
                 }
                 self.bump();
                 just_parsed_doc_comment = true;
@@ -97,7 +117,7 @@ pub fn parse_attribute(
             inner_parse_policy, self.token
         );
         let lo = self.token.span;
-        // Attributse can't have attributes of their own
+        // Attributes can't have attributes of their own [Editor's note: not with that attitude]
         self.collect_tokens_no_attrs(|this| {
             if this.eat(&token::Pound) {
                 let style = if this.eat(&token::Not) {
@@ -125,6 +145,75 @@ pub fn parse_attribute(
         })
     }
 
+    fn annotate_following_item_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        span: Span,
+        attr_type: OuterAttributeType,
+    ) -> Option<Span> {
+        let mut snapshot = self.clone();
+        let lo = span.lo()
+            + BytePos(match attr_type {
+                OuterAttributeType::Attribute => 1,
+                _ => 2,
+            });
+        let hi = lo + BytePos(1);
+        let replacement_span = span.with_lo(lo).with_hi(hi);
+        if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type {
+            snapshot.bump();
+        }
+        loop {
+            // skip any other attributes, we want the item
+            if snapshot.token.kind == token::Pound {
+                if let Err(mut err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) {
+                    err.cancel();
+                    return Some(replacement_span);
+                }
+            } else {
+                break;
+            }
+        }
+        match snapshot.parse_item_common(
+            AttrWrapper::empty(),
+            true,
+            false,
+            |_| true,
+            ForceCollect::No,
+        ) {
+            Ok(Some(item)) => {
+                let attr_name = match attr_type {
+                    OuterAttributeType::Attribute => "attribute",
+                    _ => "doc comment",
+                };
+                err.span_label(
+                    item.span,
+                    &format!("the inner {} doesn't annotate this {}", attr_name, item.kind.descr()),
+                );
+                err.span_suggestion_verbose(
+                    replacement_span,
+                    &format!(
+                        "to annotate the {}, change the {} from inner to outer style",
+                        item.kind.descr(),
+                        attr_name
+                    ),
+                    (match attr_type {
+                        OuterAttributeType::Attribute => "",
+                        OuterAttributeType::DocBlockComment => "*",
+                        OuterAttributeType::DocComment => "/",
+                    })
+                    .to_string(),
+                    rustc_errors::Applicability::MachineApplicable,
+                );
+                return None;
+            }
+            Err(mut item_err) => {
+                item_err.cancel();
+            }
+            Ok(None) => {}
+        }
+        Some(replacement_span)
+    }
+
     pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
         if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
             let prev_attr_note =
@@ -138,11 +227,20 @@ pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerA
             }
 
             diag.note(
-                "inner attributes, like `#![no_std]`, annotate the item enclosing them, \
-                and are usually found at the beginning of source files. \
-                Outer attributes, like `#[test]`, annotate the item following them.",
-            )
-            .emit();
+                "inner attributes, like `#![no_std]`, annotate the item enclosing them, and \
+                are usually found at the beginning of source files",
+            );
+            if self
+                .annotate_following_item_if_applicable(
+                    &mut diag,
+                    attr_sp,
+                    OuterAttributeType::Attribute,
+                )
+                .is_some()
+            {
+                diag.note("outer attributes, like `#[test]`, annotate the item following them");
+            };
+            diag.emit();
         }
     }
 
index a1d3e9adba013e91d0ecd36745bd928bac6d32cf..05156745105a1c0a10b839720f00c8a957d153ef 100644 (file)
@@ -516,6 +516,26 @@ macro_rules! make_it {
             token::BinOp(token::And) | token::AndAnd => {
                 make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
             }
+            token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
+                let mut err = this.struct_span_err(lo, "leading `+` is not supported");
+                err.span_label(lo, "unexpected `+`");
+
+                // a block on the LHS might have been intended to be an expression instead
+                if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
+                    this.sess.expr_parentheses_needed(&mut err, *sp);
+                } else {
+                    err.span_suggestion_verbose(
+                        lo,
+                        "try removing the `+`",
+                        "".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                }
+                err.emit();
+
+                this.bump();
+                this.parse_prefix_expr(None)
+            } // `+expr`
             token::Ident(..) if this.token.is_keyword(kw::Box) => {
                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
             }
index ae65222f3f22fc450d959293fa9a4152799382dc..25ad00aaf1f753caa8f98f37224d898d5e1528ee 100644 (file)
@@ -775,5 +775,5 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     let krate = tcx.hir().krate();
     let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor { tcx, live_symbols };
-    intravisit::walk_crate(&mut visitor, krate);
+    tcx.hir().walk_toplevel_module(&mut visitor);
 }
index 944a3097a61c33ee476631a3aa956d3ab55018be..18f61c6e1c1a787df5b6733e881d0db950c4f3f2 100644 (file)
 pub fn check_crate(tcx: TyCtxt<'_>) {
     tcx.dep_graph.assert_ignored();
 
+    if tcx.sess.opts.debugging_opts.hir_stats {
+        crate::hir_stats::print_hir_stats(tcx);
+    }
+
     let errors = Lock::new(Vec::new());
     let hir_map = tcx.hir();
 
index b8ce973185c8d73011338ae1e4abe9d5f1b6dbbf..d665c12f762c5baa49a0fb6974c847191d196f34 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::HirId;
 use rustc_middle::hir::map::Map;
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::util::common::to_readable_str;
 use rustc_span::Span;
 
@@ -25,18 +26,19 @@ struct NodeData {
 }
 
 struct StatCollector<'k> {
-    krate: Option<&'k hir::Crate<'k>>,
+    krate: Option<Map<'k>>,
     data: FxHashMap<&'static str, NodeData>,
     seen: FxHashSet<Id>,
 }
 
-pub fn print_hir_stats(krate: &hir::Crate<'_>) {
+pub fn print_hir_stats(tcx: TyCtxt<'_>) {
     let mut collector = StatCollector {
-        krate: Some(krate),
+        krate: Some(tcx.hir()),
         data: FxHashMap::default(),
         seen: FxHashSet::default(),
     };
-    hir_visit::walk_crate(&mut collector, krate);
+    tcx.hir().walk_toplevel_module(&mut collector);
+    tcx.hir().walk_attributes(&mut collector);
     collector.print("HIR STATS");
 }
 
index 64ea4ee570e821d97a9269693f27c8182a6f7e4a..aa78fcfb4b373cc42066634ba885784ac7acb44b 100644 (file)
@@ -3,10 +3,11 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::ItemKind;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::sym;
-use rustc_target::abi::{HasDataLayout, LayoutOf, TargetDataLayout};
+use rustc_span::Span;
+use rustc_target::abi::{HasDataLayout, TargetDataLayout};
 
 pub fn test_layout(tcx: TyCtxt<'_>) {
     if tcx.features().rustc_attrs {
@@ -113,12 +114,16 @@ struct UnwrapLayoutCx<'tcx> {
     param_env: ParamEnv<'tcx>,
 }
 
-impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty)).unwrap()
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        span_bug!(
+            span,
+            "`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`",
+            ty,
+            err
+        );
     }
 }
 
index 7d15ca1e8f798a2299f5e9201d8abe6a7814798e..ff8bd37238d6bc7db187fb58509da637e6919df1 100644 (file)
@@ -6,7 +6,7 @@
 
 use rustc_ast::{Attribute, MetaItem, MetaItemKind};
 use rustc_errors::struct_span_err;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::lib_features::LibFeatures;
 use rustc_middle::ty::query::Providers;
@@ -126,9 +126,7 @@ fn visit_attribute(&mut self, _: rustc_hir::HirId, attr: &'tcx Attribute) {
 
 fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
-    let krate = tcx.hir().krate();
-
-    intravisit::walk_crate(&mut collector, krate);
+    tcx.hir().walk_attributes(&mut collector);
     collector.lib_features
 }
 
index a88393cea828593f0ac8696284af222226a4d808..b7e43b7785da602a170632beddb3ad53f0083155 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
 use rustc_middle::hir::map::Map;
@@ -678,7 +679,6 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
         .collect();
 
     {
-        let krate = tcx.hir().krate();
         let mut annotator = Annotator {
             tcx,
             index: &mut index,
@@ -711,13 +711,13 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
 
         annotator.annotate(
             CRATE_DEF_ID,
-            krate.module().inner,
+            tcx.hir().span(CRATE_HIR_ID),
             None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
             InheritStability::No,
-            |v| intravisit::walk_crate(v, krate),
+            |v| tcx.hir().walk_toplevel_module(v),
         );
     }
     index
@@ -908,8 +908,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
-        missing.check_missing_stability(CRATE_DEF_ID, krate.module().inner);
-        intravisit::walk_crate(&mut missing, krate);
+        missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
+        tcx.hir().walk_toplevel_module(&mut missing);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
 
index 9c376c6c93e2e009f128a966e10f48d81d479086..35e25e52dc5f9f1e2fc12b492055eff4eeb9dbd3 100644 (file)
@@ -2169,7 +2169,7 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
         changed: false,
     };
     loop {
-        intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+        tcx.hir().walk_toplevel_module(&mut visitor);
         if visitor.changed {
             visitor.changed = false;
         } else {
@@ -2192,11 +2192,11 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
         in_variant: false,
         old_error_set: Default::default(),
     };
-    intravisit::walk_crate(&mut visitor, krate);
+    tcx.hir().walk_toplevel_module(&mut visitor);
 
     let has_pub_restricted = {
         let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false };
-        intravisit::walk_crate(&mut pub_restricted_visitor, krate);
+        tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor);
         pub_restricted_visitor.has_pub_restricted
     };
 
index c973eae6b0665a29e49f480fe09d39f75b44e252..42e8b4023cfad489c219d106031baaf804cfdc79 100644 (file)
@@ -294,6 +294,16 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
     }
 }
 
+impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.def_id().krate == LOCAL_CRATE
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        tcx.def_span(self.def_id())
+    }
+}
+
 impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
index ee64f22618e7e000c98d82fa84f2a4f6e2d430e0..5c2803c67e73fca87c75741741946820689356e2 100644 (file)
@@ -1,6 +1,7 @@
 use crate::QueryCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
+use rustc_data_structures::memmap::Mmap;
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell, RwLock};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
@@ -42,7 +43,7 @@
 /// any side effects that have been emitted during a query.
 pub struct OnDiskCache<'sess> {
     // The complete cache data in serialized form.
-    serialized_data: Vec<u8>,
+    serialized_data: RwLock<Option<Mmap>>,
 
     // Collects all `QuerySideEffects` created during the current compilation
     // session.
@@ -182,7 +183,8 @@ fn new(tcx: TyCtxt<'_>, file: &SourceFile) -> EncodedSourceFileId {
 }
 
 impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
-    fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
+    /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
+    fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
         debug_assert!(sess.opts.incremental.is_some());
 
         // Wrap in a scope so we can borrow `data`.
@@ -204,7 +206,7 @@ fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
         };
 
         Self {
-            serialized_data: data,
+            serialized_data: RwLock::new(Some(data)),
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
             cnum_map: OnceCell::new(),
@@ -225,7 +227,7 @@ fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
 
     fn new_empty(source_map: &'sess SourceMap) -> Self {
         Self {
-            serialized_data: Vec::new(),
+            serialized_data: RwLock::new(None),
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
             cnum_map: OnceCell::new(),
@@ -244,7 +246,31 @@ fn new_empty(source_map: &'sess SourceMap) -> Self {
         }
     }
 
-    fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncodeResult {
+    /// Execute all cache promotions and release the serialized backing Mmap.
+    ///
+    /// Cache promotions require invoking queries, which needs to read the serialized data.
+    /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be
+    /// deleted, hence we won't be able to refer to its memmapped data.
+    fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) {
+        // Register any dep nodes that we reused from the previous session,
+        // but didn't `DepNode::construct` in this session. This ensures
+        // that their `DefPathHash` to `RawDefId` mappings are registered
+        // in 'latest_foreign_def_path_hashes' if necessary, since that
+        // normally happens in `DepNode::construct`.
+        tcx.dep_graph.register_reused_dep_nodes(tcx);
+
+        // Load everything into memory so we can write it out to the on-disk
+        // cache. The vast majority of cacheable query results should already
+        // be in memory, so this should be a cheap operation.
+        // Do this *before* we clone 'latest_foreign_def_path_hashes', since
+        // loading existing queries may cause us to create new DepNodes, which
+        // may in turn end up invoking `store_foreign_def_id_hash`
+        tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
+
+        *self.serialized_data.write() = None;
+    }
+
+    fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileEncodeResult {
         // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
             // Allocate `SourceFileIndex`es.
@@ -266,21 +292,6 @@ fn serialize(&self, tcx: TyCtxt<'sess>, encoder: &mut FileEncoder) -> FileEncode
                 (file_to_file_index, file_index_to_stable_id)
             };
 
-            // Register any dep nodes that we reused from the previous session,
-            // but didn't `DepNode::construct` in this session. This ensures
-            // that their `DefPathHash` to `RawDefId` mappings are registered
-            // in 'latest_foreign_def_path_hashes' if necessary, since that
-            // normally happens in `DepNode::construct`.
-            tcx.dep_graph.register_reused_dep_nodes(tcx);
-
-            // Load everything into memory so we can write it out to the on-disk
-            // cache. The vast majority of cacheable query results should already
-            // be in memory, so this should be a cheap operation.
-            // Do this *before* we clone 'latest_foreign_def_path_hashes', since
-            // loading existing queries may cause us to create new DepNodes, which
-            // may in turn end up invoking `store_foreign_def_id_hash`
-            tcx.dep_graph.exec_cache_promotions(QueryCtxt::from_tcx(tcx));
-
             let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
             let hygiene_encode_context = HygieneEncodeContext::default();
 
@@ -564,7 +575,7 @@ fn load_indexed<'tcx, T>(
         })
     }
 
-    fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+    fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T>(
         &'sess self,
         tcx: TyCtxt<'tcx>,
         pos: AbsoluteBytePos,
@@ -575,9 +586,10 @@ fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
     {
         let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
 
+        let serialized_data = self.serialized_data.read();
         let mut decoder = CacheDecoder {
             tcx,
-            opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
+            opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
             source_map: self.source_map,
             cnum_map,
             file_index_to_file: &self.file_index_to_file,
index 60573968361203330f30e8f77c33ec89f8d15c81..c0b52d21fa639c293987ce4779a9158e9f261d53 100644 (file)
@@ -1999,9 +1999,8 @@ fn smart_resolve_path_fragment(
                         let item_span =
                             path.iter().last().map_or(span, |segment| segment.ident.span);
 
-                        let mut hm = self.r.session.confused_type_with_std_module.borrow_mut();
-                        hm.insert(item_span, span);
-                        hm.insert(span, span);
+                        self.r.confused_type_with_std_module.insert(item_span, span);
+                        self.r.confused_type_with_std_module.insert(span, span);
                     }
                 }
 
index 152d34fd63558df8e2c8caac358cae5b6f7f8608..6d2961db9e3dace832a4e86ef6e3663148d7fbb3 100644 (file)
@@ -1038,6 +1038,7 @@ pub struct Resolver<'a> {
     /// A list of proc macro LocalDefIds, written out in the order in which
     /// they are declared in the static array generated by proc_macro_harness.
     proc_macros: Vec<NodeId>,
+    confused_type_with_std_module: FxHashMap<Span, Span>,
 }
 
 /// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1404,6 +1405,7 @@ pub fn new(
             main_def: Default::default(),
             trait_impls: Default::default(),
             proc_macros: Default::default(),
+            confused_type_with_std_module: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1447,6 +1449,7 @@ pub fn into_outputs(self) -> ResolverOutputs {
         let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
         let glob_map = self.glob_map;
         let main_def = self.main_def;
+        let confused_type_with_std_module = self.confused_type_with_std_module;
         ResolverOutputs {
             definitions,
             cstore: Box::new(self.crate_loader.into_cstore()),
@@ -1464,6 +1467,7 @@ pub fn into_outputs(self) -> ResolverOutputs {
             main_def,
             trait_impls: self.trait_impls,
             proc_macros,
+            confused_type_with_std_module,
         }
     }
 
@@ -1486,6 +1490,7 @@ pub fn clone_outputs(&self) -> ResolverOutputs {
             main_def: self.main_def.clone(),
             trait_impls: self.trait_impls.clone(),
             proc_macros,
+            confused_type_with_std_module: self.confused_type_with_std_module.clone(),
         }
     }
 
index 29068761d6d843849770cd1889ff57576628fc1c..3e99f4e29ef36ca8e46c2a5d61941d51a3bdbcfb 100644 (file)
@@ -693,7 +693,6 @@ fn process_trait(
                     (Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
                 }
                 hir::GenericBound::Outlives(..) => continue,
-                hir::GenericBound::Unsized(_) => continue,
             };
 
             if let Some(id) = def_id {
@@ -1122,7 +1121,7 @@ pub(crate) fn process_crate(&mut self, krate: &'tcx hir::Crate<'tcx>) {
                 attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
             },
         );
-        intravisit::walk_crate(self, krate);
+        self.tcx.hir().walk_toplevel_module(self);
     }
 
     fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
index 0f7db69fefefc779cb66adc8035bb8a330dfb45f..c71595ab57e7224ab60699e8bf4caf698827bc8b 100644 (file)
@@ -183,10 +183,6 @@ pub struct Session {
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
-    /// Mapping from ident span to path span for paths that don't exist as written, but that
-    /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
-    pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
-
     /// Tracks the current behavior of the CTFE engine when an error occurs.
     /// Options range from returning the error without a backtrace to returning an error
     /// and immediately printing the backtrace to stderr.
@@ -1313,7 +1309,6 @@ pub fn build_session(
         print_fuel,
         jobserver: jobserver::client(),
         driver_lint_caps,
-        confused_type_with_std_module: Lock::new(Default::default()),
         ctfe_backtrace,
         miri_unleashed_features: Lock::new(Default::default()),
         asm_arch,
index 820399943f0afc91f62b36e38e0c5781bc549352..b0ecd117dd20e89b4016bcb6660cfc9cb19e9e9a 100644 (file)
@@ -13,7 +13,6 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::json::{Json, ToJson};
-use rustc_span::Span;
 
 pub mod call;
 
@@ -1173,46 +1172,6 @@ fn deref(&self) -> &&'a Layout {
     }
 }
 
-/// Trait for context types that can compute layouts of things.
-pub trait LayoutOf<'a>: Sized {
-    type Ty: TyAbiInterface<'a, Self>;
-    type TyAndLayout: MaybeResult<TyAndLayout<'a, Self::Ty>>;
-
-    fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
-    fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
-        self.layout_of(ty)
-    }
-}
-
-pub trait MaybeResult<T> {
-    type Error;
-
-    fn from(x: Result<T, Self::Error>) -> Self;
-    fn to_result(self) -> Result<T, Self::Error>;
-}
-
-impl<T> MaybeResult<T> for T {
-    type Error = !;
-
-    fn from(Ok(x): Result<T, Self::Error>) -> Self {
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        Ok(self)
-    }
-}
-
-impl<T, E> MaybeResult<T> for Result<T, E> {
-    type Error = E;
-
-    fn from(x: Result<T, Self::Error>) -> Self {
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        self
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
     /// Most general case, we know no restrictions to tell LLVM.
index db3432b01422fabe81afa2654993521cb3672be6..0d3fd748645edb266980aa635a32a72f011529d5 100644 (file)
@@ -1244,7 +1244,7 @@ fn report_closure_arg_mismatch(
             let sig = if let ty::Tuple(inputs) = inputs.kind() {
                 tcx.mk_fn_sig(
                     inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
@@ -1252,7 +1252,7 @@ fn report_closure_arg_mismatch(
             } else {
                 tcx.mk_fn_sig(
                     std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
index 17a4184c3c9ef92d734ce676477ad4e747a3340a..44c675243838a11e1213f6f5131af5edc5803db0 100644 (file)
@@ -625,6 +625,31 @@ fn dump_vtable_entries<'tcx>(
     tcx.sess.struct_span_err(sp, &msg).emit();
 }
 
+fn own_existential_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+) -> &'tcx [DefId] {
+    let trait_methods = tcx
+        .associated_items(trait_ref.def_id())
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Fn);
+    // Now list each method's DefId (for within its trait).
+    let own_entries = trait_methods.filter_map(move |trait_method| {
+        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+        let def_id = trait_method.def_id;
+
+        // Some methods cannot be called on an object; skip those.
+        if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+            debug!("own_existential_vtable_entry: not vtable safe");
+            return None;
+        }
+
+        Some(def_id)
+    });
+
+    tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
 /// Given a trait `trait_ref`, iterates the vtable entries
 /// that come from `trait_ref`, including its supertraits.
 fn vtable_entries<'tcx>(
@@ -641,21 +666,15 @@ fn vtable_entries<'tcx>(
                 entries.extend(COMMON_VTABLE_ENTRIES);
             }
             VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                let trait_methods = tcx
-                    .associated_items(trait_ref.def_id())
-                    .in_definition_order()
-                    .filter(|item| item.kind == ty::AssocKind::Fn);
-                // Now list each method's DefId and InternalSubsts (for within its trait).
-                // If the method can never be called from this object, produce `Vacant`.
-                let own_entries = trait_methods.map(move |trait_method| {
-                    debug!("vtable_entries: trait_method={:?}", trait_method);
-                    let def_id = trait_method.def_id;
-
-                    // Some methods cannot be called on an object; skip those.
-                    if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                        debug!("vtable_entries: not vtable safe");
-                        return VtblEntry::Vacant;
-                    }
+                let existential_trait_ref = trait_ref
+                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+                // Lookup the shape of vtable for the trait.
+                let own_existential_entries =
+                    tcx.own_existential_vtable_entries(existential_trait_ref);
+
+                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+                    debug!("vtable_entries: trait_method={:?}", def_id);
 
                     // The method may have some early-bound lifetimes; add regions for those.
                     let substs = trait_ref.map_bound(|trait_ref| {
@@ -804,6 +823,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+        own_existential_vtable_entries,
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
index fd94f9f799847496580e1d330d1349555a195308..b108d85bb20c9afc2184fab8be73133fc8d05289 100644 (file)
@@ -285,15 +285,10 @@ pub fn upcast_choices(
 /// that come from `trait_ref`, excluding its supertraits. Used in
 /// computing the vtable base for an upcast trait of a trait object.
 pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-    let mut entries = 0;
-    // Count number of methods and add them to the total offset.
-    // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
-        if trait_item.kind == ty::AssocKind::Fn {
-            entries += 1;
-        }
-    }
-    entries
+    let existential_trait_ref =
+        trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+    let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
+    tcx.own_existential_vtable_entries(existential_trait_ref).len()
 }
 
 /// Given an upcast trait object described by `object`, returns the
@@ -304,22 +299,21 @@ pub fn get_vtable_index_of_object_method<N>(
     object: &super::ImplSourceObjectData<'tcx, N>,
     method_def_id: DefId,
 ) -> usize {
+    let existential_trait_ref = object
+        .upcast_trait_ref
+        .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+    let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
     // Count number of methods preceding the one we are selecting and
     // add them to the total offset.
-    // Skip over associated types and constants, as those aren't stored in the vtable.
-    let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
-        if trait_item.def_id == method_def_id {
-            // The item with the ID we were given really ought to be a method.
-            assert_eq!(trait_item.kind, ty::AssocKind::Fn);
-            return entries;
-        }
-        if trait_item.kind == ty::AssocKind::Fn {
-            entries += 1;
-        }
-    }
-
-    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+    let index = tcx
+        .own_existential_vtable_entries(existential_trait_ref)
+        .iter()
+        .copied()
+        .position(|def_id| def_id == method_def_id)
+        .unwrap_or_else(|| {
+            bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+        });
+    object.vtable_base + index
 }
 
 pub fn closure_trait_ref_and_return_type(
index c405bbe2d1f53abb2193df1b8a478db40843ced5..d9ce169efc15ca49d8de63606490a637023e317e 100644 (file)
@@ -363,10 +363,11 @@ pub enum IntVarValue {
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub struct FloatVarValue(pub FloatTy);
 
-/// A **ty**pe **v**ariable **ID**.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-pub struct TyVid {
-    pub index: u32,
+rustc_index::newtype_index! {
+    /// A **ty**pe **v**ariable **ID**.
+    pub struct TyVid {
+        DEBUG_FORMAT = "_#{}t"
+    }
 }
 
 /// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
@@ -422,10 +423,10 @@ pub enum InferTy {
 impl UnifyKey for TyVid {
     type Value = ();
     fn index(&self) -> u32 {
-        self.index
+        self.as_u32()
     }
     fn from_index(i: u32) -> TyVid {
-        TyVid { index: i }
+        TyVid::from_u32(i)
     }
     fn tag() -> &'static str {
         "TyVid"
@@ -558,7 +559,7 @@ impl<CTX> HashStable<CTX> for InferTy {
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         use InferTy::*;
         match self {
-            TyVar(v) => v.index.hash_stable(ctx, hasher),
+            TyVar(v) => v.as_u32().hash_stable(ctx, hasher),
             IntVar(v) => v.index.hash_stable(ctx, hasher),
             FloatVar(v) => v.index.hash_stable(ctx, hasher),
             FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
@@ -587,12 +588,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl fmt::Debug for TyVid {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "_#{}t", self.index)
-    }
-}
-
 impl fmt::Debug for IntVid {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "_#{}i", self.index)
index 059e0cadd190cf649cf092fe4a291e48e6ebca11..51bb09e4c54ba29bebcf1a8356bb01a9a6fc9587 100644 (file)
@@ -111,11 +111,6 @@ fn projected_ty_from_poly_trait_ref(
     fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span);
 }
 
-pub enum SizedByDefault {
-    Yes,
-    No,
-}
-
 #[derive(Debug)]
 struct ConvertedBinding<'a, 'tcx> {
     hir_id: hir::HirId,
@@ -698,6 +693,61 @@ pub fn instantiate_mono_trait_ref(
         )
     }
 
+    fn instantiate_poly_trait_ref_inner(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+        binding_span: Option<Span>,
+        constness: ty::BoundConstness,
+        bounds: &mut Bounds<'tcx>,
+        speculative: bool,
+        trait_ref_span: Span,
+        trait_def_id: DefId,
+        trait_segment: &hir::PathSegment<'_>,
+        args: &GenericArgs<'_>,
+        infer_args: bool,
+        self_ty: Ty<'tcx>,
+    ) -> GenericArgCountResult {
+        let (substs, arg_count) = self.create_substs_for_ast_path(
+            trait_ref_span,
+            trait_def_id,
+            &[],
+            trait_segment,
+            args,
+            infer_args,
+            Some(self_ty),
+        );
+
+        let tcx = self.tcx();
+        let bound_vars = tcx.late_bound_vars(hir_id);
+        debug!(?bound_vars);
+
+        let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
+
+        let poly_trait_ref =
+            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
+
+        debug!(?poly_trait_ref, ?assoc_bindings);
+        bounds.trait_bounds.push((poly_trait_ref, span, constness));
+
+        let mut dup_bindings = FxHashMap::default();
+        for binding in &assoc_bindings {
+            // Specify type to assert that error was already reported in `Err` case.
+            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
+                hir_id,
+                poly_trait_ref,
+                binding,
+                bounds,
+                speculative,
+                &mut dup_bindings,
+                binding_span.unwrap_or(binding.span),
+            );
+            // Okay to ignore `Err` because of `ErrorReported` (see above).
+        }
+
+        arg_count
+    }
+
     /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
     /// a full trait reference. The resulting trait reference is returned. This may also generate
     /// auxiliary bounds, which are added to `bounds`.
@@ -718,7 +768,7 @@ pub fn instantiate_mono_trait_ref(
     /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly,
     /// however.
     #[tracing::instrument(level = "debug", skip(self, span, constness, bounds, speculative))]
-    pub fn instantiate_poly_trait_ref(
+    pub(crate) fn instantiate_poly_trait_ref(
         &self,
         trait_ref: &hir::TraitRef<'_>,
         span: Span,
@@ -727,48 +777,34 @@ pub fn instantiate_poly_trait_ref(
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
     ) -> GenericArgCountResult {
+        let hir_id = trait_ref.hir_ref_id;
+        let binding_span = None;
+        let trait_ref_span = trait_ref.path.span;
         let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+        let trait_segment = trait_ref.path.segments.last().unwrap();
+        let args = trait_segment.args();
+        let infer_args = trait_segment.infer_args;
 
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
+        self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
 
-        let tcx = self.tcx();
-        let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
-        debug!(?bound_vars);
-
-        let (substs, arg_count) = self.create_substs_for_ast_trait_ref(
-            trait_ref.path.span,
+        self.instantiate_poly_trait_ref_inner(
+            hir_id,
+            span,
+            binding_span,
+            constness,
+            bounds,
+            speculative,
+            trait_ref_span,
             trait_def_id,
+            trait_segment,
+            args,
+            infer_args,
             self_ty,
-            trait_ref.path.segments.last().unwrap(),
-        );
-        let assoc_bindings = self
-            .create_assoc_bindings_for_generic_args(trait_ref.path.segments.last().unwrap().args());
-
-        let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-
-        debug!(?poly_trait_ref, ?assoc_bindings);
-        bounds.trait_bounds.push((poly_trait_ref, span, constness));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in &assoc_bindings {
-            // Specify type to assert that error was already reported in `Err` case.
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                trait_ref.hir_ref_id,
-                poly_trait_ref,
-                binding,
-                bounds,
-                speculative,
-                &mut dup_bindings,
-                binding.span,
-            );
-            // Okay to ignore `Err` because of `ErrorReported` (see above).
-        }
-
-        arg_count
+        )
     }
 
-    pub fn instantiate_lang_item_trait_ref(
+    pub(crate) fn instantiate_lang_item_trait_ref(
         &self,
         lang_item: hir::LangItem,
         span: Span,
@@ -777,36 +813,28 @@ pub fn instantiate_lang_item_trait_ref(
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
     ) {
+        let binding_span = Some(span);
+        let constness = ty::BoundConstness::NotConst;
+        let speculative = false;
+        let trait_ref_span = span;
         let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span));
+        let trait_segment = &hir::PathSegment::invalid();
+        let infer_args = false;
 
-        let (substs, _) = self.create_substs_for_ast_path(
+        self.instantiate_poly_trait_ref_inner(
+            hir_id,
             span,
+            binding_span,
+            constness,
+            bounds,
+            speculative,
+            trait_ref_span,
             trait_def_id,
-            &[],
-            &hir::PathSegment::invalid(),
+            trait_segment,
             args,
-            false,
-            Some(self_ty),
+            infer_args,
+            self_ty,
         );
-        let assoc_bindings = self.create_assoc_bindings_for_generic_args(args);
-        let tcx = self.tcx();
-        let bound_vars = tcx.late_bound_vars(hir_id);
-        let poly_trait_ref =
-            ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-        bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst));
-
-        let mut dup_bindings = FxHashMap::default();
-        for binding in assoc_bindings {
-            let _: Result<_, ErrorReported> = self.add_predicates_for_ast_type_binding(
-                hir_id,
-                poly_trait_ref,
-                &binding,
-                bounds,
-                false,
-                &mut dup_bindings,
-                span,
-            );
-        }
     }
 
     fn ast_path_to_mono_trait_ref(
@@ -853,46 +881,76 @@ fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: I
             .is_some()
     }
 
-    // Returns `true` if a bounds list includes `?Sized`.
-    pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bool {
+    // Sets `implicitly_sized` to true on `Bounds` if necessary
+    pub(crate) fn add_implicitly_sized<'hir>(
+        &self,
+        bounds: &mut Bounds<'hir>,
+        ast_bounds: &'hir [hir::GenericBound<'hir>],
+        self_ty_where_predicates: Option<(hir::HirId, &'hir [hir::WherePredicate<'hir>])>,
+        span: Span,
+    ) {
         let tcx = self.tcx();
 
         // Try to find an unbound in bounds.
         let mut unbound = None;
-        for ab in ast_bounds {
-            if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
-                if unbound.is_none() {
-                    unbound = Some(&ptr.trait_ref);
-                } else {
-                    tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+        let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
+            for ab in ast_bounds {
+                if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
+                    if unbound.is_none() {
+                        unbound = Some(&ptr.trait_ref);
+                    } else {
+                        tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+                    }
                 }
             }
-        }
-
-        let kind_id = tcx.lang_items().require(LangItem::Sized);
-        match unbound {
-            Some(tpb) => {
-                // FIXME(#8559) currently requires the unbound to be built-in.
-                if let Ok(kind_id) = kind_id {
-                    if tpb.path.res != Res::Def(DefKind::Trait, kind_id) {
-                        tcx.sess.span_warn(
-                            span,
-                            "default bound relaxed for a type parameter, but \
-                             this does nothing because the given bound is not \
-                             a default; only `?Sized` is supported",
-                        );
-                        return false;
+        };
+        search_bounds(ast_bounds);
+        if let Some((self_ty, where_clause)) = self_ty_where_predicates {
+            let self_ty_def_id = tcx.hir().local_def_id(self_ty).to_def_id();
+            for clause in where_clause {
+                match clause {
+                    hir::WherePredicate::BoundPredicate(pred) => {
+                        match pred.bounded_ty.kind {
+                            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
+                                Res::Def(DefKind::TyParam, def_id) if def_id == self_ty_def_id => {}
+                                _ => continue,
+                            },
+                            _ => continue,
+                        }
+                        search_bounds(pred.bounds);
                     }
+                    _ => {}
                 }
             }
-            _ if kind_id.is_ok() => {
-                return false;
+        }
+
+        let sized_def_id = tcx.lang_items().require(LangItem::Sized);
+        match (&sized_def_id, unbound) {
+            (Ok(sized_def_id), Some(tpb))
+                if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
+            {
+                // There was in fact a `?Sized` bound, return without doing anything
+                return;
+            }
+            (_, Some(_)) => {
+                // There was a `?Trait` bound, but it was not `?Sized`; warn.
+                tcx.sess.span_warn(
+                    span,
+                    "default bound relaxed for a type parameter, but \
+                        this does nothing because the given bound is not \
+                        a default; only `?Sized` is supported",
+                );
+                // Otherwise, add implicitly sized if `Sized` is available.
             }
+            _ => {
+                // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
+            }
+        }
+        if sized_def_id.is_err() {
             // No lang item for `Sized`, so we can't add it as a bound.
-            None => {}
+            return;
         }
-
-        true
+        bounds.implicitly_sized = Some(span);
     }
 
     /// This helper takes a *converted* parameter type (`param_ty`)
@@ -910,46 +968,43 @@ pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound<'_>], span: Span) -> bo
     /// **A note on binders:** there is an implied binder around
     /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref`
     /// for more details.
-    #[tracing::instrument(level = "debug", skip(self, bounds))]
-    fn add_bounds(
+    #[tracing::instrument(level = "debug", skip(self, ast_bounds, bounds))]
+    pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>(
         &self,
         param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
+        ast_bounds: I,
         bounds: &mut Bounds<'tcx>,
         bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     ) {
         for ast_bound in ast_bounds {
-            match *ast_bound {
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
-                    self.instantiate_poly_trait_ref(
-                        &b.trait_ref,
-                        b.span,
-                        ty::BoundConstness::NotConst,
+            match ast_bound {
+                hir::GenericBound::Trait(poly_trait_ref, modifier) => {
+                    let constness = match modifier {
+                        hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
+                        hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+                        hir::TraitBoundModifier::Maybe => continue,
+                    };
+
+                    let _ = self.instantiate_poly_trait_ref(
+                        &poly_trait_ref.trait_ref,
+                        poly_trait_ref.span,
+                        constness,
                         param_ty,
                         bounds,
                         false,
                     );
                 }
-                hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => {
-                    self.instantiate_poly_trait_ref(
-                        &b.trait_ref,
-                        b.span,
-                        ty::BoundConstness::ConstIfConst,
-                        param_ty,
-                        bounds,
-                        false,
+                &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
+                    self.instantiate_lang_item_trait_ref(
+                        lang_item, span, hir_id, args, param_ty, bounds,
                     );
                 }
-                hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe)
-                | hir::GenericBound::Unsized(_) => {}
-                hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => self
-                    .instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
-                    ),
-                hir::GenericBound::Outlives(ref l) => bounds.region_bounds.push((
-                    ty::Binder::bind_with_vars(self.ast_region_to_region(l, None), bound_vars),
-                    l.span,
-                )),
+                hir::GenericBound::Outlives(lifetime) => {
+                    let region = self.ast_region_to_region(lifetime, None);
+                    bounds
+                        .region_bounds
+                        .push((ty::Binder::bind_with_vars(region, bound_vars), lifetime.span));
+                }
             }
         }
     }
@@ -970,24 +1025,20 @@ fn add_bounds(
     /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`.
     ///
     /// `span` should be the declaration size of the parameter.
-    pub fn compute_bounds(
+    pub(crate) fn compute_bounds(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
     ) -> Bounds<'tcx> {
-        self.compute_bounds_inner(param_ty, &ast_bounds, sized_by_default, span)
+        self.compute_bounds_inner(param_ty, &ast_bounds)
     }
 
     /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
     /// named `assoc_name` into ty::Bounds. Ignore the rest.
-    pub fn compute_bounds_that_match_assoc_type(
+    pub(crate) fn compute_bounds_that_match_assoc_type(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
         assoc_name: Ident,
     ) -> Bounds<'tcx> {
         let mut result = Vec::new();
@@ -1002,25 +1053,17 @@ pub fn compute_bounds_that_match_assoc_type(
             }
         }
 
-        self.compute_bounds_inner(param_ty, &result, sized_by_default, span)
+        self.compute_bounds_inner(param_ty, &result)
     }
 
     fn compute_bounds_inner(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
-        sized_by_default: SizedByDefault,
-        span: Span,
     ) -> Bounds<'tcx> {
         let mut bounds = Bounds::default();
 
-        self.add_bounds(param_ty, ast_bounds, &mut bounds, ty::List::empty());
-
-        bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default {
-            if !self.is_unsized(ast_bounds, span) { Some(span) } else { None }
-        } else {
-            None
-        };
+        self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
 
         bounds
     }
@@ -1212,7 +1255,7 @@ fn add_predicates_for_ast_type_binding(
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
                 let param_ty = tcx.mk_ty(ty::Projection(projection_ty.skip_binder()));
-                self.add_bounds(param_ty, ast_bounds, bounds, candidate.bound_vars());
+                self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
             }
         }
         Ok(())
@@ -1495,9 +1538,8 @@ fn report_ambiguous_associated_type(
         let mut err = struct_span_err!(self.tcx().sess, span, E0223, "ambiguous associated type");
         if let (true, Ok(snippet)) = (
             self.tcx()
-                .sess
+                .resolutions(())
                 .confused_type_with_std_module
-                .borrow()
                 .keys()
                 .any(|full_span| full_span.contains(span)),
             self.tcx().sess.source_map().span_to_snippet(span),
index 64594a82ec0b6e5dd0838a1e492a81175d205e97..d578fac4cdb227d0ed1ce86dc250d1cb24a18969 100644 (file)
@@ -1236,6 +1236,7 @@ fn check_expr_struct(
             variant,
             fields,
             base_expr.is_none(),
+            expr.span,
         );
         if let Some(base_expr) = base_expr {
             // If check_expr_struct_fields hit an error, do not attempt to populate
@@ -1283,6 +1284,7 @@ fn check_expr_struct_fields(
         variant: &'tcx ty::VariantDef,
         ast_fields: &'tcx [hir::ExprField<'tcx>],
         check_completeness: bool,
+        expr_span: Span,
     ) -> bool {
         let tcx = self.tcx;
 
@@ -1334,7 +1336,9 @@ fn check_expr_struct_fields(
                         ident,
                     });
                 } else {
-                    self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span);
+                    self.report_unknown_field(
+                        adt_ty, variant, field, ast_fields, kind_name, expr_span,
+                    );
                 }
 
                 tcx.ty_error()
@@ -1467,7 +1471,7 @@ fn report_unknown_field(
         field: &hir::ExprField<'_>,
         skip_fields: &[hir::ExprField<'_>],
         kind_name: &str,
-        ty_span: Span,
+        expr_span: Span,
     ) {
         if variant.is_recovered() {
             self.set_tainted_by_errors();
@@ -1510,8 +1514,8 @@ fn report_unknown_field(
                         ),
                     );
                     err.span_label(field.ident.span, "field does not exist");
-                    err.span_suggestion(
-                        ty_span,
+                    err.span_suggestion_verbose(
+                        expr_span,
                         &format!(
                             "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
                             adt = ty,
@@ -1528,8 +1532,8 @@ fn report_unknown_field(
                 _ => {
                     err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
                     err.span_label(field.ident.span, "field does not exist");
-                    err.span_suggestion(
-                        ty_span,
+                    err.span_suggestion_verbose(
+                        expr_span,
                         &format!(
                             "`{adt}` is a tuple {kind_name}, use the appropriate syntax",
                             adt = ty,
index 17e0c42440c219d35a0df6014ffbdfe07ad4de12..9748c0835bf12e29c4e6463208899f8f4cfe2fd9 100644 (file)
@@ -945,7 +945,7 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Spa
                     Ok(s) if s.starts_with('<') => sugg,
                     _ => format!("<{}>", sugg),
                 };
-                let replace = String::from("use `dyn`");
+                let sugg_label = "use `dyn`";
                 if self.sess().edition() >= Edition::Edition2021 {
                     let mut err = rustc_errors::struct_span_err!(
                         self.sess(),
@@ -956,8 +956,8 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Spa
                     );
                     err.span_suggestion(
                         self_ty.span,
-                        &sugg,
-                        replace,
+                        sugg_label,
+                        sugg,
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -968,7 +968,7 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Spa
                         self_ty.span,
                         |lint| {
                             let mut db = lint.build(msg);
-                            db.span_suggestion(self_ty.span, &replace, sugg, app);
+                            db.span_suggestion(self_ty.span, sugg_label, sugg, app);
                             db.emit()
                         },
                     );
index afe274a2a796e11e8b2c39d911eac04dab0b2fba..a746ad7ad4bc722b63c1d05287547301a87c87a6 100644 (file)
@@ -6,8 +6,7 @@
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
-use rustc_hir::intravisit;
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -435,7 +434,7 @@ pub fn report_method_error(
                             }
                         }
                         if let Some(span) =
-                            tcx.sess.confused_type_with_std_module.borrow().get(&span)
+                            tcx.resolutions(()).confused_type_with_std_module.get(&span)
                         {
                             if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
                                 err.span_suggestion(
@@ -743,7 +742,7 @@ fn report_function<T: std::fmt::Display>(
                                 let projection_ty = pred.skip_binder().projection_ty;
 
                                 let substs_with_infer_self = tcx.mk_substs(
-                                    iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
+                                    iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
                                         .chain(projection_ty.substs.iter().skip(1)),
                                 );
 
@@ -830,6 +829,8 @@ trait bound{s}",
                         err.note(&format!(
                             "the following trait bounds were not satisfied:\n{bound_list}"
                         ));
+                        self.suggest_derive(&mut err, &unsatisfied_predicates);
+
                         unsatisfied_bounds = true;
                     }
                 }
@@ -972,6 +973,85 @@ trait bound{s}",
         None
     }
 
+    fn suggest_derive(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        unsatisfied_predicates: &Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
+    ) {
+        let derivables = [
+            sym::Eq,
+            sym::PartialEq,
+            sym::Ord,
+            sym::PartialOrd,
+            sym::Clone,
+            sym::Copy,
+            sym::Hash,
+            sym::Default,
+            sym::debug_trait,
+        ];
+        let mut derives = unsatisfied_predicates
+            .iter()
+            .filter_map(|(pred, _)| {
+                let trait_pred =
+                    if let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() {
+                        trait_pred
+                    } else {
+                        return None;
+                    };
+                let trait_ref = trait_pred.trait_ref;
+                let adt_def = if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() {
+                    adt_def
+                } else {
+                    return None;
+                };
+                if adt_def.did.is_local() {
+                    let diagnostic_items = self.tcx.diagnostic_items(trait_ref.def_id.krate);
+                    return derivables.iter().find_map(|trait_derivable| {
+                        let item_def_id =
+                            if let Some(item_def_id) = diagnostic_items.get(trait_derivable) {
+                                item_def_id
+                            } else {
+                                return None;
+                            };
+                        if item_def_id == &trait_pred.trait_ref.def_id
+                            && !(adt_def.is_enum() && *trait_derivable == sym::Default)
+                        {
+                            return Some((
+                                format!("{}", trait_ref.self_ty()),
+                                self.tcx.def_span(adt_def.did),
+                                format!("{}", trait_ref.print_only_trait_path()),
+                            ));
+                        }
+                        None
+                    });
+                }
+                None
+            })
+            .collect::<Vec<(String, Span, String)>>();
+        derives.sort();
+        let derives_grouped = derives.into_iter().fold(
+            Vec::<(String, Span, String)>::new(),
+            |mut acc, (self_name, self_span, trait_name)| {
+                if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() {
+                    if acc_self_name == &self_name {
+                        traits.push_str(format!(", {}", trait_name).as_str());
+                        return acc;
+                    }
+                }
+                acc.push((self_name, self_span, trait_name));
+                acc
+            },
+        );
+        for (self_name, self_span, traits) in &derives_grouped {
+            err.span_suggestion_verbose(
+                self_span.shrink_to_lo(),
+                &format!("consider annotating `{}` with `#[derive({})]`", self_name, traits),
+                format!("#[derive({})]\n", traits),
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
     /// Print out the type for use in value namespace.
     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
         match ty.kind() {
@@ -1011,9 +1091,7 @@ fn suggest_use_candidates(
         candidates: Vec<DefId>,
     ) {
         let module_did = self.tcx.parent_module(self.body_id);
-        let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
-        let krate = self.tcx.hir().krate();
-        let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
+        let (span, found_use) = find_use_placement(self.tcx, module_did);
         if let Some(span) = span {
             let path_strings = candidates.iter().map(|did| {
                 // Produce an additional newline to separate the new use statement
@@ -1606,64 +1684,38 @@ pub fn provide(providers: &mut ty::query::Providers) {
     providers.all_traits = compute_all_traits;
 }
 
-struct UsePlacementFinder<'tcx> {
-    target_module: hir::HirId,
-    span: Option<Span>,
-    found_use: bool,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl UsePlacementFinder<'tcx> {
-    fn check(
-        tcx: TyCtxt<'tcx>,
-        krate: &'tcx hir::Crate<'tcx>,
-        target_module: hir::HirId,
-    ) -> (Option<Span>, bool) {
-        let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
-        intravisit::walk_crate(&mut finder, krate);
-        (finder.span, finder.found_use)
-    }
-}
-
-impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
-    fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
-        if self.span.is_some() {
-            return;
-        }
-        if hir_id != self.target_module {
-            intravisit::walk_mod(self, module, hir_id);
-            return;
-        }
-        // Find a `use` statement.
-        for &item_id in module.item_ids {
-            let item = self.tcx.hir().item(item_id);
-            match item.kind {
-                hir::ItemKind::Use(..) => {
-                    // Don't suggest placing a `use` before the prelude
-                    // import or other generated ones.
-                    if !item.span.from_expansion() {
-                        self.span = Some(item.span.shrink_to_lo());
-                        self.found_use = true;
-                        return;
-                    }
+fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {
+    let mut span = None;
+    let mut found_use = false;
+    let (module, _, _) = tcx.hir().get_module(target_module);
+
+    // Find a `use` statement.
+    for &item_id in module.item_ids {
+        let item = tcx.hir().item(item_id);
+        match item.kind {
+            hir::ItemKind::Use(..) => {
+                // Don't suggest placing a `use` before the prelude
+                // import or other generated ones.
+                if !item.span.from_expansion() {
+                    span = Some(item.span.shrink_to_lo());
+                    found_use = true;
+                    break;
                 }
-                // Don't place `use` before `extern crate`...
-                hir::ItemKind::ExternCrate(_) => {}
-                // ...but do place them before the first other item.
-                _ => {
-                    if self.span.map_or(true, |span| item.span < span) {
-                        if !item.span.from_expansion() {
-                            self.span = Some(item.span.shrink_to_lo());
-                            // Don't insert between attributes and an item.
-                            let attrs = self.tcx.hir().attrs(item.hir_id());
-                            // Find the first attribute on the item.
-                            // FIXME: This is broken for active attributes.
-                            for attr in attrs {
-                                if !attr.span.is_dummy()
-                                    && self.span.map_or(true, |span| attr.span < span)
-                                {
-                                    self.span = Some(attr.span.shrink_to_lo());
-                                }
+            }
+            // Don't place `use` before `extern crate`...
+            hir::ItemKind::ExternCrate(_) => {}
+            // ...but do place them before the first other item.
+            _ => {
+                if span.map_or(true, |span| item.span < span) {
+                    if !item.span.from_expansion() {
+                        span = Some(item.span.shrink_to_lo());
+                        // Don't insert between attributes and an item.
+                        let attrs = tcx.hir().attrs(item.hir_id());
+                        // Find the first attribute on the item.
+                        // FIXME: This is broken for active attributes.
+                        for attr in attrs {
+                            if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) {
+                                span = Some(attr.span.shrink_to_lo());
                             }
                         }
                     }
@@ -1672,11 +1724,7 @@ fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirI
         }
     }
 
-    type Map = intravisit::ErasedMap<'tcx>;
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
+    (span, found_use)
 }
 
 fn print_disambiguation_help(
index 702f69a9fcf0ba2381c181d97a40fefb78d93f53..53b99a14f379d2450c5656eaf87f8ed99e58fa5a 100644 (file)
@@ -399,7 +399,14 @@ fn process_collected_capture_information(
                 }
             };
 
+            // This restriction needs to be applied after we have handled adjustments for `move`
+            // closures. We want to make sure any adjustment that might make us move the place into
+            // the closure gets handled.
+            let (place, capture_kind) =
+                restrict_precision_for_drop_types(self, place, capture_kind, usage_span);
+
             capture_info.capture_kind = capture_kind;
+
             let capture_info = if let Some(existing) = processed.get(&place) {
                 determine_capture_info(*existing, capture_info)
             } else {
@@ -626,7 +633,7 @@ fn perform_2229_migration_anaysis(
             self.tcx.struct_span_lint_hir(
                 lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
                 closure_hir_id,
-                closure_head_span,
+                 closure_head_span,
                 |lint| {
                     let mut diagnostics_builder = lint.build(
                         format!(
@@ -1852,6 +1859,31 @@ fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::H
         self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
     }
 }
+
+/// Rust doesn't permit moving fields out of a type that implements drop
+fn restrict_precision_for_drop_types<'a, 'tcx>(
+    fcx: &'a FnCtxt<'a, 'tcx>,
+    mut place: Place<'tcx>,
+    mut curr_mode: ty::UpvarCapture<'tcx>,
+    span: Span,
+) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+    let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty(), span);
+
+    if let (false, UpvarCapture::ByValue(..)) = (is_copy_type, curr_mode) {
+        for i in 0..place.projections.len() {
+            match place.ty_before_projection(i).kind() {
+                ty::Adt(def, _) if def.destructor(fcx.tcx).is_some() => {
+                    truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
+                    break;
+                }
+                _ => {}
+            }
+        }
+    }
+
+    (place, curr_mode)
+}
+
 /// Truncate `place` so that an `unsafe` block isn't required to capture it.
 /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture
 ///   them completely.
index 64120510e5624a5c7fbed86eb89d7250d790d4e4..3688fa05e038eb2948da4152ded88e55e01aabd5 100644 (file)
@@ -14,7 +14,7 @@
 //! At present, however, we do run collection across all items in the
 //! crate as a kind of pass. This should eventually be factored away.
 
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
 use crate::bounds::Bounds;
 use crate::check::intrinsic::intrinsic_operation_unsafety;
 use crate::constrained_generic_params as cgp;
@@ -1156,18 +1156,10 @@ fn super_predicates_that_define_assoc_type(
                 &icx,
                 self_param_ty,
                 &bounds,
-                SizedByDefault::No,
-                item.span,
                 assoc_name,
             )
         } else {
-            <dyn AstConv<'_>>::compute_bounds(
-                &icx,
-                self_param_ty,
-                &bounds,
-                SizedByDefault::No,
-                item.span,
-            )
+            <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, &bounds)
         };
 
         let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
@@ -2176,12 +2168,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
                 index += 1;
 
-                let sized = SizedByDefault::Yes;
-                let bounds = <dyn AstConv<'_>>::compute_bounds(
+                let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, param_ty, &param.bounds);
+                // Params are implicitly sized unless a `?Sized` bound is found
+                <dyn AstConv<'_>>::add_implicitly_sized(
                     &icx,
-                    param_ty,
+                    &mut bounds,
                     &param.bounds,
-                    sized,
+                    Some((param.hir_id, ast_generics.where_clause.predicates)),
                     param.span,
                 );
                 predicates.extend(bounds.predicates(tcx, param_ty));
@@ -2227,64 +2220,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     }
                 }
 
-                for bound in bound_pred.bounds.iter() {
-                    match bound {
-                        hir::GenericBound::Trait(poly_trait_ref, modifier) => {
-                            let constness = match modifier {
-                                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
-                                hir::TraitBoundModifier::MaybeConst => {
-                                    ty::BoundConstness::ConstIfConst
-                                }
-                                // We ignore `where T: ?Sized`, it is already part of
-                                // type parameter `T`.
-                                hir::TraitBoundModifier::Maybe => continue,
-                            };
-
-                            let mut bounds = Bounds::default();
-                            let _ = <dyn AstConv<'_>>::instantiate_poly_trait_ref(
-                                &icx,
-                                &poly_trait_ref.trait_ref,
-                                poly_trait_ref.span,
-                                constness,
-                                ty,
-                                &mut bounds,
-                                false,
-                            );
-                            predicates.extend(bounds.predicates(tcx, ty));
-                        }
-
-                        &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
-                            let mut bounds = Bounds::default();
-                            <dyn AstConv<'_>>::instantiate_lang_item_trait_ref(
-                                &icx,
-                                lang_item,
-                                span,
-                                hir_id,
-                                args,
-                                ty,
-                                &mut bounds,
-                            );
-                            predicates.extend(bounds.predicates(tcx, ty));
-                        }
-
-                        hir::GenericBound::Unsized(_) => {}
-
-                        hir::GenericBound::Outlives(lifetime) => {
-                            let region =
-                                <dyn AstConv<'_>>::ast_region_to_region(&icx, lifetime, None);
-                            predicates.insert((
-                                ty::Binder::bind_with_vars(
-                                    ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
-                                        ty, region,
-                                    )),
-                                    bound_vars,
-                                )
-                                .to_predicate(tcx),
-                                lifetime.span,
-                            ));
-                        }
-                    }
-                }
+                let mut bounds = Bounds::default();
+                <dyn AstConv<'_>>::add_bounds(
+                    &icx,
+                    ty,
+                    bound_pred.bounds.iter(),
+                    &mut bounds,
+                    bound_vars,
+                );
+                predicates.extend(bounds.predicates(tcx, ty));
             }
 
             hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -2498,45 +2442,14 @@ fn predicates_from_bound<'tcx>(
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-    match *bound {
-        hir::GenericBound::Trait(ref tr, modifier) => {
-            let constness = match modifier {
-                hir::TraitBoundModifier::Maybe => return vec![],
-                hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
-                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
-            };
-
-            let mut bounds = Bounds::default();
-            let _ = astconv.instantiate_poly_trait_ref(
-                &tr.trait_ref,
-                tr.span,
-                constness,
-                param_ty,
-                &mut bounds,
-                false,
-            );
-            bounds.predicates(astconv.tcx(), param_ty)
-        }
-        hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
-            let mut bounds = Bounds::default();
-            astconv.instantiate_lang_item_trait_ref(
-                lang_item,
-                span,
-                hir_id,
-                args,
-                param_ty,
-                &mut bounds,
-            );
-            bounds.predicates(astconv.tcx(), param_ty)
-        }
-        hir::GenericBound::Unsized(_) => vec![],
-        hir::GenericBound::Outlives(ref lifetime) => {
-            let region = astconv.ast_region_to_region(lifetime, None);
-            let pred = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region))
-                .to_predicate(astconv.tcx());
-            vec![(pred, lifetime.span)]
-        }
-    }
+    let mut bounds = Bounds::default();
+    astconv.add_bounds(
+        param_ty,
+        std::array::IntoIter::new([bound]),
+        &mut bounds,
+        ty::List::empty(),
+    );
+    bounds.predicates(astconv.tcx(), param_ty)
 }
 
 fn compute_sig_of_foreign_fn_decl<'tcx>(
index 1d08c4450afcfcb1595ab811ede3fc914ebdf411..2bc048ac8a0e9395fd69b79749c586cfcc9b9ac6 100644 (file)
@@ -1,5 +1,5 @@
 use super::ItemCtxt;
-use crate::astconv::{AstConv, SizedByDefault};
+use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
@@ -17,7 +17,7 @@
 fn associated_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     assoc_item_def_id: DefId,
-    bounds: &'tcx [hir::GenericBound<'tcx>],
+    ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     let item_ty = tcx.mk_projection(
@@ -25,13 +25,10 @@ fn associated_type_bounds<'tcx>(
         InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
     );
 
-    let bounds = <dyn AstConv<'_>>::compute_bounds(
-        &ItemCtxt::new(tcx, assoc_item_def_id),
-        item_ty,
-        &bounds,
-        SizedByDefault::Yes,
-        span,
-    );
+    let icx = ItemCtxt::new(tcx, assoc_item_def_id);
+    let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+    // Associated types are implicitly sized unless a `?Sized` bound is found
+    <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
 
     let trait_def_id = tcx.associated_item(assoc_item_def_id).container.id();
     let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local());
@@ -59,21 +56,18 @@ fn associated_type_bounds<'tcx>(
 fn opaque_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     opaque_def_id: DefId,
-    bounds: &'tcx [hir::GenericBound<'tcx>],
+    ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     ty::print::with_no_queries(|| {
         let item_ty =
             tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
 
-        let bounds = <dyn AstConv<'_>>::compute_bounds(
-            &ItemCtxt::new(tcx, opaque_def_id),
-            item_ty,
-            &bounds,
-            SizedByDefault::Yes,
-            span,
-        )
-        .predicates(tcx, item_ty);
+        let icx = ItemCtxt::new(tcx, opaque_def_id);
+        let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, &ast_bounds);
+        // Opaque types are implicitly sized unless a `?Sized` bound is found
+        <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, &ast_bounds, None, span);
+        let bounds = bounds.predicates(tcx, item_ty);
 
         debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(opaque_def_id), bounds);
 
index 41277b22da0e034281487848d107834f1f71e621..7f9afaae0eaa2675f8273aaf32af2ee7e9c5a53b 100644 (file)
@@ -691,7 +691,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     debug!("find_opaque_ty_constraints: scope={:?}", scope);
 
     if scope == hir::CRATE_HIR_ID {
-        intravisit::walk_crate(&mut locator, tcx.hir().krate());
+        tcx.hir().walk_toplevel_module(&mut locator);
     } else {
         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
         match tcx.hir().get(scope) {
index 920a5ca7db067891c871adc1173f2b56254cf7ff..c304f74884721a60d976eef7abe200e00999f68e 100644 (file)
@@ -54,6 +54,50 @@ pub fn $name(b: &mut Bencher) {
     };
 }
 
+macro_rules! map_from_iter_rand_bench {
+    ($name: ident, $n: expr, $map: ident) => {
+        #[bench]
+        pub fn $name(b: &mut Bencher) {
+            let n: usize = $n;
+            // setup
+            let mut rng = thread_rng();
+            let mut vec = Vec::with_capacity(n);
+
+            for _ in 0..n {
+                let i = rng.gen::<usize>() % n;
+                vec.push((i, i));
+            }
+
+            // measure
+            b.iter(|| {
+                let map: $map<_, _> = vec.iter().copied().collect();
+                black_box(map);
+            });
+        }
+    };
+}
+
+macro_rules! map_from_iter_seq_bench {
+    ($name: ident, $n: expr, $map: ident) => {
+        #[bench]
+        pub fn $name(b: &mut Bencher) {
+            let n: usize = $n;
+            // setup
+            let mut vec = Vec::with_capacity(n);
+
+            for i in 0..n {
+                vec.push((i, i));
+            }
+
+            // measure
+            b.iter(|| {
+                let map: $map<_, _> = vec.iter().copied().collect();
+                black_box(map);
+            });
+        }
+    };
+}
+
 macro_rules! map_find_rand_bench {
     ($name: ident, $n: expr, $map: ident) => {
         #[bench]
@@ -111,6 +155,12 @@ pub fn $name(b: &mut Bencher) {
 map_insert_seq_bench! {insert_seq_100,    100,    BTreeMap}
 map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap}
 
+map_from_iter_rand_bench! {from_iter_rand_100,    100,    BTreeMap}
+map_from_iter_rand_bench! {from_iter_rand_10_000, 10_000, BTreeMap}
+
+map_from_iter_seq_bench! {from_iter_seq_100,    100,    BTreeMap}
+map_from_iter_seq_bench! {from_iter_seq_10_000, 10_000, BTreeMap}
+
 map_find_rand_bench! {find_rand_100,    100,    BTreeMap}
 map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap}
 
diff --git a/library/alloc/src/collections/btree/dedup_sorted_iter.rs b/library/alloc/src/collections/btree/dedup_sorted_iter.rs
new file mode 100644 (file)
index 0000000..60bf83b
--- /dev/null
@@ -0,0 +1,47 @@
+use core::iter::Peekable;
+
+/// A iterator for deduping the key of a sorted iterator.
+/// When encountering the duplicated key, only the last key-value pair is yielded.
+///
+/// Used by [`BTreeMap::bulk_build_from_sorted_iter`].
+pub struct DedupSortedIter<K, V, I>
+where
+    I: Iterator<Item = (K, V)>,
+{
+    iter: Peekable<I>,
+}
+
+impl<K, V, I> DedupSortedIter<K, V, I>
+where
+    I: Iterator<Item = (K, V)>,
+{
+    pub fn new(iter: I) -> Self {
+        Self { iter: iter.peekable() }
+    }
+}
+
+impl<K, V, I> Iterator for DedupSortedIter<K, V, I>
+where
+    K: Eq,
+    I: Iterator<Item = (K, V)>,
+{
+    type Item = (K, V);
+
+    fn next(&mut self) -> Option<(K, V)> {
+        loop {
+            let next = match self.iter.next() {
+                Some(next) => next,
+                None => return None,
+            };
+
+            let peeked = match self.iter.peek() {
+                Some(peeked) => peeked,
+                None => return Some(next),
+            };
+
+            if next.0 != peeked.0 {
+                return Some(next);
+            }
+        }
+    }
+}
index 70a838a35f9d202b0af56357af0a4da9382d0536..501a604e7f76d037fdfbc23c21a22367816491c6 100644 (file)
@@ -1,3 +1,4 @@
+use crate::vec::Vec;
 use core::borrow::Borrow;
 use core::cmp::Ordering;
 use core::fmt::{self, Debug};
@@ -9,6 +10,7 @@
 use core::ptr;
 
 use super::borrow::DormantMutRef;
+use super::dedup_sorted_iter::DedupSortedIter;
 use super::navigate::{LazyLeafRange, LeafRange};
 use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root};
 use super::search::SearchResult::*;
@@ -1285,6 +1287,18 @@ pub fn into_keys(self) -> IntoKeys<K, V> {
     pub fn into_values(self) -> IntoValues<K, V> {
         IntoValues { inner: self.into_iter() }
     }
+
+    /// Makes a `BTreeMap` from a sorted iterator.
+    pub(crate) fn bulk_build_from_sorted_iter<I>(iter: I) -> Self
+    where
+        K: Ord,
+        I: Iterator<Item = (K, V)>,
+    {
+        let mut root = Root::new();
+        let mut length = 0;
+        root.bulk_push(DedupSortedIter::new(iter), &mut length);
+        BTreeMap { root: Some(root), length }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1909,9 +1923,15 @@ impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
-        let mut map = BTreeMap::new();
-        map.extend(iter);
-        map
+        let mut inputs: Vec<_> = iter.into_iter().collect();
+
+        if inputs.is_empty() {
+            return BTreeMap::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        inputs.sort_by(|a, b| a.0.cmp(&b.0));
+        BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter())
     }
 }
 
@@ -2020,8 +2040,14 @@ fn index(&self, key: &Q) -> &V {
     /// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into();
     /// assert_eq!(map1, map2);
     /// ```
-    fn from(arr: [(K, V); N]) -> Self {
-        core::array::IntoIter::new(arr).collect()
+    fn from(mut arr: [(K, V); N]) -> Self {
+        if N == 0 {
+            return BTreeMap::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        arr.sort_by(|a, b| a.0.cmp(&b.0));
+        BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr))
     }
 }
 
index f74172c7d976fb50f4921cb9f772f51466822ae4..9571b3d594df8cf6c410a663388c6825d099c82d 100644 (file)
@@ -1,5 +1,6 @@
 mod append;
 mod borrow;
+mod dedup_sorted_iter;
 mod fix;
 pub mod map;
 mod mem;
index 8f6a2ec9ebd1ff002ee79cf8b7497cbcc9b3e347..a73f00a083af333b80e395e992c4bb3c9e2d9f51 100644 (file)
@@ -1663,7 +1663,7 @@ pub trait BorrowType {
         const PERMITS_TRAVERSAL: bool = true;
     }
     impl BorrowType for Owned {
-        // Traversal isn't needede, it happens using the result of `borrow_mut`.
+        // Traversal isn't needed, it happens using the result of `borrow_mut`.
         // By disabling traversal, and only creating new references to roots,
         // we know that every reference of the `Owned` type is to a root node.
         const PERMITS_TRAVERSAL: bool = false;
index ff0db22e0cc2d48519bbfac8ffb37f4752cce3a0..c664e201aec544067d825faf5633b9c90a253020 100644 (file)
@@ -1,6 +1,7 @@
 // This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface
 // to TreeMap
 
+use crate::vec::Vec;
 use core::borrow::Borrow;
 use core::cmp::Ordering::{Equal, Greater, Less};
 use core::cmp::{max, min};
@@ -1056,9 +1057,17 @@ pub const fn is_empty(&self) -> bool {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
-        let mut set = BTreeSet::new();
-        set.extend(iter);
-        set
+        let mut inputs: Vec<_> = iter.into_iter().collect();
+
+        if inputs.is_empty() {
+            return BTreeSet::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        inputs.sort();
+        let iter = inputs.into_iter().map(|k| (k, ()));
+        let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+        BTreeSet { map }
     }
 }
 
@@ -1071,8 +1080,16 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
     /// let set2: BTreeSet<_> = [1, 2, 3, 4].into();
     /// assert_eq!(set1, set2);
     /// ```
-    fn from(arr: [T; N]) -> Self {
-        core::array::IntoIter::new(arr).collect()
+    fn from(mut arr: [T; N]) -> Self {
+        if N == 0 {
+            return BTreeSet::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        arr.sort();
+        let iter = core::array::IntoIter::new(arr).map(|k| (k, ()));
+        let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+        BTreeSet { map }
     }
 }
 
index 3caada06f6b58d33128685ea8fb0ca32184c3b4f..be21018512d8bbe9c158bf5f1ee7640a4175aa1d 100644 (file)
@@ -323,7 +323,7 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
     pub fn reserve(&mut self, len: usize, additional: usize) {
         // Callers expect this function to be very cheap when there is already sufficient capacity.
         // Therefore, we move all the resizing and error-handling logic from grow_amortized and
-        // handle_reserve behind a call, while making sure that the this function is likely to be
+        // handle_reserve behind a call, while making sure that this function is likely to be
         // inlined as just a comparison and a call if the comparison fails.
         #[cold]
         fn do_reserve_and_handle<T, A: Allocator>(
index 70cccd31b92ded435eb886bd9a475bc79b27a1c1..8c33a43ab330ebd4d847152d7e188cbb231afbb6 100644 (file)
@@ -396,7 +396,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     ///
     /// This method is particularly useful if combined with other methods, like
     /// [`map`](#method.map). This way, you can avoid moving the original
-    /// array if its elements are not `Copy`.
+    /// array if its elements are not [`Copy`].
     ///
     /// ```
     /// #![feature(array_methods)]
index dcafaae2f5b493a4a858462f589cc52ade71e76b..ca1c0ae759892466228d0f072e48a6da7da78df6 100644 (file)
@@ -2,7 +2,7 @@
 
 #[lang = "bool"]
 impl bool {
-    /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
+    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
     ///
     /// # Examples
     ///
@@ -18,7 +18,7 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
         if self { Some(t) } else { None }
     }
 
-    /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
+    /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
     ///
     /// # Examples
     ///
index 0dadbdd1bd0543e4c08423b91c59363f8e777f7b..e6d3ac8f2d2c5d3637cb4fd144fc1572cedf691a 100644 (file)
@@ -96,7 +96,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into
     /// Converts a `u32` to a `char`.
     ///
     /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
-    /// `as`:
+    /// [`as`](keyword.as.html):
     ///
     /// ```
     /// let c = '💯';
@@ -372,7 +372,7 @@ pub fn to_digit(self, radix: u32) -> Option<u32> {
     /// println!("\\u{{2764}}");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
@@ -422,7 +422,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
     /// Returns an iterator that yields the literal escape code of a character
     /// as `char`s.
     ///
-    /// This will escape the characters similar to the `Debug` implementations
+    /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations
     /// of `str` or `char`.
     ///
     /// # Examples
@@ -448,7 +448,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
     /// println!("\\n");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
@@ -502,7 +502,7 @@ pub fn escape_debug(self) -> EscapeDebug {
     /// println!("\\\"");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('"'.escape_default().to_string(), "\\\"");
@@ -937,7 +937,7 @@ pub fn is_numeric(self) -> bool {
     /// println!("i\u{307}");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('C'.to_lowercase().to_string(), "c");
@@ -1002,7 +1002,7 @@ pub fn to_lowercase(self) -> ToLowercase {
     /// println!("SS");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('c'.to_uppercase().to_string(), "C");
@@ -1131,7 +1131,7 @@ pub const fn to_ascii_lowercase(&self) -> char {
 
     /// Checks that two values are an ASCII case-insensitive match.
     ///
-    /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    /// Equivalent to <code>[to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b)</code>.
     ///
     /// # Examples
     ///
@@ -1144,6 +1144,8 @@ pub const fn to_ascii_lowercase(&self) -> char {
     /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
     /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
     /// ```
+    ///
+    /// [to_ascii_lowercase]: #method.to_ascii_lowercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
     #[inline]
index 4e82b65539460eeaffeb71fe8839a79c93359548..5ac9fdec0cf58f9a1618b8eda53d32ab52fd3da6 100644 (file)
     message = "can't compare `{Self}` with `{Rhs}`",
     label = "no implementation for `{Self} == {Rhs}`"
 )]
+#[rustc_diagnostic_item = "PartialEq"]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
     /// by `==`.
@@ -269,6 +270,7 @@ fn ne(&self, other: &Rhs) -> bool {
 #[doc(alias = "==")]
 #[doc(alias = "!=")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Eq"]
 pub trait Eq: PartialEq<Self> {
     // this method is used solely by #[deriving] to assert
     // that every component of a type implements #[deriving]
@@ -728,6 +730,7 @@ fn clone_from(&mut self, other: &Self) {
 #[doc(alias = "<=")]
 #[doc(alias = ">=")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Ord"]
 pub trait Ord: Eq + PartialOrd<Self> {
     /// This method returns an [`Ordering`] between `self` and `other`.
     ///
@@ -984,6 +987,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
     message = "can't compare `{Self}` with `{Rhs}`",
     label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`"
 )]
+#[rustc_diagnostic_item = "PartialOrd"]
 pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values if one exists.
     ///
index 77161e961e79812b2b931c457b9efb1546d23f3f..da3f20d18e5108f9b5cc1a6ce10e014df78a8f2b 100644 (file)
 /// [`HashSet`]: ../../std/collections/struct.HashSet.html
 /// [`hash`]: Hash::hash
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_diagnostic_item = "Hash"]
 pub trait Hash {
     /// Feeds this value into the given [`Hasher`].
     ///
index 333f81ce4cfc4b52c967522d84b6690b29553f4e..82962a1fe13fc2ce59a3342904ee4044c286a627 100644 (file)
@@ -382,6 +382,7 @@ pub trait StructuralEq {
 // existing specializations on `Copy` that already exist in the standard
 // library, and there's no way to safely have this behavior right now.
 #[rustc_unsafe_specialization_marker]
+#[rustc_diagnostic_item = "Copy"]
 pub trait Copy: Clone {
     // Empty.
 }
index a23ca51ef87d023731b027748cdf74e261d61209..e4599067f85f7328cc54286fec615c8ad5becc30 100644 (file)
@@ -116,8 +116,8 @@ pub const fn i128(val: i128) -> u32 {
 
 macro_rules! impl_checked {
     ($T:ident) => {
-        pub const fn $T(val: $T) -> Option<$T> {
-            if val > 0 { Some(unchecked::$T(val) as $T) } else { None }
+        pub const fn $T(val: $T) -> Option<u32> {
+            if val > 0 { Some(unchecked::$T(val)) } else { None }
         }
     };
 }
index 780d6c34c919732640dc0da9004f85eae97dc4d6..77643290cc455fb16813480c08b029b61846a622 100644 (file)
@@ -2026,7 +2026,7 @@ pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log(self, base: Self) -> Self {
+        pub const fn log(self, base: Self) -> u32 {
             match self.checked_log(base) {
                 Some(n) => n,
                 None => {
@@ -2060,7 +2060,7 @@ pub const fn log(self, base: Self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log2(self) -> Self {
+        pub const fn log2(self) -> u32 {
             match self.checked_log2() {
                 Some(n) => n,
                 None => {
@@ -2094,7 +2094,7 @@ pub const fn log2(self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log10(self) -> Self {
+        pub const fn log10(self) -> u32 {
             match self.checked_log10() {
                 Some(n) => n,
                 None => {
@@ -2125,7 +2125,7 @@ pub const fn log10(self) -> Self {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log(self, base: Self) -> Option<Self> {
+        pub const fn checked_log(self, base: Self) -> Option<u32> {
             if self <= 0 || base <= 1 {
                 None
             } else {
@@ -2161,12 +2161,12 @@ pub const fn checked_log(self, base: Self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log2(self) -> Option<Self> {
+        pub const fn checked_log2(self) -> Option<u32> {
             if self <= 0 {
                 None
             } else {
                 // SAFETY: We just checked that this number is positive
-                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
                 Some(log)
             }
         }
@@ -2185,11 +2185,8 @@ pub const fn checked_log2(self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log10(self) -> Option<Self> {
-            match int_log10::$ActualT(self as $ActualT) {
-                Some(s) => Some(s as Self),
-                None => None,
-            }
+        pub const fn checked_log10(self) -> Option<u32> {
+            int_log10::$ActualT(self as $ActualT)
         }
 
         /// Computes the absolute value of `self`.
index 02a5ed4ca800e124de5d6791164285fc48984247..46e64c33b84d77cb7f207abc3f132db3b7fa2cd5 100644 (file)
@@ -660,7 +660,7 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log(self, base: Self) -> Self {
+        pub const fn log(self, base: Self) -> u32 {
             match self.checked_log(base) {
                 Some(n) => n,
                 None => {
@@ -694,7 +694,7 @@ pub const fn log(self, base: Self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log2(self) -> Self {
+        pub const fn log2(self) -> u32 {
             match self.checked_log2() {
                 Some(n) => n,
                 None => {
@@ -728,7 +728,7 @@ pub const fn log2(self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log10(self) -> Self {
+        pub const fn log10(self) -> u32 {
             match self.checked_log10() {
                 Some(n) => n,
                 None => {
@@ -759,7 +759,7 @@ pub const fn log10(self) -> Self {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log(self, base: Self) -> Option<Self> {
+        pub const fn checked_log(self, base: Self) -> Option<u32> {
             if self <= 0 || base <= 1 {
                 None
             } else {
@@ -795,12 +795,12 @@ pub const fn checked_log(self, base: Self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log2(self) -> Option<Self> {
+        pub const fn checked_log2(self) -> Option<u32> {
             if self <= 0 {
                 None
             } else {
                 // SAFETY: We just checked that this number is positive
-                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
                 Some(log)
             }
         }
@@ -819,11 +819,8 @@ pub const fn checked_log2(self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log10(self) -> Option<Self> {
-            match int_log10::$ActualT(self as $ActualT) {
-                Some(s) => Some(s as Self),
-                None => None,
-            }
+        pub const fn checked_log10(self) -> Option<u32> {
+            int_log10::$ActualT(self as $ActualT)
         }
 
         /// Checked negation. Computes `-self`, returning `None` unless `self ==
index 51f804381734545f946fe411bdb123197ac5f6e6..92f45ac9e7ea9251c39e9cdd4d9cd1a6703cff16 100644 (file)
@@ -30,6 +30,7 @@
 /// ```
 #[lang = "not"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "!")]
 pub trait Not {
     /// The resulting type after applying the `!` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
index 51122c11ce1e29bc19a40e37091e4b1bc1b3cf8e..1517e8a952f93b525c90027d248cc609e80a23d7 100644 (file)
@@ -26,10 +26,10 @@ fn checked_log() {
         assert_eq!(i.checked_log(4), None);
     }
     for i in 1..=i16::MAX {
-        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
     }
     for i in 1..=u16::MAX {
-        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
     }
 }
 
@@ -46,19 +46,19 @@ fn checked_log2() {
     assert_eq!(0i16.checked_log2(), None);
 
     for i in 1..=u8::MAX {
-        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
     }
     for i in 1..=u16::MAX {
         // Guard against Android's imprecise f32::log2 implementation.
         if i != 8192 && i != 32768 {
-            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
         }
     }
     for i in i8::MIN..=0 {
         assert_eq!(i.checked_log2(), None);
     }
     for i in 1..=i8::MAX {
-        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
     }
     for i in i16::MIN..=0 {
         assert_eq!(i.checked_log2(), None);
@@ -66,7 +66,7 @@ fn checked_log2() {
     for i in 1..=i16::MAX {
         // Guard against Android's imprecise f32::log2 implementation.
         if i != 8192 {
-            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
         }
     }
 }
@@ -75,9 +75,9 @@ fn checked_log2() {
 #[test]
 #[cfg(not(target_os = "android"))]
 fn checked_log2_not_android() {
-    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
-    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
-    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u32));
+    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u32));
+    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as u32));
 }
 
 #[test]
@@ -91,10 +91,10 @@ fn checked_log10() {
         assert_eq!(i.checked_log10(), None);
     }
     for i in 1..=i16::MAX {
-        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
     }
     for i in 1..=u16::MAX {
-        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
     }
 }
 
index 749a441d1826361e7c8b324c43db468659726d25..3af941f59b68918d1417e444428112cdc662e17a 100644 (file)
@@ -119,7 +119,7 @@ mod break_keyword {}
 
 #[doc(keyword = "const")]
 //
-/// Compile-time constants and compile-time evaluable functions.
+/// Compile-time constants, compile-time evaluable functions, and raw pointers.
 ///
 /// ## Compile-time constants
 ///
index b20eafb4d53a59396a629ea903fda96b33e5e7a0..71563a02dcbb931290b75a22c20ed4cc6bc1be80 100644 (file)
@@ -517,11 +517,20 @@ fn is_symlink_file(&self) -> bool {
     }
 }
 
-/// Creates a new file symbolic link on the filesystem.
+/// Creates a new symlink to a non-directory file on the filesystem.
 ///
 /// The `link` path will be a file symbolic link pointing to the `original`
 /// path.
 ///
+/// The `original` path should not be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```no_run
@@ -537,11 +546,20 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io:
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
 }
 
-/// Creates a new directory symlink on the filesystem.
+/// Creates a new symlink to a directory on the filesystem.
 ///
 /// The `link` path will be a directory symbolic link pointing to the `original`
 /// path.
 ///
+/// The `original` path must be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_file`] for other files.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```no_run
index 261d0e648e2ef3df066bcecb92c7c7cf9cb1aa9e..1669c467b918c480e0c2c11d1230690311fe94b3 100644 (file)
@@ -3,16 +3,16 @@
 #[doc(alias = "false")]
 /// The boolean type.
 ///
-/// The `bool` represents a value, which could only be either `true` or `false`. If you cast
-/// a `bool` into an integer, `true` will be 1 and `false` will be 0.
+/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast
+/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0.
 ///
 /// # Basic usage
 ///
 /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
 /// which allow us to perform boolean operations using `&`, `|` and `!`.
 ///
-/// `if` requires a `bool` value as its conditional. [`assert!`], which is an
-/// important macro in testing, checks whether an expression is `true` and panics
+/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is [`true`] and panics
 /// if it isn't.
 ///
 /// ```
 /// assert!(!bool_val);
 /// ```
 ///
+/// [`true`]: keyword.true.html
+/// [`false`]: keyword.false.html
 /// [`BitAnd`]: ops::BitAnd
 /// [`BitOr`]: ops::BitOr
 /// [`Not`]: ops::Not
+/// [`if`]: keyword.if.html
 ///
 /// # Examples
 ///
@@ -385,8 +388,11 @@ mod prim_char {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_unit {}
 
-#[doc(alias = "ptr")]
 #[doc(primitive = "pointer")]
+#[doc(alias = "ptr")]
+#[doc(alias = "*")]
+#[doc(alias = "*const")]
+#[doc(alias = "*mut")]
 //
 /// Raw, unsafe pointers, `*const T`, and `*mut T`.
 ///
@@ -499,10 +505,10 @@ mod prim_unit {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
+#[doc(primitive = "array")]
 #[doc(alias = "[]")]
 #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
 #[doc(alias = "[T; N]")]
-#[doc(primitive = "array")]
 /// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
 /// non-negative compile-time constant size, `N`.
 ///
@@ -574,8 +580,8 @@ mod prim_pointer {}
 ///
 /// # Editions
 ///
-/// Prior to Rust 1.53, arrays did not implement `IntoIterator` by value, so the method call
-/// `array.into_iter()` auto-referenced into a slice iterator. Right now, the old behavior
+/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old behavior
 /// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
 /// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition
 /// might be made consistent to the behavior of later editions.
@@ -833,7 +839,7 @@ mod prim_str {}
 /// ```
 ///
 /// The sequential nature of the tuple applies to its implementations of various
-/// traits.  For example, in `PartialOrd` and `Ord`, the elements are compared
+/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared
 /// sequentially until the first non-equal set is found.
 ///
 /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
@@ -1037,14 +1043,16 @@ mod prim_usize {}
 /// References, both shared and mutable.
 ///
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
-/// operators on a value, or by using a `ref` or `ref mut` pattern.
+/// operators on a value, or by using a [`ref`](keyword.ref.html) or
+/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
 ///
 /// For those familiar with pointers, a reference is just a pointer that is assumed to be
 /// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
-/// `&bool` can only point to an allocation containing the integer values `1` (`true`) or `0`
-/// (`false`), but creating a `&bool` that points to an allocation containing
-/// the value `3` causes undefined behaviour.
-/// In fact, `Option<&T>` has the same memory representation as a
+/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
+/// ([`true`](keyword.true.html)) or `0` ([`false`](keyword.false.html)), but creating a
+/// <code>&[bool]</code> that points to an allocation containing the value `3` causes
+/// undefined behaviour.
+/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
 /// nullable but aligned pointer, and can be passed across FFI boundaries as such.
 ///
 /// In most cases, references can be used much like the original value. Field access, method
@@ -1140,7 +1148,7 @@ mod prim_usize {}
 /// * [`ExactSizeIterator`]
 /// * [`FusedIterator`]
 /// * [`TrustedLen`]
-/// * [`Send`] \(note that `&T` references only get `Send` if `T: Sync`)
+/// * [`Send`] \(note that `&T` references only get `Send` if <code>T: [Sync]</code>)
 /// * [`io::Write`]
 /// * [`Read`]
 /// * [`Seek`]
@@ -1172,7 +1180,8 @@ mod prim_ref {}
 /// Function pointers are pointers that point to *code*, not data. They can be called
 /// just like functions. Like references, function pointers are, among other things, assumed to
 /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
-/// pointers, make your type `Option<fn()>` with your required signature.
+/// pointers, make your type [`Option<fn()>`](core::option#options-and-pointers-nullable-pointers)
+/// with your required signature.
 ///
 /// ### Safety
 ///
index e34768bc2c906ba9f3245cc87f7c3508f6e0f559..1f1eca1c76cf101ccded1b19843cef64a855bfd1 100644 (file)
@@ -4,6 +4,7 @@ import contextlib
 import datetime
 import distutils.version
 import hashlib
+import json
 import os
 import re
 import shutil
@@ -24,19 +25,17 @@ def support_xz():
     except tarfile.CompressionError:
         return False
 
-def get(url, path, verbose=False, do_verify=True):
-    suffix = '.sha256'
-    sha_url = url + suffix
+def get(base, url, path, checksums, verbose=False, do_verify=True):
     with tempfile.NamedTemporaryFile(delete=False) as temp_file:
         temp_path = temp_file.name
-    with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file:
-        sha_path = sha_file.name
 
     try:
         if do_verify:
-            download(sha_path, sha_url, False, verbose)
+            if url not in checksums:
+                raise RuntimeError("src/stage0.json doesn't contain a checksum for {}".format(url))
+            sha256 = checksums[url]
             if os.path.exists(path):
-                if verify(path, sha_path, False):
+                if verify(path, sha256, False):
                     if verbose:
                         print("using already-download file", path)
                     return
@@ -45,23 +44,17 @@ def get(url, path, verbose=False, do_verify=True):
                         print("ignoring already-download file",
                             path, "due to failed verification")
                     os.unlink(path)
-        download(temp_path, url, True, verbose)
-        if do_verify and not verify(temp_path, sha_path, verbose):
+        download(temp_path, "{}/{}".format(base, url), True, verbose)
+        if do_verify and not verify(temp_path, sha256, verbose):
             raise RuntimeError("failed verification")
         if verbose:
             print("moving {} to {}".format(temp_path, path))
         shutil.move(temp_path, path)
     finally:
-        delete_if_present(sha_path, verbose)
-        delete_if_present(temp_path, verbose)
-
-
-def delete_if_present(path, verbose):
-    """Remove the given file if present"""
-    if os.path.isfile(path):
-        if verbose:
-            print("removing", path)
-        os.unlink(path)
+        if os.path.isfile(temp_path):
+            if verbose:
+                print("removing", temp_path)
+            os.unlink(temp_path)
 
 
 def download(path, url, probably_big, verbose):
@@ -98,14 +91,12 @@ def _download(path, url, probably_big, verbose, exception):
             exception=exception)
 
 
-def verify(path, sha_path, verbose):
+def verify(path, expected, verbose):
     """Check if the sha256 sum of the given path is valid"""
     if verbose:
         print("verifying", path)
     with open(path, "rb") as source:
         found = hashlib.sha256(source.read()).hexdigest()
-    with open(sha_path, "r") as sha256sum:
-        expected = sha256sum.readline().split()[0]
     verified = found == expected
     if not verified:
         print("invalid checksum:\n"
@@ -176,15 +167,6 @@ def require(cmd, exit=True):
         sys.exit(1)
 
 
-def stage0_data(rust_root):
-    """Build a dictionary from stage0.txt"""
-    nightlies = os.path.join(rust_root, "src/stage0.txt")
-    with open(nightlies, 'r') as nightlies:
-        lines = [line.rstrip() for line in nightlies
-                 if not line.startswith("#")]
-        return dict([line.split(": ", 1) for line in lines if line])
-
-
 def format_build_time(duration):
     """Return a nicer format for build time
 
@@ -372,13 +354,22 @@ def output(filepath):
     os.rename(tmp, filepath)
 
 
+class Stage0Toolchain:
+    def __init__(self, stage0_payload):
+        self.date = stage0_payload["date"]
+        self.version = stage0_payload["version"]
+
+    def channel(self):
+        return self.version + "-" + self.date
+
+
 class RustBuild(object):
     """Provide all the methods required to build Rust"""
     def __init__(self):
-        self.date = ''
+        self.checksums_sha256 = {}
+        self.stage0_compiler = None
+        self.stage0_rustfmt = None
         self._download_url = ''
-        self.rustc_channel = ''
-        self.rustfmt_channel = ''
         self.build = ''
         self.build_dir = ''
         self.clean = False
@@ -402,11 +393,10 @@ class RustBuild(object):
         will move all the content to the right place.
         """
         if rustc_channel is None:
-            rustc_channel = self.rustc_channel
-        rustfmt_channel = self.rustfmt_channel
+            rustc_channel = self.stage0_compiler.version
         bin_root = self.bin_root(stage0)
 
-        key = self.date
+        key = self.stage0_compiler.date
         if not stage0:
             key += str(self.rustc_commit)
         if self.rustc(stage0).startswith(bin_root) and \
@@ -445,19 +435,23 @@ class RustBuild(object):
 
         if self.rustfmt() and self.rustfmt().startswith(bin_root) and (
             not os.path.exists(self.rustfmt())
-            or self.program_out_of_date(self.rustfmt_stamp(), self.rustfmt_channel)
+            or self.program_out_of_date(
+                self.rustfmt_stamp(),
+                "" if self.stage0_rustfmt is None else self.stage0_rustfmt.channel()
+            )
         ):
-            if rustfmt_channel:
+            if self.stage0_rustfmt is not None:
                 tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
-                [channel, date] = rustfmt_channel.split('-', 1)
-                filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix)
+                filename = "rustfmt-{}-{}{}".format(
+                    self.stage0_rustfmt.version, self.build, tarball_suffix,
+                )
                 self._download_component_helper(
-                    filename, "rustfmt-preview", tarball_suffix, key=date
+                    filename, "rustfmt-preview", tarball_suffix, key=self.stage0_rustfmt.date
                 )
                 self.fix_bin_or_dylib("{}/bin/rustfmt".format(bin_root))
                 self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(bin_root))
                 with output(self.rustfmt_stamp()) as rustfmt_stamp:
-                    rustfmt_stamp.write(self.rustfmt_channel)
+                    rustfmt_stamp.write(self.stage0_rustfmt.channel())
 
         # Avoid downloading LLVM twice (once for stage0 and once for the master rustc)
         if self.downloading_llvm() and stage0:
@@ -518,7 +512,7 @@ class RustBuild(object):
     ):
         if key is None:
             if stage0:
-                key = self.date
+                key = self.stage0_compiler.date
             else:
                 key = self.rustc_commit
         cache_dst = os.path.join(self.build_dir, "cache")
@@ -527,12 +521,21 @@ class RustBuild(object):
             os.makedirs(rustc_cache)
 
         if stage0:
-            url = "{}/dist/{}".format(self._download_url, key)
+            base = self._download_url
+            url = "dist/{}".format(key)
         else:
-            url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(self.rustc_commit)
+            base = "https://ci-artifacts.rust-lang.org"
+            url = "rustc-builds/{}".format(self.rustc_commit)
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
-            get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=stage0)
+            get(
+                base,
+                "{}/{}".format(url, filename),
+                tarball,
+                self.checksums_sha256,
+                verbose=self.verbose,
+                do_verify=stage0,
+            )
         unpack(tarball, tarball_suffix, self.bin_root(stage0), match=pattern, verbose=self.verbose)
 
     def _download_ci_llvm(self, llvm_sha, llvm_assertions):
@@ -542,7 +545,8 @@ class RustBuild(object):
         if not os.path.exists(rustc_cache):
             os.makedirs(rustc_cache)
 
-        url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
+        base = "https://ci-artifacts.rust-lang.org"
+        url = "rustc-builds/{}".format(llvm_sha)
         if llvm_assertions:
             url = url.replace('rustc-builds', 'rustc-builds-alt')
         # ci-artifacts are only stored as .xz, not .gz
@@ -554,7 +558,14 @@ class RustBuild(object):
         filename = "rust-dev-nightly-" + self.build + tarball_suffix
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
-            get("{}/{}".format(url, filename), tarball, verbose=self.verbose, do_verify=False)
+            get(
+                base,
+                "{}/{}".format(url, filename),
+                tarball,
+                self.checksums_sha256,
+                verbose=self.verbose,
+                do_verify=False,
+            )
         unpack(tarball, tarball_suffix, self.llvm_root(),
                 match="rust-dev",
                 verbose=self.verbose)
@@ -816,7 +827,7 @@ class RustBuild(object):
 
     def rustfmt(self):
         """Return config path for rustfmt"""
-        if not self.rustfmt_channel:
+        if self.stage0_rustfmt is None:
             return None
         return self.program_config('rustfmt')
 
@@ -1040,19 +1051,12 @@ class RustBuild(object):
             self.update_submodule(module[0], module[1], recorded_submodules)
         print("Submodules updated in %.2f seconds" % (time() - start_time))
 
-    def set_normal_environment(self):
+    def set_dist_environment(self, url):
         """Set download URL for normal environment"""
         if 'RUSTUP_DIST_SERVER' in os.environ:
             self._download_url = os.environ['RUSTUP_DIST_SERVER']
         else:
-            self._download_url = 'https://static.rust-lang.org'
-
-    def set_dev_environment(self):
-        """Set download URL for development environment"""
-        if 'RUSTUP_DEV_DIST_SERVER' in os.environ:
-            self._download_url = os.environ['RUSTUP_DEV_DIST_SERVER']
-        else:
-            self._download_url = 'https://dev-static.rust-lang.org'
+            self._download_url = url
 
     def check_vendored_status(self):
         """Check that vendoring is configured properly"""
@@ -1161,17 +1165,14 @@ def bootstrap(help_triggered):
     build_dir = build.get_toml('build-dir', 'build') or 'build'
     build.build_dir = os.path.abspath(build_dir.replace("$ROOT", build.rust_root))
 
-    data = stage0_data(build.rust_root)
-    build.date = data['date']
-    build.rustc_channel = data['rustc']
-
-    if "rustfmt" in data:
-        build.rustfmt_channel = data['rustfmt']
+    with open(os.path.join(build.rust_root, "src", "stage0.json")) as f:
+        data = json.load(f)
+    build.checksums_sha256 = data["checksums_sha256"]
+    build.stage0_compiler = Stage0Toolchain(data["compiler"])
+    if data.get("rustfmt") is not None:
+        build.stage0_rustfmt = Stage0Toolchain(data["rustfmt"])
 
-    if 'dev' in data:
-        build.set_dev_environment()
-    else:
-        build.set_normal_environment()
+    build.set_dist_environment(data["dist_server"])
 
     build.build = args.build or build.build_triple()
     build.update_submodules()
index 615071141594f12a6d28fcb7db79ed98e93f6f19..7bffc1c15206b67b4d59436673051d870ec08a63 100644 (file)
@@ -13,38 +13,18 @@ from shutil import rmtree
 import bootstrap
 
 
-class Stage0DataTestCase(unittest.TestCase):
-    """Test Case for stage0_data"""
-    def setUp(self):
-        self.rust_root = tempfile.mkdtemp()
-        os.mkdir(os.path.join(self.rust_root, "src"))
-        with open(os.path.join(self.rust_root, "src",
-                               "stage0.txt"), "w") as stage0:
-            stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta\nrustfmt: beta")
-
-    def tearDown(self):
-        rmtree(self.rust_root)
-
-    def test_stage0_data(self):
-        """Extract data from stage0.txt"""
-        expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta", "rustfmt": "beta"}
-        data = bootstrap.stage0_data(self.rust_root)
-        self.assertDictEqual(data, expected)
-
-
 class VerifyTestCase(unittest.TestCase):
     """Test Case for verify"""
     def setUp(self):
         self.container = tempfile.mkdtemp()
         self.src = os.path.join(self.container, "src.txt")
-        self.sums = os.path.join(self.container, "sums")
         self.bad_src = os.path.join(self.container, "bad.txt")
         content = "Hello world"
 
+        self.expected = hashlib.sha256(content.encode("utf-8")).hexdigest()
+
         with open(self.src, "w") as src:
             src.write(content)
-        with open(self.sums, "w") as sums:
-            sums.write(hashlib.sha256(content.encode("utf-8")).hexdigest())
         with open(self.bad_src, "w") as bad:
             bad.write("Hello!")
 
@@ -53,11 +33,11 @@ class VerifyTestCase(unittest.TestCase):
 
     def test_valid_file(self):
         """Check if the sha256 sum of the given file is valid"""
-        self.assertTrue(bootstrap.verify(self.src, self.sums, False))
+        self.assertTrue(bootstrap.verify(self.src, self.expected, False))
 
     def test_invalid_file(self):
         """Should verify that the file is invalid"""
-        self.assertFalse(bootstrap.verify(self.bad_src, self.sums, False))
+        self.assertFalse(bootstrap.verify(self.bad_src, self.expected, False))
 
 
 class ProgramOutOfDate(unittest.TestCase):
@@ -99,7 +79,6 @@ if __name__ == '__main__':
     TEST_LOADER = unittest.TestLoader()
     SUITE.addTest(doctest.DocTestSuite(bootstrap))
     SUITE.addTests([
-        TEST_LOADER.loadTestsFromTestCase(Stage0DataTestCase),
         TEST_LOADER.loadTestsFromTestCase(VerifyTestCase),
         TEST_LOADER.loadTestsFromTestCase(ProgramOutOfDate)])
 
index 5911309a044cebc4dd47800999c003e983a5895b..0a6ed2f49b7877dcc19549b8571ed592509ffbfc 100644 (file)
@@ -523,7 +523,7 @@ macro_rules! describe {
                 install::Src,
                 install::Rustc
             ),
-            Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest),
+            Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::BumpStage0),
         }
     }
 
index 4eb335979b983b004efb2a1358a094947f917a64..f5fad4b4136849c8f023eda32bb9d71365f7e1b1 100644 (file)
@@ -107,6 +107,11 @@ fn run(self, builder: &Builder<'_>) {
             add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
         }
 
+        // don't run on std twice with x.py clippy
+        if builder.kind == Kind::Clippy {
+            return;
+        }
+
         // Then run cargo again, once we've put the rmeta files for the library
         // crates into the sysroot. This is needed because e.g., core's tests
         // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
@@ -120,6 +125,7 @@ fn run(self, builder: &Builder<'_>) {
             target,
             cargo_subcommand(builder.kind),
         );
+
         cargo.arg("--all-targets");
         std_cargo(builder, target, compiler.stage, &mut cargo);
 
@@ -192,7 +198,12 @@ fn run(self, builder: &Builder<'_>) {
             cargo_subcommand(builder.kind),
         );
         rustc_cargo(builder, &mut cargo, target);
-        cargo.arg("--all-targets");
+
+        // For ./x.py clippy, don't run with --all-targets because
+        // linting tests and benchmarks can produce very noisy results
+        if builder.kind != Kind::Clippy {
+            cargo.arg("--all-targets");
+        }
 
         // Explicitly pass -p for all compiler krates -- this will force cargo
         // to also check the tests/benches/examples for these crates, rather
@@ -313,7 +324,12 @@ fn run(self, builder: &Builder<'_>) {
                     $source_type,
                     &[],
                 );
-                cargo.arg("--all-targets");
+
+                // For ./x.py clippy, don't run with --all-targets because
+                // linting tests and benchmarks can produce very noisy results
+                if builder.kind != Kind::Clippy {
+                    cargo.arg("--all-targets");
+                }
 
                 // Enable internal lints for clippy and rustdoc
                 // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
index 3d56650f7752ad70f8d851af2739ecca63931f6c..a4735d54be03828f1d91c37a3c507c85f4cefc00 100644 (file)
@@ -31,7 +31,7 @@
 //! When you execute `x.py build`, the steps executed are:
 //!
 //! * First, the python script is run. This will automatically download the
-//!   stage0 rustc and cargo according to `src/stage0.txt`, or use the cached
+//!   stage0 rustc and cargo according to `src/stage0.json`, or use the cached
 //!   versions if they're available. These are then used to compile rustbuild
 //!   itself (using Cargo). Finally, control is then transferred to rustbuild.
 //!
index 8cf43eac404c6e541a1d2ef4285596070b497377..0e306cb7211b5e9a186ed0b4d3871572469ba9c2 100644 (file)
@@ -189,6 +189,11 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
             .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
 
+        // Parts of our test suite rely on the `FileCheck` tool, which is built by default in
+        // `build/$TARGET/llvm/build/bin` is but *not* then installed to `build/$TARGET/llvm/bin`.
+        // This flag makes sure `FileCheck` is copied in the final binaries directory.
+        cfg.define("LLVM_INSTALL_UTILS", "ON");
+
         if builder.config.llvm_profile_generate {
             cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
             cfg.define("LLVM_BUILD_RUNTIME", "No");
index 7c64e5a0aadc8e3624dfc6900a268115eb40a931..11b393857e74c281b3dd4fb14f2366d8b3103d2d 100644 (file)
@@ -82,3 +82,24 @@ fn run(self, builder: &Builder<'_>) {
         builder.run(&mut cmd);
     }
 }
+
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct BumpStage0;
+
+impl Step for BumpStage0 {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/bump-stage0")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(BumpStage0);
+    }
+
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let mut cmd = builder.tool_cmd(Tool::BumpStage0);
+        builder.run(&mut cmd);
+    }
+}
index 74e50c606107fec6be26387e99acd6f5356d931a..d7db2cef24f2be27323779d047afcd1a99e9617c 100644 (file)
@@ -15,7 +15,7 @@
 use std::path::PathBuf;
 use std::process::Command;
 
-use build_helper::{output, t};
+use build_helper::output;
 
 use crate::cache::INTERNER;
 use crate::config::Target;
@@ -227,14 +227,4 @@ pub fn check(build: &mut Build) {
     if let Some(ref s) = build.config.ccache {
         cmd_finder.must_have(s);
     }
-
-    if build.config.channel == "stable" {
-        let stage0 = t!(fs::read_to_string(build.src.join("src/stage0.txt")));
-        if stage0.contains("\ndev:") {
-            panic!(
-                "bootstrapping from a dev compiler in a stable release, but \
-                    should only be bootstrapping from a released compiler!"
-            );
-        }
-    }
 }
index f5e3f61dcc88f6fb5827382bd8dcef13780dc8b2..c035894638538a9b7576f4f705914bb72671607c 100644 (file)
@@ -377,6 +377,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
     LintDocs, "src/tools/lint-docs", "lint-docs";
     JsonDocCk, "src/tools/jsondocck", "jsondocck";
     HtmlChecker, "src/tools/html-checker", "html-checker";
+    BumpStage0, "src/tools/bump-stage0", "bump-stage0";
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
index 9217209fcf0516a8348fdfc35854c4bbcaeffd20..11adb56490b32406e54f218cfe30b53aad27344f 100644 (file)
@@ -331,9 +331,10 @@ fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet<GenericPa
                 match br {
                     // We only care about named late bound regions, as we need to add them
                     // to the 'for<>' section
-                    ty::BrNamed(_, name) => {
-                        Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
-                    }
+                    ty::BrNamed(_, name) => Some(GenericParamDef {
+                        name,
+                        kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+                    }),
                     _ => None,
                 }
             })
@@ -659,7 +660,7 @@ fn param_env_to_generics(
                         bounds.insert(0, GenericBound::maybe_sized(self.cx));
                     }
                 }
-                GenericParamDefKind::Lifetime => {}
+                GenericParamDefKind::Lifetime { .. } => {}
                 GenericParamDefKind::Const { ref mut default, .. } => {
                     // We never want something like `impl<const N: usize = 10>`
                     default.take();
index a9baa1c31aeb8785958feb2b360053fb09b48d6c..a95300217ab75edab1c4d3125bbf9d70dff6f95f 100644 (file)
@@ -30,6 +30,7 @@
 use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_typeck::hir_ty_to_ty;
 
+use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
 use std::default::Default;
 use std::hash::Hash;
@@ -128,7 +129,6 @@ impl Clean<GenericBound> for hir::GenericBound<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
         match *self {
             hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
-            hir::GenericBound::Unsized(_) => GenericBound::maybe_sized(cx),
             hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
                 let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
 
@@ -199,9 +199,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
             .collect_referenced_late_bound_regions(&poly_trait_ref)
             .into_iter()
             .filter_map(|br| match br {
-                ty::BrNamed(_, name) => {
-                    Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
-                }
+                ty::BrNamed(_, name) => Some(GenericParamDef {
+                    name,
+                    kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+                }),
                 _ => None,
             })
             .collect();
@@ -241,30 +242,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
     }
 }
 
-impl Clean<Lifetime> for hir::GenericParam<'_> {
-    fn clean(&self, _: &mut DocContext<'_>) -> Lifetime {
-        match self.kind {
-            hir::GenericParamKind::Lifetime { .. } => {
-                if !self.bounds.is_empty() {
-                    let mut bounds = self.bounds.iter().map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => lt,
-                        _ => panic!(),
-                    });
-                    let name = bounds.next().expect("no more bounds").name.ident();
-                    let mut s = format!("{}: {}", self.name.ident(), name);
-                    for bound in bounds {
-                        s.push_str(&format!(" + {}", bound.name.ident()));
-                    }
-                    Lifetime(Symbol::intern(&s))
-                } else {
-                    Lifetime(self.name.ident().name)
-                }
-            }
-            _ => panic!(),
-        }
-    }
-}
-
 impl Clean<Constant> for hir::ConstArg {
     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
         Constant {
@@ -302,11 +279,30 @@ fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
 impl Clean<WherePredicate> for hir::WherePredicate<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
         match *self {
-            hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
-                ty: wbp.bounded_ty.clean(cx),
-                bounds: wbp.bounds.clean(cx),
-                bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
-            },
+            hir::WherePredicate::BoundPredicate(ref wbp) => {
+                let bound_params = wbp
+                    .bound_generic_params
+                    .into_iter()
+                    .map(|param| {
+                        // Higher-ranked params must be lifetimes.
+                        // Higher-ranked lifetimes can't have bounds.
+                        assert_matches!(
+                            param,
+                            hir::GenericParam {
+                                kind: hir::GenericParamKind::Lifetime { .. },
+                                bounds: [],
+                                ..
+                            }
+                        );
+                        Lifetime(param.name.ident().name)
+                    })
+                    .collect();
+                WherePredicate::BoundPredicate {
+                    ty: wbp.bounded_ty.clean(cx),
+                    bounds: wbp.bounds.clean(cx),
+                    bound_params,
+                }
+            }
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                 lifetime: wrp.lifetime.clean(cx),
@@ -412,7 +408,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
 impl Clean<GenericParamDef> for ty::GenericParamDef {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
-            ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
+            ty::GenericParamDefKind::Lifetime => {
+                (self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
+            }
             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
                 let default = if has_default {
                     let mut default = cx.tcx.type_of(self.def_id).clean(cx);
@@ -462,21 +460,15 @@ impl Clean<GenericParamDef> for hir::GenericParam<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             hir::GenericParamKind::Lifetime { .. } => {
-                let name = if !self.bounds.is_empty() {
-                    let mut bounds = self.bounds.iter().map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => lt,
+                let outlives = self
+                    .bounds
+                    .iter()
+                    .map(|bound| match bound {
+                        hir::GenericBound::Outlives(lt) => lt.clean(cx),
                         _ => panic!(),
-                    });
-                    let name = bounds.next().expect("no more bounds").name.ident();
-                    let mut s = format!("{}: {}", self.name.ident(), name);
-                    for bound in bounds {
-                        s.push_str(&format!(" + {}", bound.name.ident()));
-                    }
-                    Symbol::intern(&s)
-                } else {
-                    self.name.ident().name
-                };
-                (name, GenericParamDefKind::Lifetime)
+                    })
+                    .collect();
+                (self.name.ident().name, GenericParamDefKind::Lifetime { outlives })
             }
             hir::GenericParamKind::Type { ref default, synthetic } => (
                 self.name.ident().name,
@@ -536,7 +528,7 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
             .map(|param| {
                 let param: GenericParamDef = param.clean(cx);
                 match param.kind {
-                    GenericParamDefKind::Lifetime => unreachable!(),
+                    GenericParamDefKind::Lifetime { .. } => unreachable!(),
                     GenericParamDefKind::Type { did, ref bounds, .. } => {
                         cx.impl_trait_bounds.insert(did.into(), bounds.clone());
                     }
@@ -564,19 +556,13 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
                 WherePredicate::BoundPredicate {
                     ty: Generic(ref name), ref mut bounds, ..
                 } => {
-                    if let [] | [GenericBound::TraitBound(_, hir::TraitBoundModifier::Maybe)] =
-                        &bounds[..]
-                    {
+                    if bounds.is_empty() {
                         for param in &mut generics.params {
                             match param.kind {
-                                GenericParamDefKind::Lifetime => {}
+                                GenericParamDefKind::Lifetime { .. } => {}
                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
                                     if &param.name == name {
                                         mem::swap(bounds, ty_bounds);
-                                        // We now keep track of `?Sized` obligations in the HIR.
-                                        // If we don't clear `ty_bounds` we end up with
-                                        // `fn foo<X: ?Sized>(_: X) where X: ?Sized`.
-                                        ty_bounds.clear();
                                         break;
                                     }
                                 }
@@ -1789,7 +1775,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
                         }
                         hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                         hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
-                        hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
+                        hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
                         hir::GenericArg::Infer(_inf) => GenericArg::Infer,
                     })
                     .collect(),
index 36b862120a27b06909bb7ef041697bd8be29a4c6..5eff56a2200e10d396cfc9eba35c29b37b486859 100644 (file)
@@ -1231,7 +1231,9 @@ impl WherePredicate {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericParamDefKind {
-    Lifetime,
+    Lifetime {
+        outlives: Vec<Lifetime>,
+    },
     Type {
         did: DefId,
         bounds: Vec<GenericBound>,
@@ -1257,7 +1259,7 @@ impl GenericParamDefKind {
         match self {
             GenericParamDefKind::Type { default, .. } => default.clone(),
             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
-            GenericParamDefKind::Lifetime => None,
+            GenericParamDefKind::Lifetime { .. } => None,
         }
     }
 }
@@ -1271,7 +1273,7 @@ impl GenericParamDefKind {
 impl GenericParamDef {
     crate fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
-            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
+            GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
         }
     }
@@ -2012,10 +2014,15 @@ impl Path {
 crate enum GenericArg {
     Lifetime(Lifetime),
     Type(Type),
-    Const(Constant),
+    Const(Box<Constant>),
     Infer,
 }
 
+// `GenericArg` can occur many times in a single `Path`, so make sure it
+// doesn't increase in size unexpectedly.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericArg, 80);
+
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericArgs {
     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
index bdfe3ffc13f1362be2168f2d58851e9d234ad57b..de2cd60d2edcd048cca1cc1d4151c7ecea0aba2d 100644 (file)
@@ -121,7 +121,7 @@ fn external_generic_args(
                 ty_kind = Some(ty.kind());
                 Some(GenericArg::Type(ty.clean(cx)))
             }
-            GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+            GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))),
         })
         .collect();
 
index e61b7a0903810ba6a77b892d4c13c678cf9e6e8d..e6097f5cad7f30688168a3107bec371e08891826 100644 (file)
             let mut global_ctxt = queries.global_ctxt()?.take();
 
             let collector = global_ctxt.enter(|tcx| {
-                let krate = tcx.hir().krate();
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
                 let mut opts = scrape_test_config(crate_attrs);
                 hir_collector.visit_testable(
                     "".to_string(),
                     CRATE_HIR_ID,
-                    krate.module().inner,
-                    |this| {
-                        intravisit::walk_crate(this, krate);
-                    },
+                    tcx.hir().span(CRATE_HIR_ID),
+                    |this| tcx.hir().walk_toplevel_module(this),
                 );
 
                 collector
index 54be830bf42e7404231de5e62b66a8235d148acf..ea0458034899c54b2db6ff4368c8b7ba506a1c56 100644 (file)
@@ -155,9 +155,23 @@ impl clean::GenericParamDef {
         &'a self,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        display_fn(move |f| match self.kind {
-            clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
-            clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
+        display_fn(move |f| match &self.kind {
+            clean::GenericParamDefKind::Lifetime { outlives } => {
+                write!(f, "{}", self.name)?;
+
+                if !outlives.is_empty() {
+                    f.write_str(": ")?;
+                    for (i, lt) in outlives.iter().enumerate() {
+                        if i != 0 {
+                            f.write_str(" + ")?;
+                        }
+                        write!(f, "{}", lt.print())?;
+                    }
+                }
+
+                Ok(())
+            }
+            clean::GenericParamDefKind::Type { bounds, default, .. } => {
                 f.write_str(&*self.name.as_str())?;
 
                 if !bounds.is_empty() {
@@ -178,7 +192,7 @@ impl clean::GenericParamDef {
 
                 Ok(())
             }
-            clean::GenericParamDefKind::Const { ref ty, ref default, .. } => {
+            clean::GenericParamDefKind::Const { ty, default, .. } => {
                 if f.alternate() {
                     write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
                 } else {
index aa3723eddfcce9473e0bae8107b9945c32882c4a..5cd5254f3282d00f6dc4be2d0a37ede3613ed41d 100644 (file)
@@ -692,6 +692,12 @@ fn next(&mut self) -> Option<Self::Item> {
                     .join("\n");
 
                 nb_lines += doc[prev_offset..offset.start].lines().count();
+                // If there are characters between the preceding line ending and
+                // this code block, `str::lines` will return an additional line,
+                // which we subtract here.
+                if nb_lines != 0 && !&doc[prev_offset..offset.start].ends_with("\n") {
+                    nb_lines -= 1;
+                }
                 let line = tests.get_line() + nb_lines + 1;
                 tests.add_test(text, block_info, line);
                 prev_offset = offset.start;
index eca75ef013aae89ea567c29552b16541de9c5799..1e4cf3381f6a38d98fe6c1d59e57184a3fcae8ea 100644 (file)
@@ -1,4 +1,4 @@
-use super::{plain_text_summary, short_markdown_summary};
+use super::{find_testable_code, plain_text_summary, short_markdown_summary};
 use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 
@@ -300,3 +300,25 @@ fn t(input: &str, expect: &str) {
     t("Struct<'a, T>", "<p>Struct&lt;’a, T&gt;</p>\n");
     t("Struct<br>", "<p>Struct&lt;br&gt;</p>\n");
 }
+
+#[test]
+fn test_find_testable_code_line() {
+    fn t(input: &str, expect: &[usize]) {
+        impl crate::doctest::Tester for Vec<usize> {
+            fn add_test(&mut self, _test: String, _config: LangString, line: usize) {
+                self.push(line);
+            }
+        }
+        let mut lines = Vec::<usize>::new();
+        find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
+        assert_eq!(lines, expect);
+    }
+
+    t("", &[]);
+    t("```rust\n```", &[1]);
+    t(" ```rust\n```", &[1]);
+    t("\n```rust\n```", &[2]);
+    t("\n ```rust\n```", &[2]);
+    t("```rust\n```\n```rust\n```", &[1, 3]);
+    t("```rust\n```\n ```rust\n```", &[1, 3]);
+}
index 39ef641a3ace2772681b7e3bea91b478aee50d4f..470749ef7b3387759cc295e21533a43bab114636 100644 (file)
@@ -8,10 +8,12 @@
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::stability;
+use rustc_middle::span_bug;
 use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Adt, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants};
 
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
@@ -1621,6 +1623,15 @@ struct update syntax will not work.",
 }
 
 fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
+    fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
+        if layout.abi.is_unsized() {
+            write!(w, "(unsized)");
+        } else {
+            let bytes = layout.size.bytes() - tag_size;
+            write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
+        }
+    }
+
     if !cx.shared.show_type_layout {
         return;
     }
@@ -1642,16 +1653,40 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
                  <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
                  chapter for details on type layout guarantees.</p></div>"
             );
-            if ty_layout.layout.abi.is_unsized() {
-                writeln!(w, "<p><strong>Size:</strong> (unsized)</p>");
-            } else {
-                let bytes = ty_layout.layout.size.bytes();
-                writeln!(
-                    w,
-                    "<p><strong>Size:</strong> {size} byte{pl}</p>",
-                    size = bytes,
-                    pl = if bytes == 1 { "" } else { "s" },
-                );
+            w.write_str("<p><strong>Size:</strong> ");
+            write_size_of_layout(w, ty_layout.layout, 0);
+            writeln!(w, "</p>");
+            if let Variants::Multiple { variants, tag, tag_encoding, .. } =
+                &ty_layout.layout.variants
+            {
+                if !variants.is_empty() {
+                    w.write_str(
+                        "<p><strong>Size for each variant:</strong></p>\
+                            <ul>",
+                    );
+
+                    let adt = if let Adt(adt, _) = ty_layout.ty.kind() {
+                        adt
+                    } else {
+                        span_bug!(tcx.def_span(ty_def_id), "not an adt")
+                    };
+
+                    let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
+                        0
+                    } else if let Primitive::Int(i, _) = tag.value {
+                        i.size().bytes()
+                    } else {
+                        span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
+                    };
+
+                    for (index, layout) in variants.iter_enumerated() {
+                        let ident = adt.variants[index].ident;
+                        write!(w, "<li><code>{name}</code>: ", name = ident);
+                        write_size_of_layout(w, layout, tag_size);
+                        writeln!(w, "</li>");
+                    }
+                    w.write_str("</ul>");
+                }
             }
         }
         // This kind of layout error can occur with valid code, e.g. if you try to
index b35cd45dc9a886c60979dd15ba134df14b162a6a..54476d9c9a459f19b34179f57caa25512baf5159 100644 (file)
@@ -45,7 +45,7 @@
 
     if include_sources {
         if generate_link_to_definition {
-            intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+            tcx.hir().walk_toplevel_module(&mut visitor);
         }
         let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
         (krate, sources, visitor.matches)
index 228d718411f141eef8ca9b7eba7af175061975ae..e6bbd237cda7d72f2f1320ae442c05cc6936f320 100644 (file)
@@ -139,7 +139,7 @@ fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
         match arg {
             Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
             Type(t) => GenericArg::Type(t.into_tcx(tcx)),
-            Const(c) => GenericArg::Const(c.into_tcx(tcx)),
+            Const(box c) => GenericArg::Const(c.into_tcx(tcx)),
             Infer => GenericArg::Infer,
         }
     }
@@ -326,7 +326,9 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
     fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericParamDefKind::*;
         match kind {
-            Lifetime => GenericParamDefKind::Lifetime,
+            Lifetime { outlives } => GenericParamDefKind::Lifetime {
+                outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
+            },
             Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
                 default: default.map(|x| x.into_tcx(tcx)),
index 8bdf1a598123043e08f7595f818b7633b920b5d3..5089cc30a1e398cb907aa45f6e585b0eed81572e 100644 (file)
@@ -234,7 +234,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
                     )
                 })
                 .collect(),
-            format_version: 6,
+            format_version: 7,
         };
         let mut p = self.out_path.clone();
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
index b81acd1a93fc29f2c9268d804336285ca6c57ba9..2dbe4c42b888ebcd1251167c7fb97f75d036c0ce 100644 (file)
@@ -4,6 +4,7 @@
 )]
 #![feature(rustc_private)]
 #![feature(array_methods)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(in_band_lifetimes)]
index a04279dd5736be294843af15ac07ca499c02acef..ec995b75d71c5f3b9a82fe084259477eb22f74da 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a04279dd5736be294843af15ac07ca499c02acef
+Subproject commit ec995b75d71c5f3b9a82fe084259477eb22f74da
index 38ba87322c2385f6d86c29f9b3c84e3b1c96de33..37cdc94441df7974d7cf1f0a68755835772c5629 100644 (file)
@@ -323,7 +323,7 @@ pub struct GenericParamDef {
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "snake_case")]
 pub enum GenericParamDefKind {
-    Lifetime,
+    Lifetime { outlives: Vec<String> },
     Type { bounds: Vec<GenericBound>, default: Option<Type> },
     Const { ty: Type, default: Option<String> },
 }
diff --git a/src/stage0.json b/src/stage0.json
new file mode 100644 (file)
index 0000000..1160cd3
--- /dev/null
@@ -0,0 +1,346 @@
+{
+  "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.",
+  "dist_server": "https://static.rust-lang.org",
+  "compiler": {
+    "date": "2021-08-22",
+    "version": "beta"
+  },
+  "rustfmt": {
+    "date": "2021-08-26",
+    "version": "nightly"
+  },
+  "checksums_sha256": {
+    "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.gz": "1aae6206b6ee057a53c6863d1aa9246a913bd8cc87945221ffe25a0763198ec9",
+    "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.xz": "9bb4026714d46f99077c4ec2ac1f818a059252996077569339a72704a1044cc5",
+    "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "127a066958fe2f67154ae5e5ffdf67e216cd9da5c8ca7f6f5818017ef647eb57",
+    "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f62459d78c012d129a38f9f05975f784ca59f613cb77f273ac1be992320968ca",
+    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "eb0e5765d0d37129a1e70680cb701fc7968baf98a183a25fbe495d5e1818a67c",
+    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "8168902da36e32c2b2946ec18d41c4877191e3b5ec95276d85a1453541be8adf",
+    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "e8a774fd383d0a7a3a1216ebd3a005fe01560002c8a28b89ce7f9a0ac522a07f",
+    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "da7e246ca883ace9f9006257dd52756395307613f2bc10d86bacfe9b24f861c8",
+    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "bc20e1ffe92aeca2a01bab6b1e383dfd7cecde01780bb2369ef5e10ef6e88bc7",
+    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5020ad70b694f18fa19be09d86983a7f396b38d71a65cf061438870d9264de45",
+    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "53792dbfd932874bc7be8cf6683e5fa318afe9e59a3069f1c82279d9b66edcfd",
+    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "cb393c4f0c0b6ef9c921733267192c01935fec55944c770765e3dcc37d9c20a8",
+    "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "96f017458f94370758b2cfa30f787707f548aeb9ca2dd9a52a43b27c73040b82",
+    "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "aa0b966b0ae33dc01714f16b3e511ae1f60da0a1a0e4de32e09cbe7a5e6a67b3",
+    "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "38f9b818c71bbf607cd0db8e73b539506f42c529fb8a5053860e844914e0ade3",
+    "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "ddfe1cee4f7d8a451ff5d1eb880c3e9ffa3fa1e59a8c12322e46562e379101de",
+    "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "33d5d918ae8d35ecc760bf876573a51d62c98a46eb6c60c2e3ba8acba4ce6488",
+    "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "0424f863ecf6e6d870325539637899720806a4130ffe815c724cdc34d8eb444f",
+    "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "d5e71781a82b424b28b90fe08d2ac4d86b37acd476bc36c106222128202a9476",
+    "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "65f860c74140318eb5c034a04c85e3eabfb31dfa8d70791d701f15d979d50361",
+    "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "034e491668d0f55b1fba9d606c2acb2d7d1d00db528f141207202ec6e5ca4410",
+    "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "f320d08c2116bcf1646f141426785e2b27488e48cf7e0ab97dab39efa4668efd",
+    "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "8bcb363d7dd7656bdeb5525df048dea384b34d564c98e3374c8c82f037e5074d",
+    "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "bbb924b505c82fef0d8912deb95b312d6547f96d15ff7cb06c5d77ee56c6fbbb",
+    "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "056e1662756321e884b84e662b9e465d58187f1fd9227ae4d7a9fce0110ddfb8",
+    "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c01a661eee4e2ab0c93cc6575f8ae56c16b79bd0d5479d9f918004cf8a8abc2b",
+    "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "b74739855529627407a72244de3efd706ed99c347061513a677ebc7fd3b4e7c1",
+    "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "a275d7e95312e868636aa1539de0b2f490973119ffb4863f5534eed395c4113e",
+    "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "4f6326173b50952d933b02cc477156d5aad067798b347ce502889e607e98c84c",
+    "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "86ffca7848946079b62f083a92e47440a431b5c451aca3600efc0a5f3939ba2f",
+    "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "9c9406fcb15e88f93a23d0a275e44559e33b4a2eeab4403cbb2184bdca36318e",
+    "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "99ca6df78a1dfcb0c9a919f0eec47783f95399bae39271a6367c07b8ef346a5a",
+    "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c24493b3e919ec268aa4b98da0a66332fa4e104210ed15b8f6c3b8c240ebeffe",
+    "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "7cfec0a0bae8471a32385a7c19d1ec17dba25ab1d6211cd062df73a9a1c030a2",
+    "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8a8d81661cc1789185be6d4c13ac2ee602194a5526467ab34e4f23243cb9f474",
+    "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b8ada6046b5351a627ae1fb4ee8ba059fa551f1de4444aba1d1915a27371d339",
+    "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "946d2d77ec784019f18372610ff438321e22f7e0d2e0045cc71180f3b2f6d376",
+    "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "2f3756d68b354341f98a3cfa4c89d78bf6e8c631dfb6477fceec5e6b00833d30",
+    "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.gz": "bccb3002b5cc3556555bb05208b7d64b9aee3a7dc3b482c03090ad0102c22570",
+    "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.xz": "a0f7dbfb008cb12bc7a8c9f464715e5aedfae175fdf5bb7bdf3d971072cd9b54",
+    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "26fcc16d533e427eeded47f8c088aaa180602f68043f5dcd84755ac2166f16af",
+    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "d5bc7bc9f2d5d2bbe7167f810b1334a86ddd694d111e145223474f8d6dee00af",
+    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "6f3fe7f685324ff07995e5fb453462a1c4b5dac9208cd23935f6435af9146692",
+    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "86e37578645f4436b7889c3b9c110888a2aff7af2833a7f5f38fa345a6f36e76",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "f0964def1f80732c1a67f0e4258a301ae2ee27d7ea474f70ab44816907a95ec3",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "6a4655c9b902b904b3dd2ca00dd656d0ef99c77e632f6d6ffc615486b4bfa543",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "5aeb8db8c2e5afd80378a0aa1572c57ff021fb5dccb1bd914b994f0ca8764667",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "0892a93f462e70aee33117de90caaa7b7ef363a27e573602c1d606c0309ae2d9",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "e4be5cd72bb220514c73d7da14ff2962dcd74b8602c1724d71538ab11da94132",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "0b643ba40ce6dbb270f85f45b2dd4d727051a896099493166cfad05c9be96b1f",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "998df5339f738815ab7c38b32df00eef09ff0e415a85d2ae2ab1c0836a380906",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "4ca058f973e2d439e812f839e57920dd9e73a0da9f9bf37889c06f3b1755b07e",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "6511df143067a3c3f6f741540f890f3bca46b11c01cda1c92e1708d0be30ebeb",
+    "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "4ebef9830e25fb28e12ea538e17a46cfe0748e6a14cf976048df056ae708b1ea",
+    "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "6af3a7f720d5a7100683636c387865b3d4e9b5148ca04c1238662b81c8bbde9c",
+    "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "459e63b66eb8e53e106896c3003183c5ef3803a8dd3d501d50e6d4e03343ad66",
+    "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.gz": "95c816378d57b5d7336373f7f53b603dd8a4efcf17634d4e008b6bd896947cac",
+    "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.xz": "209caeea6df90996d5239d0900767135bde716387317a10dc348b96aa818a93a",
+    "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.gz": "54ec6a313cc523fc568c4879cf36ab90bade8a1ae9c2ee89bafd57c2c9f3f754",
+    "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.xz": "82de1d66bf9cf226b80fea722d2828f368cbe75bc5d99a524193b50db6003636",
+    "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.gz": "1a08cd54ff716d6ef3e53177e31787e8aa00f948054b42f94d791d3d59aa3169",
+    "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.xz": "32c1b56cc223bab3e7f15de719488c874011dd6be622038ce5b1f7ff03b05c59",
+    "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "62a85f52db02e9afc659e84ea8bc3c8828f6a9fe4c1b58eecc3cefeb99e2d8ac",
+    "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "1e6126312252956f5ad887ca5e8271be3cf31ac8d793071f6af8c2adcdd57f00",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "5542b7e2ee1611f0410e2e962796cd7067e483b37730061a4f788f853f31c7c1",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "97f149839149fcff4004260eb119c1213f10a455b37a8256aec977bc04c9e2c0",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "48dada900d144fc9a17ff273ab44d9c4c5fb0cfbaae986d6396aaa6c9c5c22d5",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "c93b5da1e22138da0a97be32b9498a3ede270253a22a9d9275f610e349438bfb",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "904b39e24f5fe72393f943a5ecb3bfa6e07f3623a0cde911b161558660ee27d9",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "013646fe9e3f640ae820bfccce656c1bc94d0c3856613dbdea8b06574e072ad4",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.gz": "59de57b6902c755a2d92d5aa154452e84c747bc414605cebb367a4a17cf16ae7",
+    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.xz": "9822fd8d21f863018ead909155ed7d931c5a9bb9ac6461c1f19609ad1a206a48",
+    "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.gz": "235bc683a244a69b1f36a875a418efb56af6e1f8411dbace6f9cef3ce1191f7d",
+    "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.xz": "a2d267e75d64e0bb96c9a8b78bb67db4ba46576edc51955108595c17ff285083",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "cc5d42c65ebc2733017a463c5a4903c681fd923dfa820ed6e420950f6c599ba5",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1e9b3e5c0025c15f485eee6a39dc20ea62bfa777a820bd524817eeab07878e67",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5f298d431d03d56112d2527c889d94296c03fb4187bbe26bd0e2be50bc9207ed",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "8be37b928562c4f08342b0661077dca25484d9e12e1e48b375fef02f6699fe87",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "db7d25058f4f39007495e864a20a398d307f9505721c9f5991db6d7065db50ee",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "fc858a2f2b7fe83cd148ee133b952ef8d63a6f39600fb101c7b98d37734484df",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "bc1ab01b0d7783c8cde71c1d4507fbf68330933e86d5b0280426eb9e9103ba38",
+    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "18a1ca7fb88d56832ee5a331c3f3fa38ff2c72ecded3e093f4d6aef5e67e886d",
+    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "3eef0c676173ae40e3b1f900627c953955fdea5b3a24401bf69e9d433c9b0996",
+    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "58cdd696c46434bc0aea39b562aab818da1644da08bb385047b7b83cfedf9334",
+    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "0035c38e059eac51cf8786bfde6162bb27ee8c642260af40646665902f9e4cc8",
+    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "893d2d56614198da58327881684b1edab0a7d849eb8e3d6ba1705c192c98718e",
+    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "489d6080bf6ab3dddfd490cc2c6cd956473389678eafe4b85b88e0ba06dfd73a",
+    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "10ed28b9ce5b2d94492034e707a78d18540b096d1439faf5c7370d29c50ea105",
+    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "febbed115d82f51d8c19b49f89a6fb9f1062826d6283e5877b8327b4b0572671",
+    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0f96c9b4bc3464cef4deeec087da38fc39d2cefb1cff7b413aedb8a79f412dc8",
+    "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "8d407d9ddbe27ac708efb40d12b2292857c49f306afa018fd7df44116ccade3c",
+    "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "253b5f4613369b4431296b1151b7c4228594889ac69674a0e3ef75438120868a",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "11e715bf0082733d94a796ed4e123f7ec77aa5fe0e8d037dd513dd69bc230a2e",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "a2d8a16c08721a406f8132f5deb960b65e38d3235a76b72d5f267b2bddb9ad91",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2351b24b205851ff51e79a228416bb6ea801551050cb791464a0364a56a0133b",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "12da6b0947eebc24ae2a279bad6f1a50d26d57c956cb66840b5db6ef266975e4",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "96d333f046236bbfe809a5526e798197e8416442ddaec5e692aa642dd58f3397",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "f2d5832790120cceda3c07cb2dadb4d4e8e30228ffedbf4988a52573382689c1",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "d71cf49d01b781c55a64b174d4b91906771aeb90e885310576b5d77a068a8961",
+    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "3e9b5c730f855b690103d44929384738748bdbc312fe5f8bdb9cb3fe1d8dc701",
+    "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.gz": "b0464837c6303c85d67ebcf45752ad9c859ea4ff013310c4ae64a2ff318db56b",
+    "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.xz": "13aec30cbdfb84483669a5d5a5d2f465f60692e997a6073d5f749c2950fe6a45",
+    "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.gz": "4c54b72683f8800f77b60889a8e91fe293a21916f756ab6fbe5f1e39884a11b2",
+    "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.xz": "5b917d543bd41f47ac8983cc5f3dfb19515b940eff644c5421f23575d8958e35",
+    "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "305fce68a56206cffb34b4735fbff367b8d1f3131a043f5cf03de1ede9402323",
+    "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "511fe782be16d7402519546af50427fc953f599773466668c0133e3d252874ce",
+    "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "31223e26db1d00219cf78e70c096aaec45a5ba2f2835dcb55edcc1e2e83e28b8",
+    "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "2453e08515943e38def4d65c8278f2d25c5b7dfa7883040346c0824abaab9cb0",
+    "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "1f22b735b50f2ccbb3ba99a27e4901b2da9d408361ad8ce2710ab61dbb6a8c46",
+    "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "e2f31b9933df67a5fdae28f26b38f907fb2607ccfc2a1f2e6b6fd9853eb6eb6a",
+    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "a3d2d4184376f6d398a3b1bfbab881659408340287d61d7f29d70bb167824427",
+    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "3803e83360d67e1866d2dada4f62fbf2a04ac3cbc7c347ba4ce97b2e6adf9ced",
+    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "c2890c8ae6c3bb71811867ab953e774161415d454009d9f36a116c86994a9056",
+    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "671191cab9795d52a7ed9762951de46a89988bb22233b6a0b09e85bdc5e5d904",
+    "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.gz": "3e83c96f73f5b526e3f20939338e0b51a94898ffcfa3c7d08ef72966e9161f71",
+    "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.xz": "8c96f60b63bdcec60ea52cbb3880f2d684b2b96a37b37946a24d893eafb4dc77",
+    "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "760e6deb8aec1185b8127bc012794463eefa87dd48a1fb69e6f79ccad45422e5",
+    "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "82809e4bf5b89cfad4d8c8770deb5c2bab4ed1f17463a09c728c25684b7d2d72",
+    "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "288086c4caf64a38b441937f9d3335b0ef419bb6a2693216b48aefe31c34f7ea",
+    "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "06bb31b48abfbfdf4c627d87717987cb0e721100f952e77435c156bd45eb02a3",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "589d7aeabc268fb06f3fd7ff37dfff434924fe87fb778ffa366a27ebf815a26c",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "b5b7bf0752034c4e79827e2155afbc7b2fd59a5220e8acf9b244023a725f9483",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "94c9450ad3915dd6367833b59e07b66083d653eaa72b3b486676c3475fcca86e",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "014e3abef9cbea6008653ba3e85c7cf074add0bbfa71afa90a9f577f014de19c",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "9897bea4ada2d49e055210699a757f59620d8092e9b40c3eba2dd9fde0205309",
+    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "7c53fbd4643e4f9f5e441a79bdbbf8044b3d35d113ca2ce670462433c9299ce4",
+    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "2d4af2bd5c632de7de1abf556acda7c4897f5475221a7e72d36d70236c90a332",
+    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "f388bb0bbfa4d505101b6f087205cef9593b29d55d04dc0f08629d23df6f4dd5",
+    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "7a35ebffe2858e68c8585c54d980edfb7fd84b3a78856110871d062f58e4c4d9",
+    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "40ca86dbff7248854b86ae2a4c05efa5e240ae40d88a887a2681aa0c4995fad3",
+    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "3d380de1f425c4e022037805b4687567870d84bd06375c26528e5a9529b1f0df",
+    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "15f951100779f6535a25f91b58630951376d9191dabb3405b34a78246bd07d6b",
+    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "d1d2f014a7d0c5b6140d282bf38d5fc4c7a93df0e484d9f893fe3ed25c5cf384",
+    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "7f96e0ebaa820cf927962b0c0c584b4b96d3fd34e90e281162138937f145fde5",
+    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "e6d8a5e5de7328d045ccc4c6457e82282c7b0a23bc35443f402672d94df088ef",
+    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "d015d566ae58d854de39337ddfc31f29cdbb4e87320e20b0fbcc83912415d11f",
+    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "cbbcf7edb5f785d89bc20c287a6dcab69eabbdfff0ed8d9283ea0766d98ccfee",
+    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "4b988afc44729564783300cfd47b1ace974bd8eacb52cc553365fdd07b8b38e7",
+    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "674d244f0d536ff053be6384ee9ba9b80db2cc6d9bd840434d26fabdb259d7be",
+    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "07aa043aac39364935f6758e1d2200d6334b719e4b13ad7bcc9e693cfef90e3c",
+    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "19aa1bc698c24eb1136de2a8ace0b872a472e9fb5b1c1fbd48d03fa8e3dab00b",
+    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "a9db5dfaca379bcb6a2c3bb5c6d6eafe4dace2e814c7edb5fdf6a26595be2538",
+    "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ebe482fecfce4ff0ee9dd514b984b9c04565470ecd7a24d94778d51e31107915",
+    "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "b663ce48f79cf4634d35e8c35f10c2c51d775c906b9c7a46ae6e67d7070e1b21",
+    "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "aeb314e2de96b9d7623a8b58d34fb1d290039b1ad63ad91da5052bbcb8569d66",
+    "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "87731e0ea78d1478f87c50d770618b7feb6d404ae257704a1a622bbfc4a079cc",
+    "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "5eeea41e13e8941e1a7e29dc649cc34fafad8ef01fdeffb133cf0dad6cc57997",
+    "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "3435ba7a88ad51266a32fdba648f1d4a60a918ad396261a03593a409db028f1b",
+    "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d453444ef726401c683042f2d33c70fc078ef79d95d4cbd0f007d41bb8894e2b",
+    "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "ab83c5f5477bb3a800e2054d345ed48bba162c871788f7b187f875652f9e8163",
+    "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "d007269d819f76c53e211c8a2871db177c6f910de463f87ae1cc3d3e3f0d42b8",
+    "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "3bc82447155b9a453abe1788705b61ea41f017048a017d973a41a587b81b4bab",
+    "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5c6b7fb54fa4effd3140848b9f7779b4139971f0666758bff43c8bc93877d962",
+    "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "4043a4dca70b44ff5471a3457fbc85218850ab0dd52bbeef87bc629170f07bc3",
+    "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "aaa6eee8c67c6c666cca044c75e0049fc982442647528263ac87bfd17bddd0e5",
+    "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "ce8633daef8fab199318c26cac981de0a7db1e93a066c05187f4f3165826da6a",
+    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "d5323d5b0a8a9c4f7f688449ac4b39b1b0e30ae26fbdb355ab3477c033e86f74",
+    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e4dd4e3b3fef2434ad5b96d7c966576f9d27cca146bb1df3ec0dea92e65d1234",
+    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "ca1e486ed9b37d64c4c1ff4ade719bd4d75ea42d862a53e7ce5106045498618e",
+    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "b07b65d1df2b7147cfcda1aa8c43b64cb0f29290fe9518569969550fd176399e",
+    "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "3225c1a028dbff77a73c8209417261689dcffff8c9019bfb81d7c2ddf440999d",
+    "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "d219a81bc543d000200f0a11de6db87f5f0b135122150f37782d0e1132669ffc",
+    "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "92a70667972c1fa0e5963ef189a450f65861d779f2251e10884bc9dac3751e2a",
+    "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "31405140b78366c182ebcb02632983017409c3c282a2eac6716d410fc2f6d1a4",
+    "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3f6dfab8290bdd2e12f7a4a8ba0e2b58006e0a0096357077cdd1392e94a81bd7",
+    "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "327a86e0e83ccaac9ebb5458e48906a5e83ec928fc01939758a50ce46c114334",
+    "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "c798402360747dac456746c4fb68de30e702ba6a3a1cea0bd5884546d1c2f714",
+    "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "63a9ebcbb4e97cd80c0c97ba6323614cc69a4ff15904e6120aae970a803b3402",
+    "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "bf1ae6e7ceeee0b9631d638aa33b29fc064699eebf1da192aed0b7c0a98f6866",
+    "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "da183dbff702ab18cf02d34c395c6dc70344b525c0d09bc26a8670b75e6e900a",
+    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "f6c66612b1f500218927504a23eb3df1bd8ff5a6171d576ebb681bb0f426d5c6",
+    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "8364308682a2c6e91b2c7bfacb09dd9a7487c106ae95c489286d13e641ecaaa0",
+    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "711e05b89ab2cf2cc17aa7beeb5bc2aafcd851606a8dd535230e64bc5d232dea",
+    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f444669bde93eae4599db7624f830b031f4d4d116d0344829be3177558a5dfd1",
+    "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "9b4699b67763b7c2691a95c69827f6c8ce8847c64e0806b0c3f36f48848a7e4e",
+    "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "2c038bc6607b115f817859aae07c495d6d2a1bd4cfe9007f36494b9229a68d86",
+    "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "7634d01dfdb18a43bc8a230df711e8254f3bbc214b89844475bfba9eb920a5cf",
+    "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "ba0815d8b0d5600cd09148343bcbfa25004b3092bee1ed0e0673fdf8937ebf62",
+    "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "823ee6535da426700b0aed6a33201873d8b6611248506e436cdddae92a074a06",
+    "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "c4b21b5300959794c811653aa907fd259970b08c41d4ce303384b34783b142cf",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "d71ce2ec3eb040244c017dc7bb40342da106d097a579ab69312f1879d5c446c7",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "05375174c0d6f9480c5b504ee16823a28d2994bea0eee52242cef25f9d7b766d",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "9e9efb15d1718421b5537aca94dbc078d8cf4f1651b0b2e790af5fb0d8592ea4",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "d7ffe70ed73bf689c3edcccc1bfc23ba75737f2d0841d471720d23a67b2cd63e",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "704a086e751b96f1249bd295a9dc45f9aeee0d93bf96d2d6fe00ffaf33af3062",
+    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c7ea8e97a90c4e27f910f8ef1e64885540179dc55ef09e4f5a844bb7ab3d0c9b",
+    "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "2165a0868d21ce1cf10e6360f8384866a985358475cae1bfa74d33d3516db565",
+    "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "6909a1ace7b22fa66b175cbf3de0cc54708f0aa73baa3e2168f3e758698c26c8",
+    "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "dd2eb7f4fb9285c11cdbeddaee20a75179a1588486ccbcb7b6e32971790acaf6",
+    "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "9e51dc30f624af1410a77b4f77f01868ec141d6288b09827f7e3a313b276f78a",
+    "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.gz": "b29b2748928aaf72aa30117cfd8bd9c6c13a6c7255efe1bcbd6bf535aefb1294",
+    "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.xz": "90f58b108a9538e190fd3ecec97581b95c85ed27ebcbf1f4ef85b4e3248db0f5",
+    "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "b6549bfeb4ad3de444ff7afce6baaa34ee7468d41480a86072cd3a26e1191de0",
+    "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "44d77279c9997ebc5f4952fde208de6747f6b95e1887c1ac637f3f5170cda003",
+    "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.gz": "3a69d284711c0eab25a73b6d22a3fd92e6741e22a454d0210694c73c2775e6db",
+    "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.xz": "08b97affa6264d739eb31925f3d4a2fb0feb32e6b3eff770c580782bea216ca0",
+    "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "15334ea58e51d1d5f35f15c75a0f941b3648d9bc2acbb57a6c07b788c78aa6d2",
+    "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "7aad1c1dc41f5713fb9a3414b0cd64b78f3b8cd6bd12a9fe14318cbab5c804aa",
+    "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.gz": "48e706203750b335276140b8156c5c74ed48cd36aa7a6f732f7febe3d517da76",
+    "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.xz": "d0a14f312a2f91961f955352f6e508cdf5e5ac82be10837843ec7c87ed9d3ff9",
+    "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.gz": "12a29451878739ba28838a8bf0eda9ab4826457a6ef249644bbe11e3afbde650",
+    "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.xz": "f2fe871094a8dbd11bf15d9139ca0d630b9fc2c03d1bfed295d1ee01a8484910",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "42237c674c4c5f6181da0eaeffc755a08087b87350770fca6a3d707158cd66f4",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "167aa8827682e3a6c140a7607ede1c0ca90014634940c228dc538263b6e1ea8d",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "7517896917e38d12d3265b0202ea8bd839d8cfd08b9c6b2c6033b5f70d24f049",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "902b1a27c034206fd03457a52eb495c2bed5d3f4355e4d94d1dea05746e10df1",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "3b2143072753553cc05d40e0684fdbabe6eb8c436588ce2f29ca393f3c5a8609",
+    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "47d03efe92f8fcfbdb192565dcf4db4e4c1c301ff4bd8cb15e0ae74c5ee00122",
+    "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "7394b58442de5d444c1fdaef7d91da57f6bd64a50ccd8be518e2e620e0829036",
+    "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "4839a52f87ec51bdf0438dfaeb57f3757b481ad47a7e86db9740d3e86e2c261f",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "a44012100040021f42335ba35be08570c86d72c371783e203fd1a6144d46a6fe",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "7279b03775bd896709700727d9db6030a05a4cad3842c1b225404bd1545a0ba9",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "ee719a8fc9a6a5ba1d47fc5d95ebdc8f692b473ed22202d3315de1aebcbae374",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "a85f334cf580035472b054383365c6da4509aa85a3901e6d30649c3e6f1af4f9",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "96884f6544e2d51034cac32618e4e35ee0c84467d8a80f635d8073980fed0ce6",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "98f745588c290a0319216d067a60ba3665506111bdcc4a773b5b850f9ac8107a",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "cb3249e99fd60a57cdab4a529c14eae3d76fc85768ec9cb9186eeafc32f45214",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "614acd645f9c79eda648236e6f3c028d9bb5482297059bfc93dab9f2e90d1478",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "c7988d678d330d31c3e88df27b9c2b482854d0b7f277f8126e2996a9f4180387",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "11d16c7f5b64e3d4bcfcad489c2710ca7e3cad12c82221848c51ed839688e02b",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "45f880920e746f53810fc70526e18ef807e6d4089ef147bed8c53c536624f646",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "0910b51938eed74ad4af9e07f74ea5648a143fbd142a9cb4fe1bc7f7b7bd6159",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "c14fd257005a11026cc3ebf23fb9f2d35a6d99f9136471574d8c0d18fc66e3b7",
+    "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "9c3438ecac2dfaf827039b506c114bdc06c05a69b81761abfb63f8a227950da7",
+    "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.gz": "357bb650d7377610e61a9ff2167a7fd480ca844322849e5dcc80a91edc5fffa5",
+    "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.xz": "3f0883cd2c1d1bc31dd89a72711ba6a22a1c455f28dc2d5644e70898614a637a",
+    "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "6366923332e491d21b5f448500fd56673fd21738e6edcbdb21c11fafb00723de",
+    "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "b0e7462540e6c96b373f6aebf6ab58ca4c2cc62627c5c5ec8b135516ce9098f9",
+    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "21bdf608d2bc3799206065225410ccbb015a379cbcf79a901e4e9420d1a4feb4",
+    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4b1520615af8f2baad919740716c482cd5ac421bd87e44cde21788e79c996a4c",
+    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "4aece49879bb274f0170b98941fa220d1ae4f1c4cb33c3fa7ae4146679675d1d",
+    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "d3c565f7a2a1bcf21849122c1c6fbbf81ce1e8dbaf103e8f5c406b2f35aadde1",
+    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "311df5769ba9a2889c1e9a97df6c1bd369224832a80789bae339121138e40513",
+    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "e2818874f3f3d873e858e78585e60804971d57e206c023e8a1c82d03cc9ee5b3",
+    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "9bb1e02517abfe3e626812cea2d389b26451db341bd1c56f5c06f90a71936cde",
+    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "fe02b9b389297a781bbdac812ac3526973a221edc2cd7b2be4fcb197e817b148",
+    "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c6733d130bda448d7801caa215d3f58abd6576119eb764a55c326344fcbbdede",
+    "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "0a553a9821eb076873976bf523c8b1278de367854d6fbca0728bde97768c4ec9",
+    "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "c5a724275014bf1c244ff6ab878271747097b3f216e5753e3ca65c1714a2456a",
+    "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "0a6ff560eb1a7d02e48661939bbb940cdb5d988ccacbcbdc0f7fa24890b0d9b2",
+    "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "da487112240ab21c3b3f9d9816e7b4738022f58ba0e93c0772a8fcbb17ba0573",
+    "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "944bd6f24ff92a748c804e3deac1994fe03cda4b897be3eb12f21d069add4cdd",
+    "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "e986624d0a97155a588c9b95c7470c1b322bbae11f9582ad62d2c914642400d9",
+    "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "dbaf95a9b3f6fccab5d59533be35f59b7901b31e61488f85032bd15bfb67eb34",
+    "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "374bd970d5cba1b9af4a36250dfea2eaacafd9e6b4b0d4d9165abdd11841d4c3",
+    "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "2ddec9e30d15f2e1f05e9a59c739f1be51fc8d836acda395aacfb933826a5637",
+    "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "a21a1c099324517b6da6dfd8f2154b4d32bfe69d3a1f386e1bc5be2c3743b938",
+    "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b81fa8c2d534386ceb0bb0767c260e340cda7122e23c834afb17097976ff682d",
+    "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "2822fdb98095c292a4e0b0e6ee3be4e1cc5ffda42dae101b2c6a6c4bb7a1ec4e",
+    "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7d40bef08d3f0d097755eae0b26057f579fd40f4968dd9e5cc82c2b9b67d9c0e",
+    "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f64962ca9b60013ce98e634ebb5207dac14c7b39aca5de37db8a6b3debad7250",
+    "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "a3f8dfb574b3af0ac48011cc7ec69d9f3e89a1994a475c3c6920b0a110db141c",
+    "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6dcce24fa93e66b69495df2d8e9aee15bbba263945fa3dea5cdb1d2c499c9744",
+    "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "038d888fea4ff185329b4ac93066167ec7cfd05a3f23be0a2fae5b8eab51d0ac",
+    "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "6a83680ff659d7b9717639d56eb18c230162ee4983ce5ac4aef78b8d9d0829ef",
+    "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "43313c88c1950ec36549f023d8e7b6c6cccb9749159115dad5255451c65f98c8",
+    "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "635544e9035d213ac7e3a82d08b445b2a446119511c219c0ad870f185133f76d",
+    "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e2fca8f43e37ed2d4896df1429e9b806f02b0e8bdd0f136cf16f606eb1ac15e2",
+    "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "ae8bafeb6423cb270b3a2538db07946d35f2514d5d5116ea085a78e4b80596aa",
+    "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c8abe082666ea792414943eab46d00727acafa97760e799a4d22ec9ff27a810f",
+    "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "b680196dea6eb4bf49afa002e6115645a67c2f7ed6de8ffcc0ace6ed2c193c76",
+    "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "1d3cca881398f45c8ef9db64820cd2afb542b55517c9ea66b71955a31fb7fad1",
+    "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.gz": "493431cd41fae24883877615ca83c1a4e94cafa7e6d6f587dfcce9782c36edaa",
+    "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.xz": "08b5610cc53cfe64914866b115ca15d184df83cf0c8bb65106380bd875bf62cb",
+    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "17c0e93976b2a83df5f6baabd67412389550f3694268e5478440c8579efbbd18",
+    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "0e736cf5ac25a78e611ea89589a8f6f0eda9891646579fe0a0b8853ab210ee19",
+    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "33f17eb3e95e4b00895c234f5d2d2c9ce19d1d36811bebc3f92bcfeed770a6bf",
+    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b26e0adcfeb9b95dce5d39c7d34126a405d9705cf58a6ee560b10eeb274b6ef0",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "27d6e27acb2d060b59e35789b81779f48a520670ad1590cb46b9862a6be74a63",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "39670b9f1865ab74458dded5a9e9f181045c8eb7e7bc82ffc308fcbc5bc26267",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "d970bcce7178cc0ddb96de50450da71b236ab56861efd399da03f916ce059685",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "6d6bda8752a6b205ca8e155624f671e716e80c78256f052c22dc2e53c379b589",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "e667282411745dfa982922d139a26058097250c33e83ca955e75b65c6098f651",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "7ed509f918aed5d259479663911427564c066b41487d4550050a9c07096344d9",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "59b3aac5504deea4daf79d5ee90951c3df5247568419a3605c8895698e7a460c",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "941f93fd0a542b9aa6b35fe26a5145085cf758c10b185e9892acf52796efe944",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "755987f90f50bbcf9881f62849bfc5749e41d95e5d6b2a35c7fce4218ba3dc60",
+    "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "09cead4864a49e750d91438149b74fa4c0d4b923efda40ba638b2ca0d3ad97c6",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "17e7cb26d7c13cc14d826966a4b93e9c152b46f2d7081038e8d3385ed5d3ba43",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "85f896275ecef1d491bb8beab54ab13d612d49fb8386b6b61d9121f52fb15e44",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e948e456f51a9fb983d36d15352d8e7782051e1fb62a4adad2ae973725aa6091",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "d21b59cc2c1706e9c14bf1464b17ed5bd51e2d225e1b3ea53c13d90ae34d4a2d",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "a51b04fa8b159ac5c80ec1db0518cf589a8530820863870173347941a5d3e0e0",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "bbb801bd4ddaeb4d2494039943e8ac746fd41fb625d3c544af2a79587f9e327e",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "8d94c74ac727b381433ff010d6a5b6576d326c88418afb1ee8a67de5731c1bd9",
+    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "da44eae518dc561f89c810d4a5f50da38b938e22542193595be615c147973ee9",
+    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "11e8422a4b4ab386015c54cf488c40297e6b63006989c40b1e4321a325333433",
+    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "b8e835cfd7f32a823ed00d174c4158220b8572c2d76486c60a20cbdad11bb216",
+    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "ff7a412a7923a24cb118979cc772863e6d9844ab6bcc619d9adca6d36b89daf8",
+    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "4fcf56bfbae46ff5cf7c28d787992d5d108231659e447cecbd25035009e0c783",
+    "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "4ae574d1aab0e0c191327fa5ad79a4e9367702ef3fd1655661a8c253bf55b7e3",
+    "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8786f646813f5ab71f5786efa6cc14e567a9dd1b2532b34d9d85ee900dafe68c",
+    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "752fdf667b1f4713b6ad3378a15835902fd7fea200c8d37f28a444dc3616b89d",
+    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "43e401e2112120970c4a7e3dacbc5ea631c1816f27db33a28f5b9cc49e4dd5da",
+    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "6935d612513b61092b36bae3a2cb11c29e05cd8773c65aa61b4451dab8cb9f43",
+    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "326177f9fda4923b010fdbefbb9703aee727b4d2871ffb1cc97321c09fc3ff51",
+    "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "875d3d7fc0e1cfda7b029656b27436f2b9d332b3f46988dba1cfbfd8d244cd7e",
+    "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "4b3e9d27d256cbbe65c0330d557dbcdd6b6144222936680705f9e74deabe80f0",
+    "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "d26a73c2ccaee81d92980a3cca0508abfce7a02f56f25f3bf9c06e6fcf3aa537",
+    "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "3f69c9a1161aeb25f03681e43d35388bf75a0e20e086d6e353911aa839fcd294",
+    "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "401fbf935e3b06e185f4426a655f2d38e058409921486758f60363f92bbc8117",
+    "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "325d89dc02f7aea4803539211c45d8044986d55f7d1331a231b5d0c0ecfe5238",
+    "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "3da7ef60aff98439a1c58d504bc62aac1d2cfa29879a28968c5a61b72e9fa33f",
+    "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "3aa2757120df94d2660b7e909e4a7d66aa73ca9f9b700231d1f21bdea2b0b5db",
+    "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "74a28139895365cdffdece9920ba6fd31a982cd5620342fbdd653084621b7726",
+    "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "7915f9e15b274e938d5e318544322d233434b6554a25ff063181e7f9cc8a8ef9",
+    "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3b56ab5ce09e8f90ee80ccfcfdbc30f52309547b5123ef474a78cbbd6ca64dad",
+    "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dcb27f9d9f425b81d7ac21025eae60b2e5bbb4cb1e2c21e6970f28e5a574cbb6",
+    "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "cb5627d2075b726c4a30b36cdf234371d02f1fe0b545fd50e02b65588b7bbe5f",
+    "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "d7d075dc678d545fedfdff220dd6b9b9c91cbf5b58fd9cb486777c596c20c20f",
+    "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "fe6af0046c2a6cc8c66d0d51590c7a725115fe785b06bed555c9c68dfaf9819f",
+    "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "559b98d646138414c3e0878bdc8245db35c17f9e804ccc0935c4f397672debcd",
+    "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "cda6141eff957bf7f7580b093d261d690fd660961722c37b19c390cb4ce85ecf",
+    "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7c4eaccfd5704b0d6e7dfeb6cd70922625df90391f1e27e48bc75f0e79b3832a",
+    "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1d16189f4fe2c5d6fb572e279eab121408c1d85d5fecb6a3f25b00ed748b8b14",
+    "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "99be46da8f40418b48261e61a645acd4755c132baf9e2f3a2ca64e853daab9ec",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "82daf2631178e46d94ce2a2718327c5e17da755397cfcddaff4b9d695aa88f3a",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6288c9cbf5e33c59597d990bf99c9536414bb73aa0bcedf1175dab4c6dd9d188",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "29e13fd9d3eb61ea609bbb55bc5f36df094623f1f1a154d9554212bf4021b8cb",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c287a80d6388527213d820c22d723fb9e17018425795f499521e7580ed9f6aed",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "2eefa9ae776a7760b3111b39e2c732d2303c4aab2e124cfbef2f7dddc32bdc30",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "a5544207cad0be04393f3a17f8f743340bf468d20a60aa44bbf3b1ea476e54d4",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "b4dfbc422e7b51db45555e6d1b775b214bf633ec6c93303fb7c52e4e25db69e4",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "158c6366adaaaf17d0d40f64a9c8887fc20f1c7600fb31b102fcc3bcbd388221",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "6fda2931d41c4c42b5f59df4a789ff3c2082ff65892e1318439aec555834a34e",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "25a2823ba3668506fe9bb85c1f51d2406b8654c4197d1dc7d88ee19f35e77756",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "2a79c57d33aca5bb6c0cc2497d6853a4df259537ba55acc66460be03c82cc9c0",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "065d95fc9b2d741ba1e8d20b90820a6ad72ce0cb802fd24842aacf01c3a7a589",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "313ea554f824d0176f44406ed70854736eefe94911182396c896ed454a07e6b8",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "23cce7c791cc4f49d5240898803b47f393b5f2f064a3273ffd290a8cf97b7591",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0416a1a4ad3b9c9e1bf7bd67e49f16e7a4011ebd784966f439ac04a87cb4042f",
+    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "64b29ff6dabc46d124ccf08e8fe351a2d46ed527efe98de36d38c0ec59b226cc"
+  }
+}
diff --git a/src/stage0.txt b/src/stage0.txt
deleted file mode 100644 (file)
index 6b1507e..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file describes the stage0 compiler that's used to then bootstrap the Rust
-# compiler itself.
-#
-# Currently Rust always bootstraps from the previous stable release, and in our
-# train model this means that the master branch bootstraps from beta, beta
-# bootstraps from current stable, and stable bootstraps from the previous stable
-# release.
-#
-# If you're looking at this file on the master branch, you'll likely see that
-# rustc is configured to `beta`, whereas if you're looking at a source tarball
-# for a stable release you'll likely see `1.x.0` for rustc, with the previous
-# stable release's version number. `date` is the date where the release we're
-# bootstrapping off was released.
-
-date: 2021-07-29
-rustc: beta
-
-# We use a nightly rustfmt to format the source because it solves some
-# bootstrapping issues with use of new syntax in this repo. If you're looking at
-# the beta/stable branch, this key should be omitted, as we don't want to depend
-# on rustfmt from nightly there.
-rustfmt: nightly-2021-03-25
-
-# When making a stable release the process currently looks like:
-#
-#   1. Produce stable build, upload it to dev-static
-#   2. Produce a beta build from the previous stable build, upload to static
-#   3. Produce a nightly build from previous beta, upload to static
-#   4. Upload stable build to static, publish full release
-#
-# This means that there's a small window of time (a few days) where artifacts
-# are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org.
-# In order to ease this transition we have an extra key which is in the
-# configuration file below. When uncommented this will instruct the bootstrap.py
-# script to download from dev-static.rust-lang.org.
-#
-# This key is typically commented out at all times. If you're looking at a
-# stable release tarball it should *definitely* be commented out. If you're
-# looking at a beta source tarball and it's uncommented we'll shortly comment it
-# out.
-
-#dev: 1
index 0917278875a57ba5c9aa09e6877c828576ee3840..c2e422f80025042d5fa852af81866f4feabd1753 100644 (file)
@@ -93,7 +93,7 @@
 +     bb6: {
           _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
           StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
-          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         goto -> bb23;                    // scope 0 at no-location
 +         goto -> bb20;                    // scope 0 at no-location
       }
 -     bb11: {
 +     bb8: {
           StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -     bb12: {
 +     bb9: {
           StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
-          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 -         falseEdge -> [real: bb2, imaginary: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
 +     bb11: {
           _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
           StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
-          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         goto -> bb23;                    // scope 0 at no-location
 +         goto -> bb20;                    // scope 0 at no-location
       }
 -     bb16: {
 +     bb13: {
           StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -     bb17: {
 +     bb14: {
           StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
-          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 -         falseEdge -> [real: bb4, imaginary: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
 +     bb15: {
           StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
-          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 -         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
index b2fbe225915b0f0aacbc7f20bc058205cfbfb89b..111549d6f3d596739e7aea36567b203194e5d612 100644 (file)
@@ -72,6 +72,7 @@ fn full_tested_match() -> () {
     }
 
     bb7: {
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         StorageLive(_5);                 // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
@@ -81,13 +82,12 @@ fn full_tested_match() -> () {
         _1 = (const 1_i32, move _8);     // scope 2 at $DIR/match_false_edges.rs:16:31: 16:37
         StorageDead(_8);                 // scope 2 at $DIR/match_false_edges.rs:16:36: 16:37
         StorageDead(_5);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
         goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
     }
 
     bb8: {
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
         goto -> bb3;                     // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
     }
index 8ff555dbb871e937055ba9c00c8dcda990585fe1..0953eba16583833021550d5eae8fce476612c64b 100644 (file)
@@ -70,6 +70,7 @@ fn full_tested_match2() -> () {
     }
 
     bb7: {
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         StorageLive(_5);                 // scope 0 at $DIR/match_false_edges.rs:27:14: 27:15
@@ -79,13 +80,12 @@ fn full_tested_match2() -> () {
         _1 = (const 1_i32, move _8);     // scope 2 at $DIR/match_false_edges.rs:27:31: 27:37
         StorageDead(_8);                 // scope 2 at $DIR/match_false_edges.rs:27:36: 27:37
         StorageDead(_5);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
         goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
     }
 
     bb8: {
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
         falseEdge -> [real: bb3, imaginary: bb1]; // scope 0 at $DIR/match_false_edges.rs:27:20: 27:27
     }
index 3fb06cfe6385f429ef1c88dd7b28d7109b3b55fa..a07e257f5494f79962fc9785e1b43b89fd77e3a5 100644 (file)
@@ -78,19 +78,19 @@ fn main() -> () {
     }
 
     bb7: {
+        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         FakeRead(ForGuardBinding, _7);   // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         StorageLive(_6);                 // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
         _6 = ((_2 as Some).0: i32);      // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
         _1 = const 1_i32;                // scope 2 at $DIR/match_false_edges.rs:36:32: 36:33
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
-        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
         StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
         goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
     }
 
     bb8: {
-        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
+        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
         falseEdge -> [real: bb1, imaginary: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:21: 36:28
     }
@@ -122,20 +122,20 @@ fn main() -> () {
 
     bb12: {
         StorageDead(_13);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
+        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         FakeRead(ForGuardBinding, _11);  // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         StorageLive(_10);                // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
         _10 = ((_2 as Some).0: i32);     // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
         _1 = const 3_i32;                // scope 4 at $DIR/match_false_edges.rs:38:33: 38:34
         StorageDead(_10);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
-        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         StorageDead(_11);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
     }
 
     bb13: {
         StorageDead(_13);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
-        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
+        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         StorageDead(_11);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         falseEdge -> [real: bb3, imaginary: bb3]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
     }
index 6cb27d244440dda62d02c17fabc8f9a6b59477c8..89eefa69019a25f70964ea9cacd17a136452be74 100644 (file)
@@ -75,14 +75,14 @@ fn main() -> () {
     }
 
     bb10: {
+        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:18: 13:19
         FakeRead(ForMatchGuard, _8);     // scope 2 at $DIR/match_test.rs:13:18: 13:19
         _3 = const 0_i32;                // scope 2 at $DIR/match_test.rs:13:23: 13:24
-        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:23: 13:24
         goto -> bb14;                    // scope 2 at $DIR/match_test.rs:13:23: 13:24
     }
 
     bb11: {
-        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:23: 13:24
+        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:18: 13:19
         falseEdge -> [real: bb3, imaginary: bb6]; // scope 2 at $DIR/match_test.rs:13:18: 13:19
     }
 
index 4a9982d7699a8fb42f897bbc9c11cf7e2f43507a..0511b59cf013a5a7359f02fdf11b70abdf315cb5 100644 (file)
@@ -66,7 +66,7 @@
 +         _7 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
           StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
 -     }
 - 
 -     bb8: {
index 4a9982d7699a8fb42f897bbc9c11cf7e2f43507a..0511b59cf013a5a7359f02fdf11b70abdf315cb5 100644 (file)
@@ -66,7 +66,7 @@
 +         _7 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
           StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
 -     }
 - 
 -     bb8: {
index eacc99dcf496632f46482177f0e79718f8fc5709..c1ba019f33c6b016a4db5b282a0588cd193b617a 100644 (file)
@@ -47,6 +47,7 @@
       }
   
       bb5: {
+          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 -         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 -         FakeRead(ForMatchGuard, _6);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
           _0 = const 0_i32;                // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
-          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
           goto -> bb7;                     // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
       }
   
       bb6: {
-          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
+          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
           goto -> bb1;                     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
       }
   
diff --git a/src/test/run-make/native-link-modifier-whole-archive/Makefile b/src/test/run-make/native-link-modifier-whole-archive/Makefile
new file mode 100644 (file)
index 0000000..799b5f6
--- /dev/null
@@ -0,0 +1,39 @@
+# ignore-cross-compile -- compiling C++ code does not work well when cross-compiling
+
+# This test case makes sure that native libraries are linked with --whole-archive semantics
+# when the `-bundle,+whole-archive` modifiers are applied to them.
+#
+# The test works by checking that the resulting executables produce the expected output,
+# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work
+# that code would never make it into the final executable and we'd thus be missing some
+# of the output.
+
+-include ../../run-make-fulldeps/tools.mk
+
+all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linked) $(TMPDIR)/$(call BIN,indirectly_linked_via_attr)
+       $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.'
+       $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.'
+       $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.'
+
+# Native lib linked directly into executable
+$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+       $(RUSTC) directly_linked.rs -Z unstable-options -l static:+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib
+       $(RUSTC) indirectly_linked.rs
+
+# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable
+$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib
+       $(RUSTC) indirectly_linked_via_attr.rs
+
+# Native lib linked into rlib with via commandline
+$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+       $(RUSTC) rlib_with_cmdline_native_lib.rs -Z unstable-options --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor
+
+# Native lib linked into rlib via `#[link()]` attribute on extern block.
+$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor)
+       $(RUSTC) native_lib_in_src.rs --crate-type=rlib
+
+$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp
+       $(call COMPILE_OBJ_CXX,$@,$<)
diff --git a/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp
new file mode 100644 (file)
index 0000000..c687eb0
--- /dev/null
@@ -0,0 +1,11 @@
+#include <cstdio>
+
+// Since this is a global variable, its constructor will be called before
+// main() is executed. But only if the object file containing it actually
+// gets linked into the executable.
+struct Foo {
+    Foo() {
+        printf("static-initializer.");
+        fflush(stdout);
+    }
+} FOO;
diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs
new file mode 100644 (file)
index 0000000..17518e8
--- /dev/null
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+fn main() {
+    print!("directly_linked.");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs
new file mode 100644 (file)
index 0000000..c8b83fc
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate rlib_with_cmdline_native_lib;
+
+fn main() {
+    rlib_with_cmdline_native_lib::hello();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs
new file mode 100644 (file)
index 0000000..b9e3476
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate native_lib_in_src;
+
+fn main() {
+    native_lib_in_src::hello();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs
new file mode 100644 (file)
index 0000000..373d89b
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(native_link_modifiers_bundle)]
+#![feature(native_link_modifiers_whole_archive)]
+#![feature(native_link_modifiers)]
+
+use std::io::Write;
+
+#[link(name = "c_static_lib_with_constructor",
+       kind = "static",
+       modifiers = "-bundle,+whole-archive")]
+extern {}
+
+pub fn hello() {
+    print!("native_lib_in_src.");
+    std::io::stdout().flush().unwrap();
+}
diff --git a/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs
new file mode 100644 (file)
index 0000000..ef2b702
--- /dev/null
@@ -0,0 +1,6 @@
+use std::io::Write;
+
+pub fn hello() {
+    print!("indirectly_linked.");
+    std::io::stdout().flush().unwrap();
+}
index ea98676863b5eed119ef38cd56561bb9950b02ea..9e64317ec203f9adc259366fac0427a8d99b2630 100644 (file)
@@ -1,7 +1,7 @@
 // @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
-// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind" \"lifetime\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
 pub struct WithPrimitives<'a> {
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.rs b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
new file mode 100644 (file)
index 0000000..b2e000b
--- /dev/null
@@ -0,0 +1,9 @@
+// This test ensures that rustdoc doesn't panic on higher-ranked lifetimes
+// with bounds, because an error should have already been emitted by rustc.
+
+pub fn hrlt<'b, 'c>()
+where
+    for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+}
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.stderr b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
new file mode 100644 (file)
index 0000000..d8fcd6c
--- /dev/null
@@ -0,0 +1,10 @@
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounded-hr-lifetime.rs:6:13
+   |
+LL |     for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+   |             ^^   ^^
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
index 272911de6815b663ec443b8ae67543c7734c4731..0868486fa59cd017a7d16c6a0c8c275bb345d0e7 100644 (file)
@@ -52,3 +52,21 @@ pub union Baz {
 
 // @!has type_layout/trait.MyTrait.html 'Size: '
 pub trait MyTrait {}
+
+// @has type_layout/enum.Variants.html 'Size: '
+// @has - '2 bytes'
+// @has - '<code>A</code>: 0 bytes'
+// @has - '<code>B</code>: 1 byte'
+pub enum Variants {
+    A,
+    B(u8),
+}
+
+// @has type_layout/enum.WithNiche.html 'Size: '
+// @has - //p '4 bytes'
+// @has - '<code>None</code>: 0 bytes'
+// @has - '<code>Some</code>: 4 bytes'
+pub enum WithNiche {
+    None,
+    Some(std::num::NonZeroU32),
+}
index ff450f60acc683d6cc2ecb05c69944f3f0d2c8e3..610798d880f0a795cd7458726cf3dbaf80253181 100644 (file)
@@ -1,8 +1,14 @@
-error: expected expression, found `+`
+error: leading `+` is not supported
   --> $DIR/issue-36499.rs:4:9
    |
 LL |     2 + +2;
-   |         ^ expected expression
+   |         ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     2 + +2;
+LL +     2 + 2;
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88476.rs b/src/test/ui/closures/2229_closure_analysis/issue-88476.rs
new file mode 100644 (file)
index 0000000..f5906d3
--- /dev/null
@@ -0,0 +1,62 @@
+// edition:2021
+
+#![feature(rustc_attrs)]
+
+// Test that we can't move out of struct that impls `Drop`.
+
+
+use std::rc::Rc;
+
+// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths
+// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop.
+pub fn test1() {
+    struct Foo(Rc<i32>);
+
+    impl Drop for Foo {
+        fn drop(self: &mut Foo) {}
+    }
+
+    let f = Foo(Rc::new(1));
+    let x = #[rustc_capture_analysis] move || {
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+        println!("{:?}", f.0);
+        //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture f[] -> ByValue
+    };
+
+    x();
+}
+
+// Test that we don't restrict precision when moving `Copy` types(i.e. when copying),
+// even if any of the parent paths implement `Drop`.
+fn test2() {
+    struct Character {
+        hp: u32,
+        name: String,
+    }
+
+    impl Drop for Character {
+        fn drop(&mut self) {}
+    }
+
+    let character = Character { hp: 100, name: format!("A") };
+
+    let c = #[rustc_capture_analysis] move || {
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    //~| ERROR: First Pass analysis includes:
+    //~| ERROR: Min Capture analysis includes:
+        println!("{}", character.hp)
+        //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture character[(0, 0)] -> ByValue
+    };
+
+    c();
+
+    println!("{}", character.name);
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88476.stderr b/src/test/ui/closures/2229_closure_analysis/issue-88476.stderr
new file mode 100644 (file)
index 0000000..c7c9ecb
--- /dev/null
@@ -0,0 +1,97 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/issue-88476.rs:20:13
+   |
+LL |     let x = #[rustc_capture_analysis] move || {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/issue-88476.rs:47:13
+   |
+LL |     let c = #[rustc_capture_analysis] move || {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+  --> $DIR/issue-88476.rs:20:39
+   |
+LL |       let x = #[rustc_capture_analysis] move || {
+   |  _______________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Capturing f[(0, 0)] -> ImmBorrow
+  --> $DIR/issue-88476.rs:25:26
+   |
+LL |         println!("{:?}", f.0);
+   |                          ^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/issue-88476.rs:20:39
+   |
+LL |       let x = #[rustc_capture_analysis] move || {
+   |  _______________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Min Capture f[] -> ByValue
+  --> $DIR/issue-88476.rs:25:26
+   |
+LL |         println!("{:?}", f.0);
+   |                          ^^^
+
+error: First Pass analysis includes:
+  --> $DIR/issue-88476.rs:47:39
+   |
+LL |       let c = #[rustc_capture_analysis] move || {
+   |  _______________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Capturing character[(0, 0)] -> ImmBorrow
+  --> $DIR/issue-88476.rs:52:24
+   |
+LL |         println!("{}", character.hp)
+   |                        ^^^^^^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/issue-88476.rs:47:39
+   |
+LL |       let c = #[rustc_capture_analysis] move || {
+   |  _______________________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |
+LL | |     };
+   | |_____^
+   |
+note: Min Capture character[(0, 0)] -> ByValue
+  --> $DIR/issue-88476.rs:52:24
+   |
+LL |         println!("{}", character.hp)
+   |                        ^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88476.rs
new file mode 100644 (file)
index 0000000..f44c2af
--- /dev/null
@@ -0,0 +1,47 @@
+// check-pass
+// edition:2021
+
+use std::rc::Rc;
+
+// Test that we restrict precision when moving not-`Copy` types, if any of the parent paths
+// implement `Drop`. This is to ensure that we don't move out of a type that implements Drop.
+pub fn test1() {
+    struct Foo(Rc<i32>);
+
+    impl Drop for Foo {
+        fn drop(self: &mut Foo) {}
+    }
+
+    let f = Foo(Rc::new(1));
+    let x = move || {
+        println!("{:?}", f.0);
+    };
+
+    x();
+}
+
+
+// Test that we don't restrict precision when moving `Copy` types(i.e. when copying),
+// even if any of the parent paths implement `Drop`.
+pub fn test2() {
+    struct Character {
+        hp: u32,
+        name: String,
+    }
+
+    impl Drop for Character {
+        fn drop(&mut self) {}
+    }
+
+    let character = Character { hp: 100, name: format!("A") };
+
+    let c = move || {
+        println!("{}", character.hp)
+    };
+
+    c();
+
+    println!("{}", character.name);
+}
+
+fn main() {}
index 6f36f2a7510a0ff474554a1ae3ab134b639d1e97..46b128c08fef959a989826852a1d1c3bcb700124 100644 (file)
@@ -5,8 +5,10 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use Lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use Lib::TheTrait;
+   |
 
 error: aborting due to previous error
 
index edfe6348d174e5a741e163fdf7b05f5c06e65832..af0ef3b693262217f7581a2aaa07979df1e8bbbd 100644 (file)
@@ -5,8 +5,10 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use coherence_inherent_cc_lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use coherence_inherent_cc_lib::TheTrait;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-82956.rs b/src/test/ui/const-generics/issues/issue-82956.rs
new file mode 100644 (file)
index 0000000..a3a0d8d
--- /dev/null
@@ -0,0 +1,33 @@
+#![feature(generic_const_exprs, array_map)]
+#![allow(incomplete_features)]
+
+pub struct ConstCheck<const CHECK: bool>;
+
+pub trait True {}
+impl True for ConstCheck<true> {}
+
+pub trait OrdesDec {
+    type Newlen;
+    type Output;
+
+    fn pop(self) -> (Self::Newlen, Self::Output);
+}
+
+impl<T, const N: usize> OrdesDec for [T; N]
+where
+    ConstCheck<{N > 1}>: True,
+    [T; N - 1]: Sized,
+{
+    type Newlen = [T; N - 1];
+    type Output = T;
+
+    fn pop(self) -> (Self::Newlen, Self::Output) {
+        let mut iter = IntoIter::new(self);
+        //~^ ERROR: failed to resolve: use of undeclared type `IntoIter`
+        let end = iter.next_back().unwrap();
+        let new = [(); N - 1].map(move |()| iter.next().unwrap());
+        (new, end)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-82956.stderr b/src/test/ui/const-generics/issues/issue-82956.stderr
new file mode 100644 (file)
index 0000000..c8b999d
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: use of undeclared type `IntoIter`
+  --> $DIR/issue-82956.rs:25:24
+   |
+LL |         let mut iter = IntoIter::new(self);
+   |                        ^^^^^^^^ not found in this scope
+   |
+help: consider importing one of these items
+   |
+LL | use std::array::IntoIter;
+   |
+LL | use std::collections::binary_heap::IntoIter;
+   |
+LL | use std::collections::btree_map::IntoIter;
+   |
+LL | use std::collections::btree_set::IntoIter;
+   |
+     and 8 other candidates
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/const-generics/issues/issue-84659.rs b/src/test/ui/const-generics/issues/issue-84659.rs
new file mode 100644 (file)
index 0000000..440ca74
--- /dev/null
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+trait Bar<const N: usize> {}
+
+trait Foo<'a> {
+    const N: usize;
+    type Baz: Bar<{ Self::N }>;
+    //~^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-84659.stderr b/src/test/ui/const-generics/issues/issue-84659.stderr
new file mode 100644 (file)
index 0000000..2dfc48a
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/issue-84659.rs:8:15
+   |
+LL |     type Baz: Bar<{ Self::N }>;
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-86530.rs b/src/test/ui/const-generics/issues/issue-86530.rs
new file mode 100644 (file)
index 0000000..b024dec
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait X {
+    const Y: usize;
+}
+
+fn z<T>(t: T)
+where
+    T: X,
+    [(); T::Y]: ,
+{
+}
+
+fn unit_literals() {
+    z(" ");
+    //~^ ERROR: the trait bound `&str: X` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86530.stderr b/src/test/ui/const-generics/issues/issue-86530.stderr
new file mode 100644 (file)
index 0000000..7cdfc9d
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `&str: X` is not satisfied
+  --> $DIR/issue-86530.rs:16:7
+   |
+LL |     z(" ");
+   |       ^^^ the trait `X` is not implemented for `&str`
+   |
+note: required by a bound in `z`
+  --> $DIR/issue-86530.rs:10:8
+   |
+LL | fn z<T>(t: T)
+   |    - required by a bound in this
+LL | where
+LL |     T: X,
+   |        ^ required by this bound in `z`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-86535-2.rs b/src/test/ui/const-generics/issues/issue-86535-2.rs
new file mode 100644 (file)
index 0000000..0b535fd
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    const ASSOC_C: usize;
+    fn foo() where [(); Self::ASSOC_C]:;
+}
+
+struct Bar<const N: &'static ()>;
+impl<const N: &'static ()> Foo for Bar<N> {
+    const ASSOC_C: usize = 3;
+
+    fn foo() where [u8; Self::ASSOC_C]: {
+        let _: [u8; Self::ASSOC_C] = loop {};
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86535.rs b/src/test/ui/const-generics/issues/issue-86535.rs
new file mode 100644 (file)
index 0000000..5289c4e
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features, unused_variables)]
+
+struct F<const S: &'static str>;
+impl<const S: &'static str> X for F<{ S }> {
+    const W: usize = 3;
+
+    fn d(r: &[u8; Self::W]) -> F<{ S }> {
+        let x: [u8; Self::W] = [0; Self::W];
+        F
+    }
+}
+
+pub trait X {
+    const W: usize;
+    fn d(r: &[u8; Self::W]) -> Self;
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.rs b/src/test/ui/const-generics/sneaky-array-repeat-expr.rs
new file mode 100644 (file)
index 0000000..b147c24
--- /dev/null
@@ -0,0 +1,32 @@
+trait Trait<const N: usize> {
+    const Assoc: usize;
+}
+
+impl<const N: usize> Trait<N> for () {
+    const Assoc: usize = 1;
+}
+
+
+pub const fn foo<const N: usize>() where (): Trait<N> {
+    let bar = [(); <()>::Assoc];
+    //~^ error: constant expression depends on a generic parameter
+}
+
+trait Trait2<const N: usize> {
+    const Assoc2: usize;
+}
+
+impl<const N: usize> Trait2<N> for () {
+    const Assoc2: usize = N - 1;
+}
+
+
+pub const fn foo2<const N: usize>() where (): Trait2<N> {
+    let bar2 = [(); <()>::Assoc2];
+    //~^ error: constant expression depends on a generic parameter
+}
+
+fn main() {
+    foo::<0>();
+    foo2::<0>();
+}
diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr b/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr
new file mode 100644 (file)
index 0000000..5c77375
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:11:20
+   |
+LL |     let bar = [(); <()>::Assoc];
+   |                    ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:25:21
+   |
+LL |     let bar2 = [(); <()>::Assoc2];
+   |                     ^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
index fd993d0f9d8854059c3bac4facd829919c742dad..1080f947732e4442c23d4720b6850292e9ad066c 100644 (file)
@@ -19,6 +19,10 @@ LL |     Bar::<NotClone> { x: 1 }.clone();
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
+help: consider annotating `NotClone` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.rs b/src/test/ui/editions/dyn-trait-sugg-2021.rs
new file mode 100644 (file)
index 0000000..47c48e7
--- /dev/null
@@ -0,0 +1,12 @@
+// edition:2021
+
+trait Foo<T> {}
+
+impl<T> dyn Foo<T> {
+    fn hi(_x: T)  {}
+}
+
+fn main() {
+    Foo::hi(123);
+    //~^ ERROR trait objects without an explicit `dyn` are deprecated
+}
diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.stderr b/src/test/ui/editions/dyn-trait-sugg-2021.stderr
new file mode 100644 (file)
index 0000000..f6e9fa9
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0783]: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/dyn-trait-sugg-2021.rs:10:5
+   |
+LL |     Foo::hi(123);
+   |     ^^^ help: use `dyn`: `<dyn Foo>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0783`.
index 04babb0644718fa37121e1c1e00876d6d0d923a5..6a1a502749a75eb1e58320688e8f369b15c60768 100644 (file)
@@ -6,7 +6,7 @@ LL | impl<R> External for (Q, R) {}
    |
    = note: conflicting implementation in crate `complex_impl_support`:
            - impl<'a, 'b, 'c, T, U, V, W> External for (T, M<'a, 'b, 'c, Box<U>, V, W>)
-             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: FnOnce<(T,)>, U: 'static, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
+             where <U as FnOnce<(T,)>>::Output == V, <V as Iterator>::Item == T, 'b: 'a, T: 'a, U: 'static, U: FnOnce<(T,)>, V: Iterator, V: Clone, W: Add, <W as Add>::Output: Copy;
 
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
   --> $DIR/complex-impl.rs:9:1
index 98e5cd6bab89351861edeb9f1184ce01ae36325a..22da0dffbf29eb87cf51d02eafa70ea5f6766338 100644 (file)
@@ -440,17 +440,6 @@ note: trait defined here, with 1 lifetime parameter: `'a`
 LL |         trait GenericLifetimeAT<'a> {
    |               ^^^^^^^^^^^^^^^^^ --
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:169:44
-   |
-LL |         type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
-   |                                            ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
-   |               ++++                             +++
-
 error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> $DIR/wrong-number-of-args.rs:169:26
    |
@@ -465,6 +454,17 @@ note: trait defined here, with 0 generic parameters
 LL |         trait GenericLifetimeAT<'a> {
    |               ^^^^^^^^^^^^^^^^^
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:169:44
+   |
+LL |         type C = Box<dyn GenericLifetimeAT<(), AssocTy=()>>;
+   |                                            ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type C<'a> = Box<dyn GenericLifetimeAT<'a, (), AssocTy=()>>;
+   |               ++++                             +++
+
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:181:26
    |
@@ -525,17 +525,6 @@ help: add missing generic argument
 LL |         type C = Box<dyn GenericTypeAT<'static, A, AssocTy=()>>;
    |                                               +++
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:201:48
-   |
-LL |         type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
-   |                                                ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
-   |               ++++                                 +++
-
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:201:26
    |
@@ -552,6 +541,17 @@ help: add missing generic argument
 LL |         type A = Box<dyn GenericLifetimeTypeAT<A, AssocTy=()>>;
    |                                                ++
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:201:48
+   |
+LL |         type A = Box<dyn GenericLifetimeTypeAT<AssocTy=()>>;
+   |                                                ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type A<'a> = Box<dyn GenericLifetimeTypeAT<'a, AssocTy=()>>;
+   |               ++++                                 +++
+
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:207:26
    |
@@ -609,17 +609,6 @@ help: consider introducing a named lifetime parameter
 LL |         type D<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), AssocTy=()>>;
    |               ++++                                 +++
 
-error[E0106]: missing lifetime specifier
-  --> $DIR/wrong-number-of-args.rs:221:48
-   |
-LL |         type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
-   |                                                ^ expected named lifetime parameter
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
-   |               ++++                                 +++
-
 error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:221:26
    |
@@ -634,6 +623,17 @@ note: trait defined here, with 1 generic parameter: `A`
 LL |         trait GenericLifetimeTypeAT<'a, A> {
    |               ^^^^^^^^^^^^^^^^^^^^^     -
 
+error[E0106]: missing lifetime specifier
+  --> $DIR/wrong-number-of-args.rs:221:48
+   |
+LL |         type E = Box<dyn GenericLifetimeTypeAT<(), (), AssocTy=()>>;
+   |                                                ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type E<'a> = Box<dyn GenericLifetimeTypeAT<'a, (), (), AssocTy=()>>;
+   |               ++++                                 +++
+
 error[E0107]: this trait takes 1 lifetime argument but 2 lifetime arguments were supplied
   --> $DIR/wrong-number-of-args.rs:227:26
    |
@@ -767,17 +767,6 @@ help: add missing lifetime argument
 LL |         type B = Box<dyn GenericLifetimeLifetimeAT<'static, 'b, AssocTy=()>>;
    |                                                           ++++
 
-error[E0106]: missing lifetime specifiers
-  --> $DIR/wrong-number-of-args.rs:279:56
-   |
-LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
-   |                                                        ^ expected 2 lifetime parameters
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |         type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
-   |               ++++                                         +++++++
-
 error[E0107]: this trait takes 1 generic argument but 0 generic arguments were supplied
   --> $DIR/wrong-number-of-args.rs:279:26
    |
@@ -794,6 +783,17 @@ help: add missing generic argument
 LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<A, AssocTy=()>>;
    |                                                        ++
 
+error[E0106]: missing lifetime specifiers
+  --> $DIR/wrong-number-of-args.rs:279:56
+   |
+LL |         type A = Box<dyn GenericLifetimeLifetimeTypeAT<AssocTy=()>>;
+   |                                                        ^ expected 2 lifetime parameters
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |         type A<'a> = Box<dyn GenericLifetimeLifetimeTypeAT<'a, 'a, AssocTy=()>>;
+   |               ++++                                         +++++++
+
 error[E0107]: this trait takes 2 lifetime arguments but 1 lifetime argument was supplied
   --> $DIR/wrong-number-of-args.rs:285:26
    |
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
new file mode 100644 (file)
index 0000000..112227c
--- /dev/null
@@ -0,0 +1,70 @@
+// check-pass
+// edition:2018
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>;
+
+fn main() {
+    f();
+}
+
+async fn f() {
+    run("dependency").await;
+}
+
+struct InMemoryStorage;
+
+struct User<'dep> {
+    dep: &'dep str,
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+    fn execute(&self) -> BoxFuture<Result<(), String>> {
+        todo!()
+    }
+}
+
+trait Storage {
+    type Error;
+}
+
+impl Storage for InMemoryStorage {
+    type Error = String;
+}
+
+trait StorageRequestReturnType {
+    type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+    fn execute(
+        &self,
+    ) -> BoxFuture<Result<<Self as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+struct SaveUser<'a> {
+    name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+    type Output = ();
+}
+
+impl<'dep> User<'dep> {
+    async fn save<S>(self)
+    where
+        S: Storage,
+        for<'a> SaveUser<'a>: StorageRequest<S>,
+    {
+        SaveUser { name: "Joe" }
+            .execute()
+            .await;
+    }
+}
+
+async fn run<S>(dep: &str)
+where
+    S: Storage,
+    for<'a> SaveUser<'a>: StorageRequest<S>,
+{
+    User { dep }.save().await;
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs
new file mode 100644 (file)
index 0000000..6316cee
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Bar {
+    type Type;
+}
+struct Foo<'a>(&'a ());
+impl<'a> Bar for Foo<'a> {
+    type Type = ();
+}
+
+fn func<'a>(_: <Foo<'a> as Bar>::Type) {}
+fn assert_is_func<A>(_: fn(A)) {}
+
+fn test()
+where
+    for<'a> <Foo<'a> as Bar>::Type: Sized,
+{
+    assert_is_func(func);
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs
new file mode 100644 (file)
index 0000000..f6ab9c2
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub trait Indexable {
+    type Idx;
+}
+impl Indexable for u8 {
+    type Idx = u8;
+}
+impl Indexable for u16 {
+    type Idx = u16;
+}
+
+pub trait Indexer<T: Indexable>: std::ops::Index<T::Idx, Output = T> {}
+
+trait StoreIndex: Indexer<u8> + Indexer<u16> {}
+
+fn foo(st: &impl StoreIndex) -> &dyn StoreIndex {
+    st as &dyn StoreIndex
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
new file mode 100644 (file)
index 0000000..3a4d6c0
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(unboxed_closures)]
+
+trait SomeTrait<'a> {
+    type Associated;
+}
+
+fn give_me_ice<T>() {
+    callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+    //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied
+}
+
+fn callee<T: Fn<(&'static (),)>>() {
+    println!("{}", std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>());
+}
+
+fn main() {
+    give_me_ice::<()>();
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
new file mode 100644 (file)
index 0000000..aaf45dc
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
+  --> $DIR/issue-85455.rs:8:5
+   |
+LL |     callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn give_me_ice<T: SomeTrait<'_>>() {
+   |                 +++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 4f49b3106edc405b9b3c709d368f25f16ae3d035..0e9b63d6370d6738d2d3c51d9cdff0baea1077a9 100644 (file)
@@ -23,9 +23,11 @@ LL |         ().clone()
    |            ^^^^^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use std::clone::Clone;`
    = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use std::clone::Clone;
+   |
 
 error: aborting due to 2 previous errors
 
index f16bb80dbb8568dbf5897d24f0dfa3b2679eca0f..77ab6e589e07c00f7011a7bf38a5d21d6a34d79e 100644 (file)
@@ -11,9 +11,11 @@ LL |     pub macro m() { ().f() }
    |                        ^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use foo::T;`
    = note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use foo::T;
+   |
 
 error: aborting due to previous error
 
index eb32c8db3f6687b384c2d577eff99e555a257748..0ccf69dc0607615580af4d1ee77df8d12710ff69 100644 (file)
@@ -5,8 +5,10 @@ LL |             b.foo();
    |               ^^^ method not found in `&B`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use a::A;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |         use a::A;
+   |
 
 error: aborting due to previous error
 
index 9be4eb1c7fddba3307fbfb6d71237240ed236bd7..2a1f1819c33cd8e796d82ee001f82de181b563f5 100644 (file)
@@ -5,9 +5,12 @@ LL | struct NonCopyable(());
    |        ----------- `NonCopyable` defined here
 ...
 LL |     let z = NonCopyable{ p: () };
-   |             -----------  ^ field does not exist
-   |             |
-   |             help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)`
+   |                          ^ field does not exist
+   |
+help: `NonCopyable` is a tuple struct, use the appropriate syntax
+   |
+LL |     let z = NonCopyable(/* fields */);
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index 22a660b4167d38186fa7f684591e6a13b4981ca0..38e46683b0823d59449583d37c6ebd528f300972 100644 (file)
@@ -5,9 +5,12 @@ LL |     V1(i32),
    |     -- `Enum::V1` defined here
 ...
 LL |     Enum::V1 { x }
-   |     --------   ^ field does not exist
-   |     |
-   |     help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
+   |                ^ field does not exist
+   |
+help: `Enum::V1` is a tuple variant, use the appropriate syntax
+   |
+LL |     Enum::V1(/* fields */)
+   |     ~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr
new file mode 100644 (file)
index 0000000..5a1294f
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0308]: mismatched types
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r T,)>`
+              found type `Fn<(&T,)>`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0310.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs b/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs
new file mode 100644 (file)
index 0000000..f833845
--- /dev/null
@@ -0,0 +1,13 @@
+//! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely
+//! recognized as E0308 mismatched types.
+
+use std::convert::identity;
+
+fn main() {}
+
+fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
+}
+
+fn g<T>(data: &[T]) {
+    f(data, identity) //~ ERROR implementation of `FnOnce` is not general
+}
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
new file mode 100644 (file)
index 0000000..d972861
--- /dev/null
@@ -0,0 +1,11 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
+
+error: aborting due to previous error
+
index 05d7d924c8fabe0aa762309665c09358d27db06f..c66037e9a73ae6d01acbe5e466208575ff956df7 100644 (file)
@@ -21,8 +21,6 @@ fn forbid_first(num: i32) -> i32 {
     #![deny(unused)]
     //~^ ERROR: deny(unused) incompatible with previous forbid
     //~| WARNING being phased out
-    //~| ERROR: deny(unused) incompatible with previous forbid
-    //~| WARNING being phased out
     #![warn(unused)]
     #![allow(unused)]
 
index 475410cecffa30b105a618f9924fa93ef502bb62..5093715decfc1925e96768f19644de41d785fe20 100644 (file)
@@ -14,16 +14,5 @@ LL | #![forbid(forbidden_lint_groups)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
-error: deny(unused) incompatible with previous forbid
-  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
-   |
-LL |     #![forbid(unused)]
-   |               ------ `forbid` level set here
-LL |     #![deny(unused)]
-   |             ^^^^^^ overruled by previous forbid
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 486ec3c46804fb0f0d01f760baa7c4c4b5cdfaa7..ba330258d111fff04c092114e60f2c60dde5c321 100644 (file)
 #![forbid(unused, non_snake_case)]
 #![forbid(forbidden_lint_groups)]
 
-#[allow(unused_variables)] //~ ERROR incompatible with previous
+#[allow(unused_variables)]
 //~^ ERROR incompatible with previous
 //~| WARNING this was previously accepted by the compiler
-//~| WARNING this was previously accepted by the compiler
 fn foo() {}
 
 #[allow(unused)] //~ ERROR incompatible with previous
index d69157a8bb3adc9d316d331c3810bc4348702c26..7814573210548e291b541a967bd2097625438b21 100644 (file)
@@ -16,7 +16,7 @@ LL | #![forbid(forbidden_lint_groups)]
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
 error: allow(unused) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:26:9
+  --> $DIR/outer-forbid.rs:25:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
@@ -28,7 +28,7 @@ LL | #[allow(unused)]
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
 error[E0453]: allow(nonstandard_style) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:30:9
+  --> $DIR/outer-forbid.rs:29:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
@@ -36,18 +36,6 @@ LL | #![forbid(unused, non_snake_case)]
 LL | #[allow(nonstandard_style)]
    |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: allow(unused_variables) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:20:9
-   |
-LL | #![forbid(unused, non_snake_case)]
-   |           ------ `forbid` level set here
-...
-LL | #[allow(unused_variables)]
-   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
index cf011653c204160674f2e596fe2e2863624ca893..d7af0c4248056de175194e77fb867f7de58c2b50 100644 (file)
@@ -11,6 +11,7 @@ trait Trait<'a> {}
 
 struct S4<T>(T) where for<'a> T: ?Trait<'a>;
 //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared
+//~| WARN default bound relaxed for a type parameter
 
 struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
 //~^ ERROR type parameter has more than one relaxed default bound
index 0ef8e9e9c795a92fb1631e240ff4a0934e2c9352..2aa6a8a38223df4d5401f433ce649bc558515360 100644 (file)
@@ -23,23 +23,29 @@ LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
    |                               ^
 
 error: `?Trait` bounds are only permitted at the point where a type parameter is declared
-  --> $DIR/maybe-bounds-where.rs:20:18
+  --> $DIR/maybe-bounds-where.rs:21:18
    |
 LL |     fn f() where T: ?Sized {}
    |                  ^
 
+warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
+  --> $DIR/maybe-bounds-where.rs:12:11
+   |
+LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>;
+   |           ^
+
 error[E0203]: type parameter has more than one relaxed default bound, only one is supported
-  --> $DIR/maybe-bounds-where.rs:15:11
+  --> $DIR/maybe-bounds-where.rs:16:11
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
    |           ^
 
 warning: default bound relaxed for a type parameter, but this does nothing because the given bound is not a default; only `?Sized` is supported
-  --> $DIR/maybe-bounds-where.rs:15:11
+  --> $DIR/maybe-bounds-where.rs:16:11
    |
 LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
    |           ^
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0203`.
index 1030061b2d1feb737ee5cd4470cbfd0c0a35373e..596b7bfe79c5c56ed7d60abd088da1ad98d344e9 100644 (file)
@@ -9,6 +9,10 @@ LL |     a.unwrap();
    |
    = note: the following trait bounds were not satisfied:
            `Foo: Debug`
+help: consider annotating `Foo` with `#[derive(Debug)]`
+   |
+LL | #[derive(Debug)]
+   |
 
 error: aborting due to previous error
 
index a2beb368b6e60aebdcfc85ddac4a58c4d0751d16..da436b89f538e511d0a6339f33594c201e6ce21e 100644 (file)
@@ -2,7 +2,7 @@
 // arms whose patterns were composed solely of constants to not have
 // them linked in the cfg.
 //
-// THis was broken for various reasons. In particular, that hack was
+// This was broken for various reasons. In particular, that hack was
 // originally authored under the assunption that other checks
 // elsewhere would ensure that the two patterns did not overlap.  But
 // that assumption did not hold, at least not in the long run (namely,
diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs
new file mode 100644 (file)
index 0000000..c3714a3
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-flags: -Zunstable-options --crate-type rlib
+// build-fail
+// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+#![feature(native_link_modifiers)]
+#![feature(native_link_modifiers_bundle)]
+#![feature(native_link_modifiers_whole_archive)]
+
+#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")]
+extern "C" { }
+
+fn main() { }
diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr
new file mode 100644 (file)
index 0000000..246efb8
--- /dev/null
@@ -0,0 +1,6 @@
+error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+error: could not find native static library `mylib`, perhaps an -L flag is missing?
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs
new file mode 100644 (file)
index 0000000..1d0768d
--- /dev/null
@@ -0,0 +1,7 @@
+// Mixing +bundle and +whole-archive is not allowed
+
+// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib
+// build-fail
+// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+fn main() { }
diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr
new file mode 100644 (file)
index 0000000..246efb8
--- /dev/null
@@ -0,0 +1,6 @@
+error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs
+
+error: could not find native static library `mylib`, perhaps an -L flag is missing?
+
+error: aborting due to 2 previous errors
+
index 13b6cfae4ec476584dd1deaeacbf908b89c6b087..b328fbe2cfb87a90c625b488bf7bb865bdb838b9 100644 (file)
@@ -5,9 +5,12 @@ LL | struct S(u8, u16);
    |        - `S` defined here
 ...
 LL |     let s = S{0b1: 10, 0: 11};
-   |             - ^^^ field does not exist
-   |             |
-   |             help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
+   |               ^^^ field does not exist
+   |
+help: `S` is a tuple struct, use the appropriate syntax
+   |
+LL |     let s = S(/* fields */);
+   |             ~~~~~~~~~~~~~~~
 
 error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:7:17
index cec6980c008c4c9cc74350c2abd46e4afc5bd3ac..d38b98a19011709225dc8765f46739ada2e50b9a 100644 (file)
@@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `]`
   --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
@@ -24,7 +25,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `)`
   --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
@@ -38,7 +40,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `)`
   --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
@@ -52,7 +55,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
@@ -60,7 +64,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    |                                 ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
@@ -68,7 +73,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    |                                 ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
@@ -82,7 +88,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    |                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
@@ -90,7 +97,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    |                                        ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
@@ -98,7 +106,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    |                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
@@ -106,7 +115,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    |                                        ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `..`
   --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
@@ -126,7 +136,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    |                                         ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
@@ -134,7 +145,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |                                             ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
@@ -151,7 +163,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
@@ -174,7 +187,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
@@ -200,7 +214,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:57:45
@@ -217,7 +232,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:61:48
@@ -240,7 +256,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:67:53
@@ -266,7 +283,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:74:32
@@ -276,7 +294,8 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    |                        |
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:76:32
@@ -286,37 +305,56 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    |                        |
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); }
+   | 
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; }
+   | 
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; }
+   | 
 
 error[E0586]: inclusive range with no end
   --> $DIR/attr-stmt-expr-attr-bad.rs:88:35
index 400a0276b3b608f8719535175c3ad846dd52b2c4..3cec61fe41eea9170d3bbfcb4743c47d4e02d7d9 100644 (file)
@@ -3,8 +3,16 @@ error: an inner attribute is not permitted in this context
    |
 LL | #![lang = "foo"]
    | ^^^^^^^^^^^^^^^^
+LL |
+LL | fn foo() {}
+   | ----------- the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![lang = "foo"]
+LL + #[lang = "foo"]
+   | 
 
 error[E0522]: definition of an unknown language item: `foo`
   --> $DIR/attr.rs:5:1
index be52a0afd46b76ca90ec86cac02c774467656b54..b7c1847fc7c0dfe7bd0c7c0b8b06c7facdb25563 100644 (file)
@@ -5,6 +5,11 @@ LL |     if true /*!*/ {}
    |             ^^^^^
    |
    = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL -     if true /*!*/ {}
+LL +     if true /**/ {}
+   | 
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/doc-comment-in-if-statement.rs:2:13
index c217ab9774fd23c63c2f2096c61326a46fb8c8c7..5f5e25991e0cc732dffa898cf5ede8fe6785476c 100644 (file)
@@ -10,7 +10,7 @@ fn foo() -> i32 {
 }
 
 fn bar() -> i32 {
-    ({2}) + 2 //~ ERROR expected expression, found `+`
+    ({2}) + 2 //~ ERROR leading `+` is not supported
     //~^ ERROR mismatched types
 }
 
index b04025faaec63caabf71a1c9d8fdf47a38860f28..5428e1c32fed3edbe0a9bef2cf7c890b3ce6246e 100644 (file)
@@ -10,7 +10,7 @@ fn foo() -> i32 {
 }
 
 fn bar() -> i32 {
-    {2} + 2 //~ ERROR expected expression, found `+`
+    {2} + 2 //~ ERROR leading `+` is not supported
     //~^ ERROR mismatched types
 }
 
index ba5cd01abfcc78a334f40a76e95e83187ba3bb4b..d99e9be0000c312ef65101aef774f070e78f8cd2 100644 (file)
@@ -9,11 +9,11 @@ help: parentheses are required to parse this as an expression
 LL |     ({2}) + {2}
    |     +   +
 
-error: expected expression, found `+`
+error: leading `+` is not supported
   --> $DIR/expr-as-stmt.rs:13:9
    |
 LL |     {2} + 2
-   |         ^ expected expression
+   |         ^ unexpected `+`
    |
 help: parentheses are required to parse this as an expression
    |
index c1e9e7a427f89696d50a8f6b2a46166c7a9f908c..404800ee15bdda66cd866cf80de57b7a161ab4c1 100644 (file)
@@ -8,8 +8,16 @@ LL | |  */
 LL | 
 LL |   #![recursion_limit="100"]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
+LL |
+LL |   fn main() {}
+   |   ------------ the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![recursion_limit="100"]
+LL + #[recursion_limit="100"]
+   | 
 
 error: aborting due to previous error
 
index e1bf2cca1c9635b5303b19a03a0b01c98abe5d05..1adac74590881d078877bedb31adcae2444a5168 100644 (file)
@@ -6,8 +6,15 @@ LL | #[feature(lang_items)]
 LL | 
 LL | #![recursion_limit="100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
+LL | fn main() {}
+   | ------------ the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![recursion_limit="100"]
+LL + #[recursion_limit="100"]
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-30318.fixed b/src/test/ui/parser/issue-30318.fixed
new file mode 100644 (file)
index 0000000..71fc821
--- /dev/null
@@ -0,0 +1,27 @@
+// run-rustfix
+#![allow(unused)]
+fn foo() { }
+
+/// Misplaced comment...
+//~^ ERROR expected outer doc comment
+fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+#[test] //~ ERROR an inner attribute is not permitted in this context
+fn baz() { } //~ NOTE the inner attribute doesn't annotate this function
+//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually
+
+/** Misplaced comment... */
+//~^ ERROR expected outer doc comment
+fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+fn main() { }
+
+// Misplaced comment...
+//~^ ERROR expected outer doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+//~| NOTE other attributes here
+/* Misplaced comment... */
+//~^ ERROR expected outer doc comment
+//~| NOTE this doc comment doesn't document anything
+//~| ERROR expected item after doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
index 38e30de716d0a1491977966b0795b3148e851934..465dca2ff82247e12efb75dc9d15c6941ae56a36 100644 (file)
@@ -1,7 +1,27 @@
+// run-rustfix
+#![allow(unused)]
 fn foo() { }
 
 //! Misplaced comment...
 //~^ ERROR expected outer doc comment
-//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+#![test] //~ ERROR an inner attribute is not permitted in this context
+fn baz() { } //~ NOTE the inner attribute doesn't annotate this function
+//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually
+
+/*! Misplaced comment... */
+//~^ ERROR expected outer doc comment
+fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function
 
 fn main() { }
+
+//! Misplaced comment...
+//~^ ERROR expected outer doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+//~| NOTE other attributes here
+/*! Misplaced comment... */
+//~^ ERROR expected outer doc comment
+//~| NOTE this doc comment doesn't document anything
+//~| ERROR expected item after doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
index b3a27f19851711db634f74fcfa146856ee6d212d..7e7108845546a1e1bf47b545f62c44c6556af4c6 100644 (file)
@@ -1,11 +1,81 @@
 error[E0753]: expected outer doc comment
-  --> $DIR/issue-30318.rs:3:1
+  --> $DIR/issue-30318.rs:5:1
+   |
+LL | //! Misplaced comment...
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn bar() { }
+   | ------------ the inner doc comment doesn't annotate this function
+   |
+help: to annotate the function, change the doc comment from inner to outer style
+   |
+LL | /// Misplaced comment...
+   |   ~
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/issue-30318.rs:9:1
+   |
+LL | #![test]
+   | ^^^^^^^^
+LL | fn baz() { }
+   | ------------ the inner attribute doesn't annotate this function
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![test]
+LL + #[test]
+   | 
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:13:1
+   |
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn bat() { }
+   | ------------ the inner doc comment doesn't annotate this function
+   |
+help: to annotate the function, change the doc comment from inner to outer style
+   |
+LL | /** Misplaced comment... */
+   |   ~
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:19:1
    |
 LL | //! Misplaced comment...
    | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL - //! Misplaced comment...
+LL + // Misplaced comment...
+   | 
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:23:1
+   |
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL - /*! Misplaced comment... */
+LL + /* Misplaced comment... */
+   | 
+
+error: expected item after doc comment
+  --> $DIR/issue-30318.rs:23:1
+   |
+LL | //! Misplaced comment...
+   | ------------------------ other attributes here
+...
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
 
-error: aborting due to previous error
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0753`.
index f242c1d29372f2ae4a04718b0f1b4164008efa14..d3a97e89f9abb229372b1a8b5e98aefdddf0e474 100644 (file)
@@ -2,4 +2,5 @@ fn main() {
     let unused = ();
 
     #![allow(unused_variables)] //~ ERROR not permitted in this context
+    fn foo() {}
 }
index c0d4ce1243e015f0dee62a0a8ab701602600286a..6abe266d4e90eae5405c331f5e3ed99b72929d09 100644 (file)
@@ -3,8 +3,15 @@ error: an inner attribute is not permitted in this context
    |
 LL |     #![allow(unused_variables)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo() {}
+   |     ----------- the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL -     #![allow(unused_variables)]
+LL +     #[allow(unused_variables)]
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-88276-unary-plus.fixed b/src/test/ui/parser/issue-88276-unary-plus.fixed
new file mode 100644 (file)
index 0000000..25b7c34
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+#[allow(unused_parens)]
+fn main() {
+    let _ = 1; //~ ERROR leading `+` is not supported
+    let _ = (1.0 + 2.0) * 3.0; //~ ERROR leading `+` is not supported
+                           //~| ERROR leading `+` is not supported
+    let _ = [3, 4+6]; //~ ERROR leading `+` is not supported
+}
diff --git a/src/test/ui/parser/issue-88276-unary-plus.rs b/src/test/ui/parser/issue-88276-unary-plus.rs
new file mode 100644 (file)
index 0000000..11b2e9d
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+#[allow(unused_parens)]
+fn main() {
+    let _ = +1; //~ ERROR leading `+` is not supported
+    let _ = (1.0 + +2.0) * +3.0; //~ ERROR leading `+` is not supported
+                           //~| ERROR leading `+` is not supported
+    let _ = [+3, 4+6]; //~ ERROR leading `+` is not supported
+}
diff --git a/src/test/ui/parser/issue-88276-unary-plus.stderr b/src/test/ui/parser/issue-88276-unary-plus.stderr
new file mode 100644 (file)
index 0000000..b267617
--- /dev/null
@@ -0,0 +1,50 @@
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:4:13
+   |
+LL |     let _ = +1;
+   |             ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = +1;
+LL +     let _ = 1;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:5:20
+   |
+LL |     let _ = (1.0 + +2.0) * +3.0;
+   |                    ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = (1.0 + +2.0) * +3.0;
+LL +     let _ = (1.0 + 2.0) * +3.0;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:5:28
+   |
+LL |     let _ = (1.0 + +2.0) * +3.0;
+   |                            ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = (1.0 + +2.0) * +3.0;
+LL +     let _ = (1.0 + +2.0) * 3.0;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:7:14
+   |
+LL |     let _ = [+3, 4+6];
+   |              ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = [+3, 4+6];
+LL +     let _ = [3, 4+6];
+   | 
+
+error: aborting due to 4 previous errors
+
index 808903d9c62f3e559d80db61cc8eff9b05cf6fc3..bf4005698a3d61da810e0ff781b3682998e98d39 100644 (file)
@@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context
 LL |     let a = #![allow(warnings)] (1, 2);
    |             ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:10:14
@@ -12,7 +13,8 @@ error: an inner attribute is not permitted in this context
 LL |     let b = (#![allow(warnings)] 1, 2);
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:15:10
@@ -20,7 +22,8 @@ error: an inner attribute is not permitted in this context
 LL |         (#![allow(warnings)] 1, 2)
    |          ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:21:18
@@ -28,7 +31,8 @@ error: an inner attribute is not permitted in this context
 LL |         let e = (#![allow(warnings)] 1, 2);
    |                  ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:26:14
@@ -36,7 +40,8 @@ error: an inner attribute is not permitted in this context
 LL |     let e = [#![allow(warnings)] 1, 2];
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:29:14
@@ -44,7 +49,8 @@ error: an inner attribute is not permitted in this context
 LL |     let f = [#![allow(warnings)] 1; 0];
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:36:24
@@ -52,7 +58,8 @@ error: an inner attribute is not permitted in this context
 LL |     let h = MyStruct { #![allow(warnings)] field: 0 };
    |                        ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed
new file mode 100644 (file)
index 0000000..426a5fa
--- /dev/null
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+// run-rustfix
+
+#[macro_use]
+extern crate test_macros;
+
+/// Inner doc comment
+//~^ ERROR expected outer doc comment
+#[derive(Empty)]
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
+
+fn main() {}
index 8be1ae77738e9cdc2d8dc6703c021e728fe8f38d..31e3f3c859236718060cd339080330d95c4b7b20 100644 (file)
@@ -1,4 +1,5 @@
 // aux-build:test-macros.rs
+// run-rustfix
 
 #[macro_use]
 extern crate test_macros;
@@ -6,6 +7,6 @@
 //! Inner doc comment
 //~^ ERROR expected outer doc comment
 #[derive(Empty)]
-pub struct Foo;
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
 
 fn main() {}
index 0b2e612ee5bb96b18803c75d4855aa77002da3d6..a92f07522e5f21e04b20e3ef9a64a7a9cd69be49 100644 (file)
@@ -1,10 +1,16 @@
 error[E0753]: expected outer doc comment
-  --> $DIR/issue-86781-bad-inner-doc.rs:6:1
+  --> $DIR/issue-86781-bad-inner-doc.rs:7:1
    |
 LL | //! Inner doc comment
    | ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | pub struct Foo;
+   | --------------- the inner doc comment doesn't annotate this struct
    |
-   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: to annotate the struct, change the doc comment from inner to outer style
+   |
+LL | /// Inner doc comment
+   |   ~
 
 error: aborting due to previous error
 
index 2cf5a073fe5c22334a30fb79d4f5b1c06f826b5f..eb4e43aaec35b4814876287c9268e0500e23c1dc 100644 (file)
@@ -8,8 +8,10 @@ LL |         x.foobar();
    |           ^^^^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use crate::foo::foobar::Foobar;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use crate::foo::foobar::Foobar;
+   |
 
 error[E0599]: no method named `bar` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:28:7
index e60f9c039be36cd746be8f8bff1ada996bc9bef9..e4662b430dccc7bdd9131fc4996955c95b5fde11 100644 (file)
@@ -15,9 +15,6 @@ LL |     fn try_into(self) -> Result<T, Self::Error>;
    |        the method is available for `Rc<u8>` here
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
-           candidate #1: `use crate::m::TryIntoU32;`
-           candidate #2: `use std::convert::TryInto;`
 help: consider wrapping the receiver expression with the appropriate type
    |
 LL |         let _: u32 = Box::new(3u8).try_into().unwrap();
@@ -34,6 +31,12 @@ help: consider wrapping the receiver expression with the appropriate type
    |
 LL |         let _: u32 = Rc::new(3u8).try_into().unwrap();
    |                      ++++++++   +
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+   |
+LL |     use crate::m::TryIntoU32;
+   |
+LL |     use std::convert::TryInto;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.rs b/src/test/ui/suggestions/derive-trait-for-method-call.rs
new file mode 100644 (file)
index 0000000..25043da
--- /dev/null
@@ -0,0 +1,44 @@
+use std::time::Instant;
+
+enum Enum {
+    First
+}
+
+#[derive(Clone)]
+enum CloneEnum {
+    First
+}
+
+struct Struct {
+}
+
+#[derive(Clone)]
+struct CloneStruct {
+}
+
+struct Foo<X, Y> (X, Y);
+impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> {
+    fn test(&self) -> (X, Y) {
+        (self.0, self.1)
+    }
+}
+
+fn test1() {
+    let x = Foo(Enum::First, CloneEnum::First);
+    let y = x.test();
+    //~^the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test2() {
+    let x = Foo(Struct{}, CloneStruct{});
+    let y = x.test();
+    //~^the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn test3() {
+    let x = Foo(Vec::<Enum>::new(), Instant::now());
+    let y = x.test();
+    //~^the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied [E0599]
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr
new file mode 100644 (file)
index 0000000..97fc113
--- /dev/null
@@ -0,0 +1,84 @@
+error[E0599]: the method `test` exists for struct `Foo<Enum, CloneEnum>`, but its trait bounds were not satisfied
+  --> $DIR/derive-trait-for-method-call.rs:28:15
+   |
+LL | enum Enum {
+   | ---------
+   | |
+   | doesn't satisfy `Enum: Clone`
+   | doesn't satisfy `Enum: Default`
+...
+LL | enum CloneEnum {
+   | -------------- doesn't satisfy `CloneEnum: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+   | ------------------------ method `test` not found for this
+...
+LL |     let y = x.test();
+   |               ^^^^ method cannot be called on `Foo<Enum, CloneEnum>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `Enum: Clone`
+           `Enum: Default`
+           `CloneEnum: Default`
+help: consider annotating `Enum` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
+
+error[E0599]: the method `test` exists for struct `Foo<Struct, CloneStruct>`, but its trait bounds were not satisfied
+  --> $DIR/derive-trait-for-method-call.rs:34:15
+   |
+LL | struct Struct {
+   | -------------
+   | |
+   | doesn't satisfy `Struct: Clone`
+   | doesn't satisfy `Struct: Default`
+...
+LL | struct CloneStruct {
+   | ------------------ doesn't satisfy `CloneStruct: Default`
+...
+LL | struct Foo<X, Y> (X, Y);
+   | ------------------------ method `test` not found for this
+...
+LL |     let y = x.test();
+   |               ^^^^ method cannot be called on `Foo<Struct, CloneStruct>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `Struct: Clone`
+           `Struct: Default`
+           `CloneStruct: Default`
+help: consider annotating `CloneStruct` with `#[derive(Default)]`
+   |
+LL | #[derive(Default)]
+   |
+help: consider annotating `Struct` with `#[derive(Clone, Default)]`
+   |
+LL | #[derive(Clone, Default)]
+   |
+
+error[E0599]: the method `test` exists for struct `Foo<Vec<Enum>, Instant>`, but its trait bounds were not satisfied
+  --> $DIR/derive-trait-for-method-call.rs:40:15
+   |
+LL | struct Foo<X, Y> (X, Y);
+   | ------------------------ method `test` not found for this
+...
+LL |     let y = x.test();
+   |               ^^^^ method cannot be called on `Foo<Vec<Enum>, Instant>` due to unsatisfied trait bounds
+   |
+  ::: $SRC_DIR/std/src/time.rs:LL:COL
+   |
+LL | pub struct Instant(time::Instant);
+   | ---------------------------------- doesn't satisfy `Instant: Default`
+   |
+  ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+   |
+LL | pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
+   | ------------------------------------------------------------------------------------------------ doesn't satisfy `Vec<Enum>: Clone`
+   |
+   = note: the following trait bounds were not satisfied:
+           `Vec<Enum>: Clone`
+           `Instant: Default`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs
new file mode 100644 (file)
index 0000000..308adcf
--- /dev/null
@@ -0,0 +1,18 @@
+pub struct S(f32, f32);
+
+pub enum E {
+    V(f32, f32),
+}
+
+fn main() {
+    let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+    //~^ ERROR struct `S` has no field named `x`
+    //~| ERROR struct `S` has no field named `y`
+    //~| ERROR struct `S` has no field named `x`
+    //~| ERROR struct `S` has no field named `y`
+    let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+    //~^ ERROR variant `E::V` has no field named `x`
+    //~| ERROR variant `E::V` has no field named `y`
+    //~| ERROR variant `E::V` has no field named `x`
+    //~| ERROR variant `E::V` has no field named `y`
+}
diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr
new file mode 100644 (file)
index 0000000..948f09f
--- /dev/null
@@ -0,0 +1,116 @@
+error[E0560]: struct `S` has no field named `x`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:8:19
+   |
+LL | pub struct S(f32, f32);
+   |            - `S` defined here
+...
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+   |                   ^ field does not exist
+   |
+help: `S` is a tuple struct, use the appropriate syntax
+   |
+LL |     let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:8:27
+   |
+LL | pub struct S(f32, f32);
+   |            - `S` defined here
+...
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+   |                           ^ field does not exist
+   |
+help: `S` is a tuple struct, use the appropriate syntax
+   |
+LL |     let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `x`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:8:41
+   |
+LL | pub struct S(f32, f32);
+   |            - `S` defined here
+...
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+   |                                         ^ field does not exist
+   |
+help: `S` is a tuple struct, use the appropriate syntax
+   |
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+   |                                     ~~~~~~~~~~~~~~~
+
+error[E0560]: struct `S` has no field named `y`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:8:49
+   |
+LL | pub struct S(f32, f32);
+   |            - `S` defined here
+...
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 });
+   |                                                 ^ field does not exist
+   |
+help: `S` is a tuple struct, use the appropriate syntax
+   |
+LL |     let _x = (S { x: 1.0, y: 2.0 }, S(/* fields */));
+   |                                     ~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:13:22
+   |
+LL |     V(f32, f32),
+   |     - `E::V` defined here
+...
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+   |                      ^ field does not exist
+   |
+help: `E::V` is a tuple variant, use the appropriate syntax
+   |
+LL |     let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:13:30
+   |
+LL |     V(f32, f32),
+   |     - `E::V` defined here
+...
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+   |                              ^ field does not exist
+   |
+help: `E::V` is a tuple variant, use the appropriate syntax
+   |
+LL |     let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
+   |               ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `x`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:13:47
+   |
+LL |     V(f32, f32),
+   |     - `E::V` defined here
+...
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+   |                                               ^ field does not exist
+   |
+help: `E::V` is a tuple variant, use the appropriate syntax
+   |
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+   |                                        ~~~~~~~~~~~~~~~~~~
+
+error[E0559]: variant `E::V` has no field named `y`
+  --> $DIR/nested-non-tuple-tuple-struct.rs:13:55
+   |
+LL |     V(f32, f32),
+   |     - `E::V` defined here
+...
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 });
+   |                                                       ^ field does not exist
+   |
+help: `E::V` is a tuple variant, use the appropriate syntax
+   |
+LL |     let _y = (E::V { x: 1.0, y: 2.0 }, E::V(/* fields */));
+   |                                        ~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0559, E0560.
+For more information about an error, try `rustc --explain E0559`.
diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.rs b/src/test/ui/traits/vtable/vtable-non-object-safe.rs
new file mode 100644 (file)
index 0000000..45b6a8a
--- /dev/null
@@ -0,0 +1,18 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+// Ensure that non-object-safe methods in Iterator does not generate
+// vtable entries.
+
+#[rustc_dump_vtable]
+trait A: Iterator {}
+//~^ error Vtable
+
+impl<T> A for T where T: Iterator {}
+
+fn foo(_a: &mut dyn A<Item=u8>) {
+}
+
+fn main() {
+    foo(&mut vec![0, 1, 2, 3].into_iter());
+}
diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr
new file mode 100644 (file)
index 0000000..f3175b8
--- /dev/null
@@ -0,0 +1,16 @@
+error: Vtable entries for `<std::vec::IntoIter<u8> as A>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<std::vec::IntoIter<u8> as Iterator>::next),
+    Method(<std::vec::IntoIter<u8> as Iterator>::size_hint),
+    Method(<std::vec::IntoIter<u8> as Iterator>::advance_by),
+    Method(<std::vec::IntoIter<u8> as Iterator>::nth),
+]
+  --> $DIR/vtable-non-object-safe.rs:8:1
+   |
+LL | trait A: Iterator {}
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index ebea94171f2ab698ac32f42f79921b945f9182e3..429ce523799f3e0faa4bd1d93ac4956884ab2132 100644 (file)
@@ -1,22 +1,25 @@
 // build-fail
 #![feature(rustc_attrs)]
+#![feature(negative_impls)]
+#![allow(where_clauses_object_safety)]
 
 // B --> A
 
 #[rustc_dump_vtable]
 trait A {
     fn foo_a1(&self) {}
-    fn foo_a2(&self) where Self: Sized {}
+    fn foo_a2(&self) where Self: Send {}
 }
 
 #[rustc_dump_vtable]
 trait B: A {
     //~^ error Vtable
     fn foo_b1(&self) {}
-    fn foo_b2() where Self: Sized {}
+    fn foo_b2(&self) where Self: Send {}
 }
 
 struct S;
+impl !Send for S {}
 
 impl A for S {}
 impl B for S {}
index 768cca526894ac81ecd6f1ade8e0140fc4234b89..f5cd36264fcff94e5a17668c667412e3c23dc376 100644 (file)
@@ -7,12 +7,12 @@ error: Vtable entries for `<S as B>`: [
     Method(<S as B>::foo_b1),
     Vacant,
 ]
-  --> $DIR/vtable-vacant.rs:13:1
+  --> $DIR/vtable-vacant.rs:15:1
    |
 LL | / trait B: A {
 LL | |
 LL | |     fn foo_b1(&self) {}
-LL | |     fn foo_b2() where Self: Sized {}
+LL | |     fn foo_b2(&self) where Self: Send {}
 LL | | }
    | |_^
 
index eb16fa9d5660b49fa5c90344a539ef42afa061e2..7faede4e6d0a9ac40af902e954e3191861237f2b 100644 (file)
@@ -5,8 +5,10 @@ LL |         x.deref();
    |           ^^^^^ method not found in `&()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use std::ops::Deref;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use std::ops::Deref;
+   |
 
 error: aborting due to previous error
 
index b52117cd19cca32b262e4228f63bd1f42c56dfa1..146a627bcdef7f160476cd730dd6bc69443debfd 100644 (file)
@@ -16,6 +16,10 @@ LL |     let w = u.clone();
    = note: the following trait bounds were not satisfied:
            `CloneNoCopy: Copy`
            which is required by `U5<CloneNoCopy>: Clone`
+help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
+   |
+LL | #[derive(Copy)]
+   |
 
 error[E0277]: the trait bound `U1: Copy` is not satisfied
   --> $DIR/union-derive-clone.rs:6:10
index b52117cd19cca32b262e4228f63bd1f42c56dfa1..146a627bcdef7f160476cd730dd6bc69443debfd 100644 (file)
@@ -16,6 +16,10 @@ LL |     let w = u.clone();
    = note: the following trait bounds were not satisfied:
            `CloneNoCopy: Copy`
            which is required by `U5<CloneNoCopy>: Clone`
+help: consider annotating `CloneNoCopy` with `#[derive(Copy)]`
+   |
+LL | #[derive(Copy)]
+   |
 
 error[E0277]: the trait bound `U1: Copy` is not satisfied
   --> $DIR/union-derive-clone.rs:6:10
index 8e0804ebf9be93401918c40519db312a6c9eaaf6..02ce371c8d5efa136448224f9615cf977cc8a7ae 100644 (file)
@@ -21,6 +21,10 @@ LL | | >(Unique<T>, A);
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
+help: consider annotating `R` with `#[derive(Clone)]`
+   |
+LL | #[derive(Clone)]
+   |
 
 error: aborting due to previous error
 
diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml
new file mode 100644 (file)
index 0000000..7d64e20
--- /dev/null
@@ -0,0 +1,14 @@
+[package]
+name = "bump-stage0"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.34"
+curl = "0.4.38"
+indexmap = { version = "1.7.0", features = ["serde"] }
+serde = { version = "1.0.125", features = ["derive"] }
+serde_json = "1.0.59"
+toml = "0.5.7"
diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs
new file mode 100644 (file)
index 0000000..96d3c87
--- /dev/null
@@ -0,0 +1,204 @@
+use anyhow::Error;
+use curl::easy::Easy;
+use indexmap::IndexMap;
+use std::collections::HashMap;
+use std::convert::TryInto;
+
+const DIST_SERVER: &str = "https://static.rust-lang.org";
+const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo"];
+const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview"];
+
+struct Tool {
+    channel: Channel,
+    version: [u16; 3],
+    checksums: IndexMap<String, String>,
+}
+
+impl Tool {
+    fn new() -> Result<Self, Error> {
+        let channel = match std::fs::read_to_string("src/ci/channel")?.trim() {
+            "stable" => Channel::Stable,
+            "beta" => Channel::Beta,
+            "nightly" => Channel::Nightly,
+            other => anyhow::bail!("unsupported channel: {}", other),
+        };
+
+        // Split "1.42.0" into [1, 42, 0]
+        let version = std::fs::read_to_string("src/version")?
+            .trim()
+            .split('.')
+            .map(|val| val.parse())
+            .collect::<Result<Vec<_>, _>>()?
+            .try_into()
+            .map_err(|_| anyhow::anyhow!("failed to parse version"))?;
+
+        Ok(Self { channel, version, checksums: IndexMap::new() })
+    }
+
+    fn update_json(mut self) -> Result<(), Error> {
+        std::fs::write(
+            "src/stage0.json",
+            format!(
+                "{}\n",
+                serde_json::to_string_pretty(&Stage0 {
+                    comment: "Generated by `./x.py run src/tools/bump-stage0`. \
+                              Run that command again to update the bootstrap compiler.",
+                    dist_server: DIST_SERVER.into(),
+                    compiler: self.detect_compiler()?,
+                    rustfmt: self.detect_rustfmt()?,
+                    checksums_sha256: {
+                        // Keys are sorted here instead of beforehand because values in this map
+                        // are added while filling the other struct fields just above this block.
+                        self.checksums.sort_keys();
+                        self.checksums
+                    }
+                })?
+            ),
+        )?;
+        Ok(())
+    }
+
+    // Currently Rust always bootstraps from the previous stable release, and in our train model
+    // this means that the master branch bootstraps from beta, beta bootstraps from current stable,
+    // and stable bootstraps from the previous stable release.
+    //
+    // On the master branch the compiler version is configured to `beta` whereas if you're looking
+    // at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous
+    // release's version number.
+    fn detect_compiler(&mut self) -> Result<Stage0Toolchain, Error> {
+        let channel = match self.channel {
+            Channel::Stable | Channel::Beta => {
+                // The 1.XX manifest points to the latest point release of that minor release.
+                format!("{}.{}", self.version[0], self.version[1] - 1)
+            }
+            Channel::Nightly => "beta".to_string(),
+        };
+
+        let manifest = fetch_manifest(&channel)?;
+        self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
+        Ok(Stage0Toolchain {
+            date: manifest.date,
+            version: if self.channel == Channel::Nightly {
+                "beta".to_string()
+            } else {
+                // The version field is like "1.42.0 (abcdef1234 1970-01-01)"
+                manifest.pkg["rust"]
+                    .version
+                    .split_once(' ')
+                    .expect("invalid version field")
+                    .0
+                    .to_string()
+            },
+        })
+    }
+
+    /// We use a nightly rustfmt to format the source because it solves some bootstrapping issues
+    /// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided,
+    /// as we don't want to depend on rustfmt from nightly there.
+    fn detect_rustfmt(&mut self) -> Result<Option<Stage0Toolchain>, Error> {
+        if self.channel != Channel::Nightly {
+            return Ok(None);
+        }
+
+        let manifest = fetch_manifest("nightly")?;
+        self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
+        Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() }))
+    }
+
+    fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> {
+        let prefix = format!("{}/", DIST_SERVER);
+        for component in components {
+            let pkg = manifest
+                .pkg
+                .get(*component)
+                .ok_or_else(|| anyhow::anyhow!("missing component from manifest: {}", component))?;
+            for target in pkg.target.values() {
+                for pair in &[(&target.url, &target.hash), (&target.xz_url, &target.xz_hash)] {
+                    if let (Some(url), Some(sha256)) = pair {
+                        let url = url
+                            .strip_prefix(&prefix)
+                            .ok_or_else(|| {
+                                anyhow::anyhow!("url doesn't start with dist server base: {}", url)
+                            })?
+                            .to_string();
+                        self.checksums.insert(url, sha256.clone());
+                    }
+                }
+            }
+        }
+        Ok(())
+    }
+}
+
+fn main() -> Result<(), Error> {
+    let tool = Tool::new()?;
+    tool.update_json()?;
+    Ok(())
+}
+
+fn fetch_manifest(channel: &str) -> Result<Manifest, Error> {
+    Ok(toml::from_slice(&http_get(&format!(
+        "{}/dist/channel-rust-{}.toml",
+        DIST_SERVER, channel
+    ))?)?)
+}
+
+fn http_get(url: &str) -> Result<Vec<u8>, Error> {
+    let mut data = Vec::new();
+    let mut handle = Easy::new();
+    handle.fail_on_error(true)?;
+    handle.url(url)?;
+    {
+        let mut transfer = handle.transfer();
+        transfer.write_function(|new_data| {
+            data.extend_from_slice(new_data);
+            Ok(new_data.len())
+        })?;
+        transfer.perform()?;
+    }
+    Ok(data)
+}
+
+#[derive(Debug, PartialEq, Eq)]
+enum Channel {
+    Stable,
+    Beta,
+    Nightly,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct Stage0 {
+    #[serde(rename = "__comment")]
+    comment: &'static str,
+    dist_server: String,
+    compiler: Stage0Toolchain,
+    rustfmt: Option<Stage0Toolchain>,
+    checksums_sha256: IndexMap<String, String>,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct Stage0Toolchain {
+    date: String,
+    version: String,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct Manifest {
+    date: String,
+    pkg: HashMap<String, ManifestPackage>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct ManifestPackage {
+    version: String,
+    target: HashMap<String, ManifestTargetPackage>,
+}
+
+#[derive(Debug, serde::Deserialize)]
+struct ManifestTargetPackage {
+    available: bool,
+    url: Option<String>,
+    hash: Option<String>,
+    xz_url: Option<String>,
+    xz_hash: Option<String>,
+}
index 62a119d662bb251f1cb3a0af16dff3b8817bc41a..5dcf1824ef0b7e3d387d0507f8f987a0ccf011df 100644 (file)
@@ -3,9 +3,9 @@
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, GenericArg};
 use rustc_lint::LateContext;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
-use rustc_target::abi::LayoutOf;
 
 use super::CAST_PTR_ALIGNMENT;
 
index 685dbf26250ce2b82aeafd95de9933831e6fc603..1ba241d37761675150a31b80e2e30cc4dc76023e 100644 (file)
@@ -5,11 +5,11 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, TraitRef, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
 use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
@@ -171,7 +171,8 @@ fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
                 // skip if there is a `self` parameter binding to a type
                 // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
                 if let Some(trait_self_ty) = self.trait_self_ty {
-                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty) {
+                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty)
+                    {
                         return;
                     }
                 }
index 3b28b1212048a1b20de55a1e613858fb236c76cd..b1f70b30c12cf1c1605b09ac48cf9fc9891fad3e 100644 (file)
@@ -2,10 +2,10 @@
 
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, IntTy, UintTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
-use rustc_target::abi::LayoutOf;
 
 use clippy_utils::comparisons::Rel;
 use clippy_utils::consts::{constant, Constant};
index 5d4e06c2af08247cfab92f51b4274eba66210b38..10281496c11cbb4e65887c6ea5e17447d17a2ab3 100644 (file)
@@ -1,10 +1,10 @@
-use crate::rustc_target::abi::LayoutOf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span};
index cde2336b690fd04753a06b56f8298b0e998b4bea..e4b8e7546283b460f6f40da388ae8b3c51453d3c 100644 (file)
@@ -6,8 +6,8 @@
 use rustc_hir::{Item, ItemKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_target::abi::LayoutOf;
 
 declare_clippy_lint! {
     /// ### What it does
index 7088630bfdbb45f56c27a73aedfc043127f84894..bbb6c1f902ce077e7fcfc6f168021f71fb356cde 100644 (file)
@@ -4,11 +4,10 @@
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-use crate::rustc_target::abi::LayoutOf;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for local arrays that may be too large.
index 2fddea7068d961f45d14a81bb3961c1377cce7f0..7ecafa1f3ba5b90d4766902cd46f04adb729f22f 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::LayoutOf;
 
 pub fn check(
     cx: &LateContext<'_>,
index 157b18c1f6b1fb8a8287c653f54827552aef5cf9..6229b9608b3cbe5aad07d6316c374f70e30f2cff 100644 (file)
 use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
 use rustc_target::spec::Target;
 
index 7a444174626f47378e020cf6459a90c717c03565..e7e2016d8f2f3de1eb7c9809111036b3cf5b36f8 100644 (file)
@@ -5,9 +5,9 @@
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TypeFoldable;
 use rustc_span::symbol::sym;
-use rustc_target::abi::LayoutOf;
 use rustc_typeck::hir_ty_to_ty;
 
 use super::VEC_BOX;
index 95a45fa937f11ab8d9a7f79fa4eae96016bad9d8..e76d5f81c9640403a75295f93c55bdb7ba6c78fa 100644 (file)
@@ -1,4 +1,3 @@
-use crate::rustc_target::abi::LayoutOf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
@@ -8,6 +7,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
index 2fbe27f94798b08d753b996d689f238320fad5da..8e1cd655b6111c5cb1a66d4abac0fa13deaee7b1 100644 (file)
@@ -3,10 +3,10 @@
 use if_chain::if_chain;
 use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::{Adt, Ty, TypeFoldable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_target::abi::LayoutOf as _;
 use rustc_typeck::hir_ty_to_ty;
 
 declare_clippy_lint! {
index e48451acfe8f5f4c67f76c65298e40b9a463e9f5..7752a8a6ff2b4094a3089d3295d77b4d2a44f597 100644 (file)
@@ -106,24 +106,6 @@ LL |         1 => 2,
    |         ^
    = help: ...or consider changing the match arm bodies
 
-error: this `match` has identical arm bodies
-  --> $DIR/match_same_arms.rs:33:14
-   |
-LL |         3 => 2, //~ ERROR 3rd matched arms have same body
-   |              ^
-   |
-note: same as this
-  --> $DIR/match_same_arms.rs:32:14
-   |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
-   |              ^
-help: consider refactoring into `2 | 3`
-  --> $DIR/match_same_arms.rs:32:9
-   |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
-   |         ^
-   = help: ...or consider changing the match arm bodies
-
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:50:55
    |
@@ -142,5 +124,5 @@ LL |                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: ...or consider changing the match arm bodies
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
index 2b2c699733852dd464507708dc41ad79a15b92eb..34f762bbb923648996cb56af20e84dba18b4fb47 100644 (file)
@@ -46,12 +46,6 @@ LL |     const ONE: u32 = 1 * 1;
    |
    = note: `-D clippy::identity-op` implied by `-D warnings`
 
-error: the operation is ineffective. Consider reducing it to `1`
-  --> $DIR/modulo_one.rs:13:22
-   |
-LL |     const ONE: u32 = 1 * 1;
-   |                      ^^^^^
-
 error: any number modulo 1 will be 0
   --> $DIR/modulo_one.rs:17:5
    |
@@ -70,5 +64,5 @@ error: any number modulo -1 will panic/overflow or result in 0
 LL |     INT_MIN % NEG_ONE; // also caught by rustc
    |     ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
index 96065699d321a057f9a8e28bf07ad3e4551ee282..dd6f2f6641d678b14b1d401fac951d98ce43f913 100644 (file)
@@ -6,12 +6,6 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |
    = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
 
-error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:14:9
-   |
-LL |         self.x == other.y && self.y == other.y && self.z == other.z
-   |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
-
 error: this sequence of operators looks suspiciously like a bug
   --> $DIR/suspicious_operation_groupings.rs:27:20
    |
@@ -162,5 +156,5 @@ error: this sequence of operators looks suspiciously like a bug
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
 
-error: aborting due to 27 previous errors
+error: aborting due to 26 previous errors
 
index 09cadcbb62a3529801d0463d9878db3f0b5060c7..7a2f1cadcd5120c44eda3596053de767cd8173a2 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 09cadcbb62a3529801d0463d9878db3f0b5060c7
+Subproject commit 7a2f1cadcd5120c44eda3596053de767cd8173a2
index a82a0527057eab59c24a0452add35ccb39584e80..bf88026f11f2cc7bb9fefdfe1dbcab642f110afa 160000 (submodule)
@@ -1 +1 @@
-Subproject commit a82a0527057eab59c24a0452add35ccb39584e80
+Subproject commit bf88026f11f2cc7bb9fefdfe1dbcab642f110afa
index 996300f4a061e895a339a909fddce94f68ce7d19..b73b321478d3b2a98d380eb79de717e01620c4e9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 996300f4a061e895a339a909fddce94f68ce7d19
+Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
index 870f0acfe395c527bd0e0a6fee9c833073e766ba..2965b0928aadaf751663bad5017ecfbf93101057 100644 (file)
@@ -311,6 +311,7 @@ fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnost
                 suggestions: vec![],
                 span: span.unwrap_or_else(MultiSpan::new),
                 sort_span: DUMMY_SP,
+                is_lint: false,
             }
         }