]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #100713 - Xiretza:parser-expr-session-diagnostics, r=estebank
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>
Mon, 22 Aug 2022 15:04:14 +0000 (20:34 +0530)
committerGitHub <noreply@github.com>
Mon, 22 Aug 2022 15:04:14 +0000 (20:34 +0530)
Convert diagnostics in parser/expr to SessionDiagnostic

This migrates all the easy cases in `rustc_parse::parser::expr` to `SessionDiagnostic`s, I've left things such as `multipart_suggestion`s out for now in the hopes of a derive API being developed soon.

387 files changed:
.gitignore
Cargo.lock
compiler/rustc_arena/src/lib.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/ast_traits.rs
compiler/rustc_ast/src/attr/mod.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_passes/Cargo.toml
compiler/rustc_ast_passes/src/ast_validation.rs
compiler/rustc_ast_passes/src/errors.rs [new file with mode: 0644]
compiler/rustc_ast_passes/src/lib.rs
compiler/rustc_borrowck/src/type_check/canonical.rs
compiler/rustc_borrowck/src/type_check/free_region_relations.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/assert/context.rs
compiler/rustc_builtin_macros/src/deriving/clone.rs
compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
compiler/rustc_builtin_macros/src/deriving/debug.rs
compiler/rustc_builtin_macros/src/deriving/decodable.rs
compiler/rustc_builtin_macros/src/deriving/default.rs
compiler/rustc_builtin_macros/src/deriving/encodable.rs
compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
compiler/rustc_builtin_macros/src/deriving/hash.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/global_allocator.rs
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
compiler/rustc_builtin_macros/src/standard_library_imports.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_builtin_macros/src/test_harness.rs
compiler/rustc_codegen_cranelift/example/alloc_system.rs
compiler/rustc_codegen_gcc/example/alloc_system.rs
compiler/rustc_data_structures/src/map_in_place.rs
compiler/rustc_data_structures/src/thin_vec.rs
compiler/rustc_data_structures/src/transitive_relation.rs
compiler/rustc_data_structures/src/transitive_relation/tests.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_messages/locales/en-US/ast_passes.ftl [new file with mode: 0644]
compiler/rustc_error_messages/locales/en-US/borrowck.ftl
compiler/rustc_error_messages/locales/en-US/expand.ftl
compiler/rustc_error_messages/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/config.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/module.rs
compiler/rustc_expand/src/placeholders.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/note.rs
compiler/rustc_infer/src/infer/free_regions.rs
compiler/rustc_infer/src/infer/outlives/env.rs
compiler/rustc_infer/src/infer/outlives/obligations.rs
compiler/rustc_lint/src/early.rs
compiler/rustc_lint_defs/src/lib.rs
compiler/rustc_macros/src/diagnostics/utils.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/generics.rs
compiler/rustc_middle/src/ty/list.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_dataflow/src/framework/mod.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/attr.rs
compiler/rustc_parse/src/parser/attr_wrapper.rs
compiler/rustc_parse/src/parser/diagnostics.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/generics.rs
compiler/rustc_parse/src/parser/item.rs
compiler/rustc_parse/src/parser/pat.rs
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_serialize/src/serialize.rs
compiler/rustc_session/src/parse.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_trait_selection/src/traits/engine.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.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/project.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_transmute/src/lib.rs
compiler/rustc_ty_utils/src/implied_bounds.rs [new file with mode: 0644]
compiler/rustc_ty_utils/src/lib.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/method/confirm.rs
compiler/rustc_typeck/src/check/method/mod.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/regionck.rs [deleted file]
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/outlives_bounds.rs
library/alloc/src/alloc/tests.rs
library/alloc/src/boxed.rs
library/alloc/src/collections/binary_heap.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/src/ffi/c_str.rs
library/alloc/src/slice.rs
library/alloc/src/str.rs
library/alloc/src/string.rs
library/alloc/src/vec/in_place_collect.rs
library/alloc/src/vec/into_iter.rs
library/alloc/src/vec/mod.rs
library/alloc/src/vec/spec_extend.rs
library/alloc/tests/str.rs
library/alloc/tests/vec.rs
library/core/src/any.rs
library/core/src/array/mod.rs
library/core/src/borrow.rs
library/core/src/char/mod.rs
library/core/src/cmp.rs
library/core/src/default.rs
library/core/src/intrinsics.rs
library/core/src/num/f32.rs
library/core/src/num/f64.rs
library/core/src/primitive_docs.rs
library/core/src/slice/mod.rs
library/core/src/slice/sort.rs
library/core/src/str/validations.rs
library/core/src/sync/atomic.rs
library/panic_abort/src/android.rs
library/panic_unwind/src/dwarf/eh.rs
library/std/src/error.rs
library/std/src/f32.rs
library/std/src/f64.rs
library/std/src/ffi/os_str.rs
library/std/src/net/ip.rs
library/std/src/net/ip/tests.rs
library/std/src/os/unix/net/addr.rs
library/std/src/primitive_docs.rs
library/std/src/process.rs
library/std/src/sys/sgx/abi/usercalls/tests.rs
library/std/src/sys/windows/alloc.rs
library/std/src/sys/windows/fs.rs
library/std/src/sys/windows/os.rs
library/std/src/sys_common/wtf8.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/highlight/fixtures/decorations.html
src/librustdoc/html/highlight/fixtures/sample.html
src/librustdoc/html/highlight/fixtures/sample.rs
src/librustdoc/html/highlight/tests.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/json/conversions.rs
src/test/assembly/x86_64-floating-point-clamp.rs [new file with mode: 0644]
src/test/codegen/pic-relocation-model.rs
src/test/codegen/pie-relocation-model.rs
src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
src/test/mir-opt/const_prop/aggregate.rs
src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/array_index.rs
src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
src/test/mir-opt/const_prop/boolean_identities.rs
src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
src/test/mir-opt/const_prop/boxes.rs
src/test/mir-opt/const_prop/cast.main.ConstProp.diff
src/test/mir-opt/const_prop/cast.rs
src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
src/test/mir-opt/const_prop/checked_add.rs
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
src/test/mir-opt/const_prop/control-flow-simplification.rs
src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/discriminant.rs
src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
src/test/mir-opt/const_prop/indirect.rs
src/test/mir-opt/const_prop/issue-66971.rs
src/test/mir-opt/const_prop/issue-67019.rs
src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
src/test/mir-opt/const_prop/mult_by_zero.rs
src/test/mir-opt/const_prop/mutable_variable.rs
src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
src/test/mir-opt/const_prop/optimizes_into_variable.rs
src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
src/test/mir-opt/const_prop/read_immutable_static.rs
src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
src/test/mir-opt/const_prop/ref_deref_project.rs
src/test/rustdoc/issue-41783.codeblock.html
src/test/rustdoc/issue-41783.rs
src/test/ui-fulldeps/pprust-expr-roundtrip.rs
src/test/ui/associated-types/associated-types-eq-3.stderr
src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
src/test/ui/associated-types/associated-types-path-2.stderr
src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
src/test/ui/associated-types/issue-59324.stderr
src/test/ui/async-await/issue-67252-unnamed-future.stderr
src/test/ui/async-await/issue-68112.stderr
src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
src/test/ui/chalkify/type_wf.rs
src/test/ui/chalkify/type_wf.stderr
src/test/ui/closure_context/issue-26046-fn-mut.stderr
src/test/ui/closure_context/issue-26046-fn-once.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
src/test/ui/closures/closure-move-sync.stderr
src/test/ui/closures/closure-wrong-kind.stderr
src/test/ui/const-generics/defaults/trait_objects_fail.stderr
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
src/test/ui/consts/const-block-const-bound.stderr
src/test/ui/derives/deriving-copyclone.stderr
src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
src/test/ui/error-codes/E0277-2.stderr
src/test/ui/extern/extern-types-unsized.stderr
src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
src/test/ui/fmt/send-sync.stderr
src/test/ui/generator/drop-tracking-parent-expression.stderr
src/test/ui/generator/drop-yield-twice.stderr
src/test/ui/generator/generator-yielding-or-returning-itself.stderr
src/test/ui/generator/issue-68112.rs
src/test/ui/generator/issue-68112.stderr
src/test/ui/generator/not-send-sync.stderr
src/test/ui/generator/partial-drop.stderr
src/test/ui/generator/print/generator-print-verbose-1.stderr
src/test/ui/generator/print/generator-print-verbose-2.stderr
src/test/ui/generic-associated-types/bugs/issue-88460.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
src/test/ui/inference/issue-71732.stderr
src/test/ui/inference/issue-86162-1.stderr
src/test/ui/inference/issue-86162-2.stderr
src/test/ui/interior-mutability/interior-mutability.stderr
src/test/ui/issues/issue-18611.stderr
src/test/ui/issues/issue-20162.stderr
src/test/ui/issues/issue-20605.stderr
src/test/ui/issues/issue-20831-debruijn.stderr
src/test/ui/issues/issue-21763.stderr
src/test/ui/issues/issue-23122-2.stderr
src/test/ui/issues/issue-31173.rs
src/test/ui/issues/issue-31173.stderr
src/test/ui/issues/issue-33941.stderr
src/test/ui/issues/issue-34334.stderr
src/test/ui/issues/issue-34349.stderr
src/test/ui/issues/issue-35570.rs
src/test/ui/issues/issue-35570.stderr
src/test/ui/issues/issue-59488.rs
src/test/ui/issues/issue-59488.stderr
src/test/ui/issues/issue-60218.stderr
src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
src/test/ui/issues/issue-69455.stderr
src/test/ui/iterators/collect-into-array.rs
src/test/ui/iterators/collect-into-array.stderr
src/test/ui/iterators/collect-into-slice.rs
src/test/ui/iterators/collect-into-slice.stderr
src/test/ui/kindck/kindck-impl-type-params-2.rs
src/test/ui/kindck/kindck-impl-type-params-2.stderr
src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
src/test/ui/kindck/kindck-nonsendable-1.stderr
src/test/ui/kindck/kindck-send-object.stderr
src/test/ui/kindck/kindck-send-object1.stderr
src/test/ui/kindck/kindck-send-object2.stderr
src/test/ui/kindck/kindck-send-owned.stderr
src/test/ui/lazy-type-alias-impl-trait/branches.stderr
src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
src/test/ui/never_type/defaulted-never-note.fallback.stderr
src/test/ui/never_type/defaulted-never-note.rs
src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
src/test/ui/nll/normalization-bounds-error.stderr
src/test/ui/no-send-res-ports.stderr
src/test/ui/not-clone-closure.stderr
src/test/ui/not-panic/not-panic-safe-2.stderr
src/test/ui/not-panic/not-panic-safe-3.stderr
src/test/ui/not-panic/not-panic-safe-4.stderr
src/test/ui/not-panic/not-panic-safe-5.stderr
src/test/ui/not-panic/not-panic-safe-6.stderr
src/test/ui/on-unimplemented/multiple-impls.stderr
src/test/ui/on-unimplemented/on-impl.stderr
src/test/ui/or-patterns/inner-or-pat.or3.stderr [new file with mode: 0644]
src/test/ui/or-patterns/inner-or-pat.or4.stderr [new file with mode: 0644]
src/test/ui/or-patterns/inner-or-pat.rs [new file with mode: 0644]
src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
src/test/ui/parser/kw-in-trait-bounds.rs [new file with mode: 0644]
src/test/ui/parser/kw-in-trait-bounds.stderr [new file with mode: 0644]
src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
src/test/ui/proc-macro/signature.stderr
src/test/ui/range/range-1.stderr
src/test/ui/recursion/issue-83150.stderr
src/test/ui/recursion/issue-95134.rs [new file with mode: 0644]
src/test/ui/recursion/issue-95134.stderr [new file with mode: 0644]
src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
src/test/ui/specialization/min_specialization/issue-79224.stderr
src/test/ui/stats/hir-stats.stderr
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
src/test/ui/suggestions/issue-62843.stderr
src/test/ui/suggestions/issue-71394-no-from-impl.stderr
src/test/ui/suggestions/issue-84973-2.stderr
src/test/ui/suggestions/issue-84973-blacklist.stderr
src/test/ui/suggestions/issue-84973-negative.stderr
src/test/ui/suggestions/issue-84973.stderr
src/test/ui/suggestions/slice-issue-87994.stderr
src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr
src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
src/test/ui/traits/bad-method-typaram-kind.stderr
src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
src/test/ui/traits/bound/on-structs-and-enums-locals.rs
src/test/ui/traits/bound/on-structs-and-enums-locals.stderr
src/test/ui/traits/bound/on-structs-and-enums-xc1.rs
src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr
src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
src/test/ui/traits/issue-77982.stderr
src/test/ui/traits/issue-91594.stderr
src/test/ui/traits/issue-97576.stderr
src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
src/test/ui/traits/suggest-where-clause.stderr
src/test/ui/transmutability/references.stderr
src/test/ui/type/type-params-in-different-spaces-2.stderr
src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
src/test/ui/union/union-generic.mirunsafeck.stderr
src/test/ui/union/union-generic.thirunsafeck.stderr
src/test/ui/unsized-locals/unsized-exprs.stderr
src/test/ui/unsized/issue-30355.stderr
src/test/ui/unsized/issue-71659.stderr
src/test/ui/unsized/issue-75707.stderr
src/test/ui/unsized/unsized-fn-param.stderr
src/test/ui/unsized/unsized-struct.stderr
src/test/ui/unsized/unsized3.stderr
src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
src/test/ui/where-clauses/where-clause-method-substituion.stderr
src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
src/tools/miri
src/tools/rustfmt/src/attr.rs
src/tools/rustfmt/src/imports.rs
src/tools/rustfmt/src/modules.rs
src/tools/rustfmt/src/parse/parser.rs
src/tools/tidy/src/style.rs

index a6625ac2ac4a172d08c081090e5cfba5597cea00..b16fb6341c2e50a2f37f04e563017a588365a4d7 100644 (file)
@@ -42,6 +42,7 @@ no_llvm_build
 /llvm/
 /mingw-build/
 /build/
+/build-rust-analyzer/
 /dist/
 /unicode-downloads
 /target
index 3a35985836c93905fe673ac66d7aecc38a50f3af..cb245ce0ff828ef01c6b0cea39b7beec89a5fc85 100644 (file)
@@ -3595,6 +3595,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
+ "rustc_macros",
  "rustc_parse",
  "rustc_session",
  "rustc_span",
index 98faacdc1fb59cb14fb6100ef4e610d319a5c1e9..d2f8ef8eaae7dbc3904c4cd8cb03fa2df4195a4e 100644 (file)
@@ -219,7 +219,7 @@ pub fn alloc(&self, object: T) -> &mut T {
             } else {
                 let ptr = self.ptr.get();
                 // Advance the pointer.
-                self.ptr.set(self.ptr.get().offset(1));
+                self.ptr.set(self.ptr.get().add(1));
                 // Write into uninitialized memory.
                 ptr::write(ptr, object);
                 &mut *ptr
index d5180b46aaff4cceba17c92b2dd6e097b93d087d..598bf771008dbb009d64ccd28c90d6b8b5fb0d97 100644 (file)
@@ -504,7 +504,7 @@ pub struct WhereEqPredicate {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Crate {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub items: Vec<P<Item>>,
     pub spans: ModSpans,
     /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold
@@ -1268,7 +1268,7 @@ pub fn take(&mut self) -> Self {
                 id: DUMMY_NODE_ID,
                 kind: ExprKind::Err,
                 span: DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
                 tokens: None,
             },
         )
@@ -2669,7 +2669,7 @@ pub fn ctor_id(&self) -> Option<NodeId> {
 /// An item definition.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Item<K = ItemKind> {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
@@ -3036,19 +3036,19 @@ mod size_asserts {
     use super::*;
     use rustc_data_structures::static_assert_size;
     // These are in alphabetical order, which is easy to maintain.
-    static_assert_size!(AssocItem, 120);
+    static_assert_size!(AssocItem, 104);
     static_assert_size!(AssocItemKind, 32);
     static_assert_size!(Attribute, 32);
     static_assert_size!(Block, 48);
     static_assert_size!(Expr, 104);
     static_assert_size!(ExprKind, 72);
     static_assert_size!(Fn, 192);
-    static_assert_size!(ForeignItem, 112);
+    static_assert_size!(ForeignItem, 96);
     static_assert_size!(ForeignItemKind, 24);
     static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 72);
     static_assert_size!(Impl, 200);
-    static_assert_size!(Item, 200);
+    static_assert_size!(Item, 184);
     static_assert_size!(ItemKind, 112);
     static_assert_size!(Lit, 48);
     static_assert_size!(LitKind, 24);
index 1fc5e480215ea4888ac673f7b48eb339d124635f..0947a71b8243261a7e7efad25f1599b7a92fb943 100644 (file)
@@ -270,7 +270,7 @@ pub trait HasAttrs {
     /// during token collection.
     const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
     fn attrs(&self) -> &[Attribute];
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec));
 }
 
 macro_rules! impl_has_attrs {
@@ -283,8 +283,8 @@ fn attrs(&self) -> &[Attribute] {
                     &self.attrs
                 }
 
-                fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-                    VecOrAttrVec::visit(&mut self.attrs, f)
+                fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
+                    f(&mut self.attrs)
                 }
             }
         )+
@@ -299,7 +299,7 @@ impl HasAttrs for $T {
                 fn attrs(&self) -> &[Attribute] {
                     &[]
                 }
-                fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
+                fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
             }
         )+
     };
@@ -330,7 +330,7 @@ impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
     fn attrs(&self) -> &[Attribute] {
         self.ast_deref().attrs()
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         self.ast_deref_mut().visit_attrs(f)
     }
 }
@@ -340,7 +340,7 @@ impl<T: HasAttrs> HasAttrs for Option<T> {
     fn attrs(&self) -> &[Attribute] {
         self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[])
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         if let Some(inner) = self.as_mut() {
             inner.visit_attrs(f);
         }
@@ -362,13 +362,13 @@ fn attrs(&self) -> &[Attribute] {
         }
     }
 
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         match self {
-            StmtKind::Local(local) => visit_attrvec(&mut local.attrs, f),
+            StmtKind::Local(local) => f(&mut local.attrs),
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
             StmtKind::Item(item) => item.visit_attrs(f),
             StmtKind::Empty => {}
-            StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
+            StmtKind::MacCall(mac) => f(&mut mac.attrs),
         }
     }
 }
@@ -378,38 +378,11 @@ impl HasAttrs for Stmt {
     fn attrs(&self) -> &[Attribute] {
         self.kind.attrs()
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         self.kind.visit_attrs(f);
     }
 }
 
-/// Helper trait for the impls above. Abstracts over
-/// the two types of attribute fields that AST nodes
-/// may have (`Vec<Attribute>` or `AttrVec`).
-trait VecOrAttrVec {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
-}
-
-impl VecOrAttrVec for Vec<Attribute> {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-        f(self)
-    }
-}
-
-impl VecOrAttrVec for AttrVec {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-        visit_attrvec(self, f)
-    }
-}
-
-fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) {
-    crate::mut_visit::visit_clobber(attrs, |attrs| {
-        let mut vec = attrs.into();
-        f(&mut vec);
-        vec.into()
-    });
-}
-
 /// A newtype around an AST node that implements the traits above if the node implements them.
 pub struct AstNodeWrapper<Wrapped, Tag> {
     pub wrapped: Wrapped,
index 0d114f1366c4d558988c980def48bad84514577e..5b72ec2b6015c32550e8f53eb0ab6f01d3495fc1 100644 (file)
@@ -12,7 +12,6 @@
 use crate::tokenstream::{LazyTokenStream, TokenStream};
 use crate::util::comments;
 
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::source_map::BytePos;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -487,7 +486,7 @@ pub fn mac_args(&self, span: Span) -> MacArgs {
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ExprKind::Lit(lit.clone()),
                     span: lit.span,
-                    attrs: ThinVec::new(),
+                    attrs: ast::AttrVec::new(),
                     tokens: None,
                 });
                 MacArgs::Eq(span, MacArgsEq::Ast(expr))
index 0520319e3be14e8190aa772391a3354a3bb786a5..458d1156ec251b7c17248facee6b2e8c91af9154 100644 (file)
@@ -14,7 +14,6 @@
 
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
@@ -338,12 +337,7 @@ pub fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F)
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_attrs<T: MutVisitor>(attrs: &mut Vec<Attribute>, vis: &mut T) {
-    visit_vec(attrs, |attr| vis.visit_attribute(attr));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_thin_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
+pub fn visit_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
     for attr in attrs.iter_mut() {
         vis.visit_attribute(attr);
     }
@@ -398,7 +392,7 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
     vis.visit_ident(ident);
     vis.visit_pat(pat);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     smallvec![fp]
 }
 
@@ -424,7 +418,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 
 pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -507,7 +501,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
-    visit_thin_attrs(attrs, visitor);
+    visit_attrs(attrs, visitor);
     visitor.visit_id(id);
     visitor.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -589,7 +583,7 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
         }
     }
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_lazy_tts(tokens, vis);
 }
 
@@ -640,7 +634,7 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
 pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
     let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     vis.visit_pat(pat);
     vis.visit_span(span);
     vis.visit_ty(ty);
@@ -882,7 +876,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
     if let Some(ref mut colon_span) = colon_span {
         vis.visit_span(colon_span);
     }
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
     match kind {
         GenericParamKind::Lifetime => {}
@@ -978,7 +972,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
-    visit_thin_attrs(attrs, visitor);
+    visit_attrs(attrs, visitor);
     smallvec![fd]
 }
 
@@ -991,7 +985,7 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
     vis.visit_expr(expr);
     vis.visit_id(id);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     smallvec![f]
 }
 
@@ -1432,7 +1426,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
     }
     vis.visit_id(id);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_lazy_tts(tokens, vis);
 }
 
@@ -1478,7 +1472,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
         StmtKind::MacCall(mut mac) => {
             let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
             vis.visit_mac_call(mac_);
-            visit_thin_attrs(attrs, vis);
+            visit_attrs(attrs, vis);
             visit_lazy_tts(tokens, vis);
             smallvec![StmtKind::MacCall(mac)]
         }
@@ -1513,12 +1507,6 @@ fn dummy() -> Self {
     }
 }
 
-impl<T> DummyAstNode for ThinVec<T> {
-    fn dummy() -> Self {
-        Default::default()
-    }
-}
-
 impl DummyAstNode for Item {
     fn dummy() -> Self {
         Item {
index 32dbd2ff47d6b98349cd4a51a65e13734a3b3107..bd61f4fa87ab8d493b0a41f63086c47478e69fea 100644 (file)
@@ -6,7 +6,6 @@
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -448,12 +447,12 @@ fn lower_expr_while_in_loop_scope(
         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
         let new_cond = self.manage_let_cond(lowered_cond);
         let then = self.lower_block_expr(body);
-        let expr_break = self.expr_break(span, ThinVec::new());
+        let expr_break = self.expr_break(span, AttrVec::new());
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
-        let else_expr = self.arena.alloc(self.expr_block(else_blk, ThinVec::new()));
+        let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
         let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
-        let if_expr = self.expr(span, if_kind, ThinVec::new());
+        let if_expr = self.expr(span, if_kind, AttrVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));
         let opt_label = self.lower_label(opt_label);
@@ -512,7 +511,7 @@ fn wrap_in_try_constructor(
         let constructor = self.arena.alloc(self.expr_lang_item_path(
             method_span,
             lang_item,
-            ThinVec::new(),
+            AttrVec::new(),
             None,
         ));
         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
@@ -635,7 +634,7 @@ pub(super) fn make_async_expr(
         let gen_future = self.expr_lang_item_path(
             unstable_span,
             hir::LangItem::FromGenerator,
-            ThinVec::new(),
+            AttrVec::new(),
             None,
         );
 
@@ -747,7 +746,7 @@ fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKi
             let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
-                this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new()))
+                this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
             });
             self.arm(ready_pat, break_x)
         };
@@ -780,7 +779,7 @@ fn lower_expr_await(&mut self, dot_await_span: Span, expr: &Expr) -> hir::ExprKi
             let yield_expr = self.expr(
                 span,
                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
-                ThinVec::new(),
+                AttrVec::new(),
             );
             let yield_expr = self.arena.alloc(yield_expr);
 
@@ -987,7 +986,7 @@ fn lower_expr_async_closure(
                     hir::AsyncGeneratorKind::Closure,
                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
                 );
-                this.expr(fn_decl_span, async_body, ThinVec::new())
+                this.expr(fn_decl_span, async_body, AttrVec::new())
             });
             body_id
         });
@@ -1257,7 +1256,7 @@ fn destructure_assign_mut(
         let ident = self.expr_ident(lhs.span, ident, binding);
         let assign =
             hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
-        let expr = self.expr(lhs.span, assign, ThinVec::new());
+        let expr = self.expr(lhs.span, assign, AttrVec::new());
         assignments.push(self.stmt_expr(lhs.span, expr));
         pat
     }
@@ -1299,7 +1298,7 @@ fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::
         let fn_path =
             hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
         let fn_expr =
-            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
+            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
     }
 
@@ -1472,7 +1471,7 @@ fn lower_expr_for(
         // `None => break`
         let none_arm = {
             let break_expr =
-                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new()));
+                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
             let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
@@ -1481,7 +1480,7 @@ fn lower_expr_for(
         let some_arm = {
             let some_pat = self.pat_some(pat_span, pat);
             let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
-            let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new()));
+            let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
             self.arm(some_pat, body_expr)
         };
 
@@ -1596,7 +1595,7 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
             };
             attr::mk_attr_outer(allow)
         };
-        let attrs = vec![attr];
+        let attrs: AttrVec = vec![attr].into();
 
         // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
         let continue_arm = {
@@ -1606,7 +1605,7 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                 span,
                 val_ident,
                 val_pat_nid,
-                ThinVec::from(attrs.clone()),
+                attrs.clone(),
             ));
             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
             self.arm(continue_pat, val_expr)
@@ -1625,7 +1624,6 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                 self.arena.alloc(residual_expr),
                 unstable_span,
             );
-            let thin_attrs = ThinVec::from(attrs);
             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(
@@ -1634,13 +1632,13 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                         hir::Destination { label: None, target_id },
                         Some(from_residual_expr),
                     ),
-                    thin_attrs,
+                    attrs,
                 ))
             } else {
                 self.arena.alloc(self.expr(
                     try_span,
                     hir::ExprKind::Ret(Some(from_residual_expr)),
-                    thin_attrs,
+                    attrs,
                 ))
             };
 
@@ -1728,7 +1726,7 @@ fn expr_match(
         arms: &'hir [hir::Arm<'hir>],
         source: hir::MatchSource,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
+        self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
     }
 
     fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
@@ -1745,12 +1743,12 @@ fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Exp
         self.expr(
             span,
             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
-            ThinVec::new(),
+            AttrVec::new(),
         )
     }
 
     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new()))
+        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
     }
 
     fn expr_call_mut(
@@ -1759,7 +1757,7 @@ fn expr_call_mut(
         e: &'hir hir::Expr<'hir>,
         args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
+        self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
     }
 
     fn expr_call(
@@ -1779,7 +1777,7 @@ fn expr_call_lang_item_fn_mut(
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
         let path =
-            self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id));
+            self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
         self.expr_call_mut(span, path, args)
     }
 
@@ -1822,7 +1820,7 @@ pub(super) fn expr_ident_mut(
         ident: Ident,
         binding: hir::HirId,
     ) -> hir::Expr<'hir> {
-        self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new())
+        self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
     }
 
     fn expr_ident_with_attrs(
@@ -1860,13 +1858,13 @@ fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
                 }),
                 None,
             ),
-            ThinVec::new(),
+            AttrVec::new(),
         )
     }
 
     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
         let blk = self.block_all(span, &[], None);
-        let expr = self.expr_block(blk, ThinVec::new());
+        let expr = self.expr_block(blk, AttrVec::new());
         self.arena.alloc(expr)
     }
 
index 22742b2adbd4fc3448c10c69f4ad7aa0b45b1908..37eff9207c128688b02768b9bddfac6c9b360719 100644 (file)
@@ -11,6 +11,7 @@ rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
index e61dfef7bd380394b28d3f0711c4a22cf8445a80..b337e5328c5df6af4c75ae61acfd3739ca616360 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, pluralize, struct_span_err, Applicability, Diagnostic};
+use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{
     DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -27,6 +27,8 @@
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+use crate::errors::*;
+
 const MORE_EXTERN: &str =
     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
 
@@ -117,23 +119,7 @@ fn with_let_management(
 
     /// Emits an error banning the `let` expression provided in the given location.
     fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
-        let err = "`let` expressions are not supported here";
-        let mut diag = self.session.struct_span_err(expr.span, err);
-        diag.note("only supported directly in conditions of `if` and `while` expressions");
-        match forbidden_let_reason {
-            ForbiddenLetReason::GenericForbidden => {}
-            ForbiddenLetReason::NotSupportedOr(span) => {
-                diag.span_note(span, "`||` operators are not supported in let chain expressions");
-            }
-            ForbiddenLetReason::NotSupportedParentheses(span) => {
-                diag.span_note(
-                    span,
-                    "`let`s wrapped in parentheses are not supported in a context with let \
-                    chains",
-                );
-            }
-        }
-        diag.emit();
+        self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
     }
 
     fn check_gat_where(
@@ -163,7 +149,7 @@ fn check_gat_where(
                 DEPRECATED_WHERE_CLAUSE_LOCATION,
                 id,
                 where_clauses.0.1,
-                "where clause not allowed here",
+                fluent::ast_passes::deprecated_where_clause_location,
                 BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
                     where_clauses.1.1.shrink_to_hi(),
                     suggestion,
@@ -193,10 +179,7 @@ fn visit_assoc_constraint_from_generic_args(&mut self, constraint: &'a AssocCons
             AssocConstraintKind::Equality { .. } => {}
             AssocConstraintKind::Bound { .. } => {
                 if self.is_assoc_ty_bound_banned {
-                    self.err_handler().span_err(
-                        constraint.span,
-                        "associated type bounds are not allowed within structs, enums, or unions",
-                    );
+                    self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span });
                 }
             }
         }
@@ -268,31 +251,26 @@ fn err_handler(&self) -> &rustc_errors::Handler {
     fn check_lifetime(&self, ident: Ident) {
         let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
-            self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
+            self.session.emit_err(KeywordLifetime { span: ident.span });
         }
     }
 
     fn check_label(&self, ident: Ident) {
         if ident.without_first_quote().is_reserved() {
-            self.err_handler()
-                .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
+            self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name });
         }
     }
 
-    fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
+    fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNote>) {
         if let VisibilityKind::Inherited = vis.kind {
             return;
         }
 
-        let mut err =
-            struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
-        if vis.kind.is_pub() {
-            err.span_label(vis.span, "`pub` not permitted here because it's implied");
-        }
-        if let Some(note) = note {
-            err.note(note);
-        }
-        err.emit();
+        self.session.emit_err(InvalidVisibility {
+            span: vis.span,
+            implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+            note,
+        });
     }
 
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
@@ -309,29 +287,13 @@ fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Iden
 
     fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
         if let Async::Yes { span, .. } = asyncness {
-            struct_span_err!(
-                self.session,
-                fn_span,
-                E0706,
-                "functions in traits cannot be declared `async`"
-            )
-            .span_label(span, "`async` because of this")
-            .note("`async` trait functions are not currently supported")
-            .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
-            .emit();
+            self.session.emit_err(TraitFnAsync { fn_span, span });
         }
     }
 
     fn check_trait_fn_not_const(&self, constness: Const) {
         if let Const::Yes(span) = constness {
-            struct_span_err!(
-                self.session,
-                span,
-                E0379,
-                "functions in traits cannot be declared const"
-            )
-            .span_label(span, "functions in traits cannot be const")
-            .emit();
+            self.session.emit_err(TraitFnConst { span });
         }
     }
 
@@ -344,8 +306,7 @@ fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
                 GenericParamKind::Lifetime { .. } => {
                     if !param.bounds.is_empty() {
                         let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
-                        self.err_handler()
-                            .span_err(spans, "lifetime bounds cannot be used in this context");
+                        self.session.emit_err(ForbiddenLifetimeBound { spans });
                     }
                     None
                 }
@@ -353,10 +314,7 @@ fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
             })
             .collect();
         if !non_lt_param_spans.is_empty() {
-            self.err_handler().span_err(
-                non_lt_param_spans,
-                "only lifetime parameters can be used in this context",
-            );
+            self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
         }
     }
 
@@ -373,10 +331,7 @@ fn check_decl_num_args(&self, fn_decl: &FnDecl) {
         let max_num_args: usize = u16::MAX.into();
         if fn_decl.inputs.len() > max_num_args {
             let Param { span, .. } = fn_decl.inputs[0];
-            self.err_handler().span_fatal(
-                span,
-                &format!("function can not have more than {} arguments", max_num_args),
-            );
+            self.session.emit_fatal(FnParamTooMany { span, max_num_args });
         }
     }
 
@@ -384,19 +339,13 @@ fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
         match &*fn_decl.inputs {
             [Param { ty, span, .. }] => {
                 if let TyKind::CVarArgs = ty.kind {
-                    self.err_handler().span_err(
-                        *span,
-                        "C-variadic function must be declared with at least one named argument",
-                    );
+                    self.session.emit_err(FnParamCVarArgsOnly { span: *span });
                 }
             }
             [ps @ .., _] => {
                 for Param { ty, span, .. } in ps {
                     if let TyKind::CVarArgs = ty.kind {
-                        self.err_handler().span_err(
-                            *span,
-                            "`...` must be the last argument of a C-variadic function",
-                        );
+                        self.session.emit_err(FnParamCVarArgsNotLast { span: *span });
                     }
                 }
             }
@@ -423,19 +372,9 @@ fn check_decl_attrs(&self, fn_decl: &FnDecl) {
             })
             .for_each(|attr| {
                 if attr.is_doc_comment() {
-                    self.err_handler()
-                        .struct_span_err(
-                            attr.span,
-                            "documentation comments cannot be applied to function parameters",
-                        )
-                        .span_label(attr.span, "doc comments are not allowed here")
-                        .emit();
+                    self.session.emit_err(FnParamDocComment { span: attr.span });
                 } else {
-                    self.err_handler().span_err(
-                        attr.span,
-                        "allow, cfg, cfg_attr, deny, expect, \
-                forbid, and warn are the only allowed built-in attributes in function parameters",
-                    );
+                    self.session.emit_err(FnParamForbiddenAttr { span: attr.span });
                 }
             });
     }
@@ -443,14 +382,7 @@ fn check_decl_attrs(&self, fn_decl: &FnDecl) {
     fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
         if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
             if param.is_self() {
-                self.err_handler()
-                    .struct_span_err(
-                        param.span,
-                        "`self` parameter is only allowed in associated functions",
-                    )
-                    .span_label(param.span, "not semantically valid as function parameter")
-                    .note("associated functions are those in `impl` or `trait` definitions")
-                    .emit();
+                self.session.emit_err(FnParamForbiddenSelf { span: param.span });
             }
         }
     }
@@ -458,47 +390,20 @@ fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
         if let Defaultness::Default(def_span) = defaultness {
             let span = self.session.source_map().guess_head_span(span);
-            self.err_handler()
-                .struct_span_err(span, "`default` is only allowed on items in trait impls")
-                .span_label(def_span, "`default` because of this")
-                .emit();
+            self.session.emit_err(ForbiddenDefault { span, def_span });
         }
     }
 
-    fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
-        self.error_item_without_body_with_help(sp, ctx, msg, sugg, |_| ());
-    }
-
-    fn error_item_without_body_with_help(
-        &self,
-        sp: Span,
-        ctx: &str,
-        msg: &str,
-        sugg: &str,
-        help: impl FnOnce(&mut Diagnostic),
-    ) {
+    /// If `sp` ends with a semicolon, returns it as a `Span`
+    /// Otherwise, returns `sp.shrink_to_hi()`
+    fn ending_semi_or_hi(&self, sp: Span) -> Span {
         let source_map = self.session.source_map();
         let end = source_map.end_point(sp);
-        let replace_span = if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
+
+        if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
             end
         } else {
             sp.shrink_to_hi()
-        };
-        let mut err = self.err_handler().struct_span_err(sp, msg);
-        err.span_suggestion(
-            replace_span,
-            &format!("provide a definition for the {}", ctx),
-            sugg,
-            Applicability::HasPlaceholders,
-        );
-        help(&mut err);
-        err.emit();
-    }
-
-    fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
-        if body.is_none() {
-            let msg = format!("associated {} in `impl` without body", ctx);
-            self.error_item_without_body(sp, ctx, &msg, sugg);
         }
     }
 
@@ -1168,7 +1073,7 @@ fn visit_item(&mut self, item: &'a Item) {
 
                 self.invalid_visibility(
                     &item.vis,
-                    Some("place qualifiers on individual impl items instead"),
+                    Some(InvalidVisibilityNote::IndividualImplItems),
                 );
                 if let Unsafe::Yes(span) = unsafety {
                     error(span, "unsafe").code(error_code!(E0197)).emit();
@@ -1191,37 +1096,23 @@ fn visit_item(&mut self, item: &'a Item) {
                 self.check_defaultness(item.span, defaultness);
 
                 if body.is_none() {
-                    let msg = "free function without a body";
-                    let ext = sig.header.ext;
-
-                    let f = |e: &mut Diagnostic| {
-                        if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext
-                        {
-                            let start_suggestion = if let Extern::Explicit(abi, _) = ext {
-                                format!("extern \"{}\" {{", abi.symbol_unescaped)
-                            } else {
-                                "extern {".to_owned()
-                            };
-
-                            let end_suggestion = " }".to_owned();
-                            let end_span = item.span.shrink_to_hi();
-
-                            e
-                            .multipart_suggestion(
-                                "if you meant to declare an externally defined function, use an `extern` block",
-                                vec![(*start_span, start_suggestion), (end_span, end_suggestion)],
-                                Applicability::MaybeIncorrect,
-                             );
-                        }
-                    };
-
-                    self.error_item_without_body_with_help(
-                        item.span,
-                        "function",
-                        msg,
-                        " { <body> }",
-                        f,
-                    );
+                    self.session.emit_err(FnWithoutBody {
+                        span: item.span,
+                        replace_span: self.ending_semi_or_hi(item.span),
+                        extern_block_suggestion: match sig.header.ext {
+                            Extern::None => None,
+                            Extern::Implicit(start_span) => Some(ExternBlockSuggestion {
+                                start_span,
+                                end_span: item.span.shrink_to_hi(),
+                                abi: None,
+                            }),
+                            Extern::Explicit(abi, start_span) => Some(ExternBlockSuggestion {
+                                start_span,
+                                end_span: item.span.shrink_to_hi(),
+                                abi: Some(abi.symbol_unescaped),
+                            }),
+                        },
+                    });
                 }
 
                 self.visit_vis(&item.vis);
@@ -1236,7 +1127,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
                 self.invalid_visibility(
                     &item.vis,
-                    Some("place qualifiers on individual foreign items instead"),
+                    Some(InvalidVisibilityNote::IndividualForeignItems),
                 );
                 if let Unsafe::Yes(span) = unsafety {
                     self.err_handler().span_err(span, "extern block cannot be declared unsafe");
@@ -1327,12 +1218,16 @@ fn visit_item(&mut self, item: &'a Item) {
             }
             ItemKind::Const(def, .., None) => {
                 self.check_defaultness(item.span, def);
-                let msg = "free constant item without body";
-                self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
+                self.session.emit_err(ConstWithoutBody {
+                    span: item.span,
+                    replace_span: self.ending_semi_or_hi(item.span),
+                });
             }
             ItemKind::Static(.., None) => {
-                let msg = "free static item without body";
-                self.error_item_without_body(item.span, "static", msg, " = <expr>;");
+                self.session.emit_err(StaticWithoutBody {
+                    span: item.span,
+                    replace_span: self.ending_semi_or_hi(item.span),
+                });
             }
             ItemKind::TyAlias(box TyAlias {
                 defaultness,
@@ -1343,8 +1238,10 @@ fn visit_item(&mut self, item: &'a Item) {
             }) => {
                 self.check_defaultness(item.span, defaultness);
                 if ty.is_none() {
-                    let msg = "free type alias without body";
-                    self.error_item_without_body(item.span, "type", msg, " = <type>;");
+                    self.session.emit_err(TyAliasWithoutBody {
+                        span: item.span,
+                        replace_span: self.ending_semi_or_hi(item.span),
+                    });
                 }
                 self.check_type_no_bounds(bounds, "this context");
                 if where_clauses.1.0 {
@@ -1648,10 +1545,20 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         if ctxt == AssocCtxt::Impl {
             match &item.kind {
                 AssocItemKind::Const(_, _, body) => {
-                    self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
+                    if body.is_none() {
+                        self.session.emit_err(AssocConstWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                 }
                 AssocItemKind::Fn(box Fn { body, .. }) => {
-                    self.check_impl_item_provided(item.span, body, "function", " { <body> }");
+                    if body.is_none() {
+                        self.session.emit_err(AssocFnWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                 }
                 AssocItemKind::TyAlias(box TyAlias {
                     generics,
@@ -1661,7 +1568,12 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                     ty,
                     ..
                 }) => {
-                    self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
+                    if ty.is_none() {
+                        self.session.emit_err(AssocTypeWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                     self.check_type_no_bounds(bounds, "`impl`s");
                     if ty.is_some() {
                         self.check_gat_where(
@@ -1876,7 +1788,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
 
 /// Used to forbid `let` expressions in certain syntactic locations.
 #[derive(Clone, Copy)]
-enum ForbiddenLetReason {
+pub(crate) enum ForbiddenLetReason {
     /// `let` is not valid and the source environment is not important
     GenericForbidden,
     /// A let chain with the `||` operator
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
new file mode 100644 (file)
index 0000000..16ba14e
--- /dev/null
@@ -0,0 +1,248 @@
+//! Errors emitted by ast_passes.
+
+use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{Span, Symbol};
+
+use crate::ast_validation::ForbiddenLetReason;
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_let)]
+#[note]
+pub struct ForbiddenLet {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub(crate) reason: ForbiddenLetReason,
+}
+
+impl AddSubdiagnostic for ForbiddenLetReason {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        match self {
+            Self::GenericForbidden => {}
+            Self::NotSupportedOr(span) => {
+                diag.span_note(span, fluent::ast_passes::not_supported_or);
+            }
+            Self::NotSupportedParentheses(span) => {
+                diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
+            }
+        }
+    }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_assoc_constraint)]
+pub struct ForbiddenAssocConstraint {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::keyword_lifetime)]
+pub struct KeywordLifetime {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::invalid_label)]
+pub struct InvalidLabel {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::invalid_visibility, code = "E0449")]
+pub struct InvalidVisibility {
+    #[primary_span]
+    pub span: Span,
+    #[label(ast_passes::implied)]
+    pub implied: Option<Span>,
+    #[subdiagnostic]
+    pub note: Option<InvalidVisibilityNote>,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum InvalidVisibilityNote {
+    #[note(ast_passes::individual_impl_items)]
+    IndividualImplItems,
+    #[note(ast_passes::individual_foreign_items)]
+    IndividualForeignItems,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::trait_fn_async, code = "E0706")]
+#[note]
+#[note(ast_passes::note2)]
+pub struct TraitFnAsync {
+    #[primary_span]
+    pub fn_span: Span,
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::trait_fn_const, code = "E0379")]
+pub struct TraitFnConst {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_lifetime_bound)]
+pub struct ForbiddenLifetimeBound {
+    #[primary_span]
+    pub spans: Vec<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_non_lifetime_param)]
+pub struct ForbiddenNonLifetimeParam {
+    #[primary_span]
+    pub spans: Vec<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_too_many)]
+pub struct FnParamTooMany {
+    #[primary_span]
+    pub span: Span,
+    pub max_num_args: usize,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_c_var_args_only)]
+pub struct FnParamCVarArgsOnly {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_c_var_args_not_last)]
+pub struct FnParamCVarArgsNotLast {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_doc_comment)]
+pub struct FnParamDocComment {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_forbidden_attr)]
+pub struct FnParamForbiddenAttr {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_forbidden_self)]
+#[note]
+pub struct FnParamForbiddenSelf {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_default)]
+pub struct ForbiddenDefault {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub def_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_const_without_body)]
+pub struct AssocConstWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_fn_without_body)]
+pub struct AssocFnWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_type_without_body)]
+pub struct AssocTypeWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <type>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::const_without_body)]
+pub struct ConstWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::static_without_body)]
+pub struct StaticWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::ty_alias_without_body)]
+pub struct TyAliasWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <type>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_without_body)]
+pub struct FnWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
+    pub replace_span: Span,
+    #[subdiagnostic]
+    pub extern_block_suggestion: Option<ExternBlockSuggestion>,
+}
+
+pub struct ExternBlockSuggestion {
+    pub start_span: Span,
+    pub end_span: Span,
+    pub abi: Option<Symbol>,
+}
+
+impl AddSubdiagnostic for ExternBlockSuggestion {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        let start_suggestion = if let Some(abi) = self.abi {
+            format!("extern \"{}\" {{", abi)
+        } else {
+            "extern {".to_owned()
+        };
+        let end_suggestion = " }".to_owned();
+
+        diag.multipart_suggestion(
+            fluent::ast_passes::extern_block_suggestion,
+            vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
index 2bc3b6f361643df5fe3e733ca2cc968b7935d06d..6a8262989850cb23d6417bba225117c062d45547 100644 (file)
@@ -12,6 +12,7 @@
 #![recursion_limit = "256"]
 
 pub mod ast_validation;
+mod errors;
 pub mod feature_gate;
 pub mod node_count;
 pub mod show_span;
index 6cfe5efb68886de601772d5f277627c277efb302..451b82c5c18700f07f1967ab571f604ebc9cf584 100644 (file)
@@ -90,12 +90,13 @@ pub(super) fn prove_trait_ref(
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
-        self.prove_predicates(
-            Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
+        self.prove_predicate(
+            ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
                 trait_ref,
                 constness: ty::BoundConstness::NotConst,
                 polarity: ty::ImplPolarity::Positive,
-            }))),
+            }))
+            .to_predicate(self.tcx()),
             locations,
             category,
         );
index 74655369faf0388d5872ffae944e3895202f3d4a..7c10047e9dc83c5ddeaa599d1ab4e3c2582b82a2 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_data_structures::frozen::Frozen;
-use rustc_data_structures::transitive_relation::TransitiveRelation;
+use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
@@ -61,25 +61,13 @@ pub(crate) fn create<'tcx>(
         constraints,
         universal_regions: universal_regions.clone(),
         region_bound_pairs: Default::default(),
-        relations: UniversalRegionRelations {
-            universal_regions: universal_regions.clone(),
-            outlives: Default::default(),
-            inverse_outlives: Default::default(),
-        },
+        outlives: Default::default(),
+        inverse_outlives: Default::default(),
     }
     .create()
 }
 
 impl UniversalRegionRelations<'_> {
-    /// Records in the `outlives_relation` (and
-    /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
-    /// builder below.
-    fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
-        debug!("relate_universal_regions: fr_a={:?} outlives fr_b={:?}", fr_a, fr_b);
-        self.outlives.add(fr_a, fr_b);
-        self.inverse_outlives.add(fr_b, fr_a);
-    }
-
     /// Given two universal regions, returns the postdominating
     /// upper-bound (effectively the least upper bound).
     ///
@@ -216,11 +204,20 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
     constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
 
     // outputs:
-    relations: UniversalRegionRelations<'tcx>,
+    outlives: TransitiveRelationBuilder<RegionVid>,
+    inverse_outlives: TransitiveRelationBuilder<RegionVid>,
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
 impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
+    /// Records in the `outlives_relation` (and
+    /// `inverse_outlives_relation`) that `fr_a: fr_b`.
+    fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
+        debug!("relate_universal_regions: fr_a={:?} outlives fr_b={:?}", fr_a, fr_b);
+        self.outlives.add(fr_a, fr_b);
+        self.inverse_outlives.add(fr_b, fr_a);
+    }
+
     pub(crate) fn create(mut self) -> CreateResult<'tcx> {
         let unnormalized_input_output_tys = self
             .universal_regions
@@ -268,7 +265,7 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
                 // }
                 // impl Foo for () {
                 //   type Bar = ();
-                //   fn foo(&self) ->&() {}
+                //   fn foo(&self) -> &() {}
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
@@ -292,9 +289,9 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
         let fr_fn_body = self.universal_regions.fr_fn_body;
         for fr in self.universal_regions.universal_regions() {
             debug!("build: relating free region {:?} to itself and to 'static", fr);
-            self.relations.relate_universal_regions(fr, fr);
-            self.relations.relate_universal_regions(fr_static, fr);
-            self.relations.relate_universal_regions(fr, fr_fn_body);
+            self.relate_universal_regions(fr, fr);
+            self.relate_universal_regions(fr_static, fr);
+            self.relate_universal_regions(fr, fr_fn_body);
         }
 
         for data in &constraint_sets {
@@ -313,7 +310,11 @@ pub(crate) fn create(mut self) -> CreateResult<'tcx> {
         }
 
         CreateResult {
-            universal_region_relations: Frozen::freeze(self.relations),
+            universal_region_relations: Frozen::freeze(UniversalRegionRelations {
+                universal_regions: self.universal_regions,
+                outlives: self.outlives.freeze(),
+                inverse_outlives: self.inverse_outlives.freeze(),
+            }),
             region_bound_pairs: self.region_bound_pairs,
             normalized_inputs_and_output,
         }
@@ -356,7 +357,7 @@ fn add_outlives_bounds<I>(&mut self, outlives_bounds: I)
                     // The bound says that `r1 <= r2`; we store `r2: r1`.
                     let r1 = self.universal_regions.to_region_vid(r1);
                     let r2 = self.universal_regions.to_region_vid(r2);
-                    self.relations.relate_universal_regions(r2, r1);
+                    self.relate_universal_regions(r2, r1);
                 }
 
                 OutlivesBound::RegionSubParam(r_a, param_b) => {
index 7bf7f7357bf4f57c5d4f6d8cb71b447f2434aba2..293d847ec9ab7aafdc3be14fae88a2b6c286ee01 100644 (file)
@@ -178,97 +178,15 @@ pub(crate) fn type_check<'mir, 'tcx>(
         upvars,
     };
 
-    let opaque_type_values = type_check_internal(
+    let mut checker = TypeChecker::new(
         infcx,
-        param_env,
         body,
-        promoted,
+        param_env,
         &region_bound_pairs,
         implicit_region_bound,
         &mut borrowck_context,
-        |mut cx| {
-            debug!("inside extra closure of type_check_internal");
-            cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
-            liveness::generate(
-                &mut cx,
-                body,
-                elements,
-                flow_inits,
-                move_data,
-                location_table,
-                use_polonius,
-            );
-
-            translate_outlives_facts(&mut cx);
-            let opaque_type_values =
-                infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
-
-            opaque_type_values
-                .into_iter()
-                .map(|(opaque_type_key, decl)| {
-                    cx.fully_perform_op(
-                        Locations::All(body.span),
-                        ConstraintCategory::OpaqueType,
-                        CustomTypeOp::new(
-                            |infcx| {
-                                infcx.register_member_constraints(
-                                    param_env,
-                                    opaque_type_key,
-                                    decl.hidden_type.ty,
-                                    decl.hidden_type.span,
-                                );
-                                Ok(InferOk { value: (), obligations: vec![] })
-                            },
-                            || "opaque_type_map".to_string(),
-                        ),
-                    )
-                    .unwrap();
-                    let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
-                    trace!(
-                        "finalized opaque type {:?} to {:#?}",
-                        opaque_type_key,
-                        hidden_type.ty.kind()
-                    );
-                    if hidden_type.has_infer_types_or_consts() {
-                        infcx.tcx.sess.delay_span_bug(
-                            decl.hidden_type.span,
-                            &format!("could not resolve {:#?}", hidden_type.ty.kind()),
-                        );
-                        hidden_type.ty = infcx.tcx.ty_error();
-                    }
-
-                    (opaque_type_key, (hidden_type, decl.origin))
-                })
-                .collect()
-        },
     );
 
-    MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
-}
-
-#[instrument(
-    skip(infcx, body, promoted, region_bound_pairs, borrowck_context, extra),
-    level = "debug"
-)]
-fn type_check_internal<'a, 'tcx, R>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body: &'a Body<'tcx>,
-    promoted: &'a IndexVec<Promoted, Body<'tcx>>,
-    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    implicit_region_bound: ty::Region<'tcx>,
-    borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
-    extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
-) -> R {
-    debug!("body: {:#?}", body);
-    let mut checker = TypeChecker::new(
-        infcx,
-        body,
-        param_env,
-        region_bound_pairs,
-        implicit_region_bound,
-        borrowck_context,
-    );
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, promoted);
         verifier.visit_body(&body);
@@ -280,7 +198,56 @@ fn type_check_internal<'a, 'tcx, R>(
         checker.typeck_mir(body);
     }
 
-    extra(checker)
+    checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
+    liveness::generate(
+        &mut checker,
+        body,
+        elements,
+        flow_inits,
+        move_data,
+        location_table,
+        use_polonius,
+    );
+
+    translate_outlives_facts(&mut checker);
+    let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+
+    let opaque_type_values = opaque_type_values
+        .into_iter()
+        .map(|(opaque_type_key, decl)| {
+            checker
+                .fully_perform_op(
+                    Locations::All(body.span),
+                    ConstraintCategory::OpaqueType,
+                    CustomTypeOp::new(
+                        |infcx| {
+                            infcx.register_member_constraints(
+                                param_env,
+                                opaque_type_key,
+                                decl.hidden_type.ty,
+                                decl.hidden_type.span,
+                            );
+                            Ok(InferOk { value: (), obligations: vec![] })
+                        },
+                        || "opaque_type_map".to_string(),
+                    ),
+                )
+                .unwrap();
+            let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
+            trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
+            if hidden_type.has_infer_types_or_consts() {
+                infcx.tcx.sess.delay_span_bug(
+                    decl.hidden_type.span,
+                    &format!("could not resolve {:#?}", hidden_type.ty.kind()),
+                );
+                hidden_type.ty = infcx.tcx.ty_error();
+            }
+
+            (opaque_type_key, (hidden_type, decl.origin))
+        })
+        .collect();
+
+    MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
 }
 
 fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
@@ -1911,7 +1878,7 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                 }
             }
 
-            &Rvalue::NullaryOp(_, ty) => {
+            &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
index 1a0ea8f416064f27c0b90a31254c9f0dd7af6731..a1051d990b14b910b1634ca8e43288a511718ca1 100644 (file)
@@ -852,7 +852,7 @@ pub(super) fn expand_global_asm<'cx>(
             if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 MacEager::items(smallvec![P(ast::Item {
                     ident: Ident::empty(),
-                    attrs: Vec::new(),
+                    attrs: ast::AttrVec::new(),
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
                     vis: ast::Visibility {
index d30fd479015ff49fa7dd0c7424c810bbdba42eda..d2ee4249989ee396a8195ae9030b70be35b55564 100644 (file)
@@ -119,7 +119,8 @@ fn build_initial_imports(&self) -> Stmt {
                 vec![self.cx.attribute(attr::mk_list_item(
                     Ident::new(sym::allow, self.span),
                     vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
-                ))],
+                ))]
+                .into(),
                 ItemKind::Use(UseTree {
                     prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
                     kind: UseTreeKind::Nested(vec![
index ee4c5aea1a3528001aaa1c93dd163134211fe751..dd7989cf48c37b784cd37fdc7020e71bcea334bc 100644 (file)
@@ -68,7 +68,7 @@ pub fn expand_deriving_clone(
     }
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
         path: path_std!(clone::Clone),
index f99ee8cb2d53c1b5b7a9167ed125a1108c1753f6..9b6d3e5032f9495f92caad1231e79e01680e7d05 100644 (file)
@@ -20,7 +20,7 @@ pub fn expand_deriving_eq(
     let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
     let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
     let no_coverage = cx.meta_word(span, sym::no_coverage);
-    let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
+    let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)].into();
     let trait_def = TraitDef {
         span,
         path: path_std!(cmp::Eq),
index 8aa16dfeb0f1f3e56dd4ba935e3c6a8997cb1b71..0e17b95178759368b59147dfca1fda6751b78066 100644 (file)
@@ -15,7 +15,7 @@ pub fn expand_deriving_ord(
     push: &mut dyn FnMut(Annotatable),
 ) {
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
         path: path_std!(cmp::Ord),
index 6f86092ba491b653ad8e92d1fcafbac16a68eee5..ac1325b92a6f38ed38acd385baded5839cdb076f 100644 (file)
@@ -68,7 +68,7 @@ fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOr
     // No need to generate `ne`, the default suffices, and not generating it is
     // faster.
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let methods = vec![MethodDef {
         name: sym::eq,
         generics: Bounds::empty(),
index 137c779f81b842ae83a6ed9316395e80d4d1db63..7763e55401783b19670703c070c72fa418e2117f 100644 (file)
@@ -19,7 +19,7 @@ pub fn expand_deriving_partial_ord(
         Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
 
     let partial_cmp_def = MethodDef {
         name: sym::partial_cmp,
index f82175af4f6f22f549689c27e586b82ab64bc5b9..4af7fd8165388894456292ac08518d98dabcbbde 100644 (file)
@@ -29,7 +29,7 @@ pub fn expand_deriving_debug(
             explicit_self: true,
             nonself_args: vec![(fmtr, sym::f)],
             ret_ty: Path(path_std!(fmt::Result)),
-            attributes: Vec::new(),
+            attributes: ast::AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 show_substructure(a, b, c)
index 47da0862b52fcd0306d060b91daeaa9f54f19686..7174dbbe7ea8b5abc7e1ac07dd2f28e1edafa14b 100644 (file)
@@ -47,7 +47,7 @@ pub fn expand_deriving_rustc_decodable(
                 ],
                 PathKind::Std,
             )),
-            attributes: Vec::new(),
+            attributes: ast::AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 decodable_substructure(a, b, c, krate)
index a431832080c0c1353eabf39d290b47c37332e43e..f316f01ef66152e7bb1b3308ce9c924b0d80b6e2 100644 (file)
@@ -2,9 +2,7 @@
 use crate::deriving::generic::*;
 
 use rustc_ast as ast;
-use rustc_ast::walk_list;
-use rustc_ast::EnumDef;
-use rustc_ast::VariantData;
+use rustc_ast::{walk_list, EnumDef, VariantData};
 use rustc_errors::Applicability;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::Ident;
@@ -22,7 +20,7 @@ pub fn expand_deriving_default(
     item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
         path: Path::new(vec![kw::Default, sym::Default]),
index d43c66a5fa644c373c499616aa64b3ccadc8673e..b220e54238f462e27c1d5d383490dcb7bdb6ec99 100644 (file)
@@ -89,7 +89,7 @@
 use crate::deriving::generic::*;
 use crate::deriving::pathvec_std;
 
-use rustc_ast::{ExprKind, MetaItem, Mutability};
+use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
@@ -131,7 +131,7 @@ pub fn expand_deriving_rustc_encodable(
                 ],
                 PathKind::Std,
             )),
-            attributes: Vec::new(),
+            attributes: AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 encodable_substructure(a, b, c, krate)
index a39b97d07ef0a8d5d9368ff35169b402c53122a7..c1bbc601560fa1550b2d5daa18c3302948fb4dcf 100644 (file)
@@ -217,7 +217,7 @@ pub struct MethodDef<'a> {
     /// Returns type
     pub ret_ty: Ty,
 
-    pub attributes: Vec<ast::Attribute>,
+    pub attributes: ast::AttrVec,
 
     /// Can we combine fieldless variants for enums into a single match arm?
     /// If true, indicates that the trait operation uses the enum tag in some
@@ -562,7 +562,7 @@ fn create_derived_impl(
                     kind: ast::VisibilityKind::Inherited,
                     tokens: None,
                 },
-                attrs: Vec::new(),
+                attrs: ast::AttrVec::new(),
                 kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
                     defaultness: ast::Defaultness::Final,
                     generics: Generics::default(),
@@ -716,7 +716,7 @@ fn create_derived_impl(
         let self_type = cx.ty_path(path);
 
         let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
-        let attrs = vec![attr];
+        let attrs = vec![attr].into();
         let opt_trait_ref = Some(trait_ref);
 
         cx.item(
index 9aa170bec14d8bd8e736972fcec6d365e94f451c..f1f02e7ce778740246c2a81b0038ec2d0ced1453 100644 (file)
@@ -2,7 +2,7 @@
 use crate::deriving::generic::*;
 use crate::deriving::{path_std, pathvec_std};
 
-use rustc_ast::{MetaItem, Mutability};
+use rustc_ast::{AttrVec, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -31,7 +31,7 @@ pub fn expand_deriving_hash(
             explicit_self: true,
             nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
             ret_ty: Unit,
-            attributes: vec![],
+            attributes: AttrVec::new(),
             unify_fieldless_variants: true,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 hash_substructure(a, b, c)
index c1ca089da221f3c12fcd0561f6e6a3858f915d5a..a65d0bad6de801e91d62ca492a2ba68ec9d20975 100644 (file)
@@ -164,7 +164,7 @@ fn inject_impl_of_structural_trait(
 
     // Keep the lint and stability attributes of the original item, to control
     // how the generated implementation is linted.
-    let mut attrs = Vec::new();
+    let mut attrs = ast::AttrVec::new();
     attrs.extend(
         item.attrs
             .iter()
index 08026c9d357846cc144cf718541b240a5a7aee05..fd517c1e1213682b6227395cc3e80b1d484a9a43 100644 (file)
@@ -1176,7 +1176,7 @@ fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>)
 
         cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
             span: MultiSpan::from_span(named_arg.positional_named_arg_span),
-            msg: msg.clone(),
+            msg: msg.into(),
             node_id: ast::CRATE_NODE_ID,
             lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
             diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
index 36cfbba45daccb2d521a5419b5c370e6e97293aa..2bad9bbce6650b30af53e970bd90a0ae21287552 100644 (file)
@@ -4,7 +4,7 @@
     AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
+use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
 use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -113,10 +113,10 @@ fn call_allocator(&self, method: Symbol, mut args: Vec<P<Expr>>) -> P<Expr> {
         self.cx.expr_call(self.ty_span, method, args)
     }
 
-    fn attrs(&self) -> Vec<Attribute> {
+    fn attrs(&self) -> AttrVec {
         let special = sym::rustc_std_internal_symbol;
         let special = self.cx.meta_word(self.span, special);
-        vec![self.cx.attribute(special)]
+        vec![self.cx.attribute(special)].into()
     }
 
     fn arg_ty(
index 5cfda33491d5b7d6392cdbc0fce93d0f4d4b52af..ebe1c3663e3a7fafc65da5117b065ac2eccb962f 100644 (file)
@@ -281,7 +281,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
     let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     let proc_macro = Ident::new(sym::proc_macro, span);
-    let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
+    let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
 
     let bridge = Ident::new(sym::bridge, span);
     let client = Ident::new(sym::client, span);
index 09ad5f9b3eaa98d40984ae1ed059e95962fb0c50..90ea1e457ba8031885f3941cb605e00e52590c0f 100644 (file)
@@ -51,7 +51,7 @@ pub fn inject(
             cx.item(
                 span,
                 ident,
-                vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
+                vec![cx.attribute(cx.meta_word(span, sym::macro_use))].into(),
                 ast::ItemKind::ExternCrate(None),
             ),
         );
@@ -78,7 +78,7 @@ pub fn inject(
     let use_item = cx.item(
         span,
         Ident::empty(),
-        vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
+        vec![cx.attribute(cx.meta_word(span, sym::prelude_import))].into(),
         ast::ItemKind::Use(ast::UseTree {
             prefix: cx.path(span, import_path),
             kind: ast::UseTreeKind::Glob,
index e20375689f3d1f7a136ea48c6d885563ff7bf4a8..03c84f5ec2a740fe1f158099885719b5369477c6 100644 (file)
@@ -227,7 +227,8 @@ pub fn expand_test_or_bench(
             )),
             // #[rustc_test_marker]
             cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
-        ],
+        ]
+        .into(),
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(
             ast::Defaultness::Final,
@@ -334,7 +335,7 @@ pub fn expand_test_or_bench(
     });
 
     // extern crate test
-    let test_extern = cx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None));
+    let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
 
     tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
index 0ebe29df95f202fa9edc2d6f71b46b346a123aa6..093f0f10a3867e591108604f1547841a960ff125 100644 (file)
@@ -298,8 +298,10 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let call_test_main = ecx.stmt_expr(call_test_main);
 
     // extern crate test
-    let test_extern_stmt =
-        ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None)));
+    let test_extern_stmt = ecx.stmt_item(
+        sp,
+        ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
+    );
 
     // #[rustc_main]
     let main_meta = ecx.meta_word(sp, sym::rustc_main);
@@ -333,7 +335,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let main = P(ast::Item {
         ident: main_id,
-        attrs: vec![main_attr],
+        attrs: vec![main_attr].into(),
         id: ast::DUMMY_NODE_ID,
         kind: main,
         vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },
index cf95c89bc3156b24b36d2bc0728a90f6e36fbd89..50261c193973932d85be96140e1359129e8e6641 100644 (file)
@@ -94,7 +94,7 @@ mod platform {
     struct Header(*mut u8);
     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
-        &mut *(ptr as *mut Header).offset(-1)
+        &mut *(ptr as *mut Header).sub(1)
     }
     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
         let aligned = ptr.add(align - (ptr as usize & (align - 1)));
index 5f66ca67f2d409e9699c49a9fcda047c1e8c6ca9..89661918d05a5d14e90359c267beb57f356dab98 100644 (file)
@@ -156,7 +156,7 @@ mod platform {
     struct Header(*mut u8);
     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
-        &mut *(ptr as *mut Header).offset(-1)
+        &mut *(ptr as *mut Header).sub(1)
     }
     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
         let aligned = ptr.add(align - (ptr as usize & (align - 1)));
index 874de03d37ac6295f8398e22acd0e3ac677bc38c..d912211443a893813d6b5c4fda225f2487765289 100644 (file)
@@ -1,3 +1,4 @@
+use crate::thin_vec::ThinVec;
 use smallvec::{Array, SmallVec};
 use std::ptr;
 
@@ -15,94 +16,64 @@ fn flat_map_in_place<F, I>(&mut self, f: F)
         I: IntoIterator<Item = T>;
 }
 
-impl<T> MapInPlace<T> for Vec<T> {
-    fn flat_map_in_place<F, I>(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator<Item = T>,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
+// The implementation of this method is syntactically identical for all the
+// different vector types.
+macro_rules! flat_map_in_place {
+    () => {
+        fn flat_map_in_place<F, I>(&mut self, mut f: F)
+        where
+            F: FnMut(T) -> I,
+            I: IntoIterator<Item = T>,
+        {
+            let mut read_i = 0;
+            let mut write_i = 0;
+            unsafe {
+                let mut old_len = self.len();
+                self.set_len(0); // make sure we just leak elements in case of panic
 
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.as_ptr().add(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
+                while read_i < old_len {
+                    // move the read_i'th item out of the vector and map it
+                    // to an iterator
+                    let e = ptr::read(self.as_ptr().add(read_i));
+                    let iter = f(e).into_iter();
+                    read_i += 1;
 
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.as_mut_ptr().add(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
+                    for e in iter {
+                        if write_i < read_i {
+                            ptr::write(self.as_mut_ptr().add(write_i), e);
+                            write_i += 1;
+                        } else {
+                            // If this is reached we ran out of space
+                            // in the middle of the vector.
+                            // However, the vector is in a valid state here,
+                            // so we just do a somewhat inefficient insert.
+                            self.set_len(old_len);
+                            self.insert(write_i, e);
 
-                        old_len = self.len();
-                        self.set_len(0);
+                            old_len = self.len();
+                            self.set_len(0);
 
-                        read_i += 1;
-                        write_i += 1;
+                            read_i += 1;
+                            write_i += 1;
+                        }
                     }
                 }
-            }
 
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
+                // write_i tracks the number of actually written new items.
+                self.set_len(write_i);
+            }
         }
-    }
+    };
 }
 
-impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
-    fn flat_map_in_place<F, I>(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator<Item = T>,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
-
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.as_ptr().add(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
-
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.as_mut_ptr().add(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
-
-                        old_len = self.len();
-                        self.set_len(0);
+impl<T> MapInPlace<T> for Vec<T> {
+    flat_map_in_place!();
+}
 
-                        read_i += 1;
-                        write_i += 1;
-                    }
-                }
-            }
+impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
+    flat_map_in_place!();
+}
 
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
-        }
-    }
+impl<T> MapInPlace<T> for ThinVec<T> {
+    flat_map_in_place!();
 }
index 716259142d18b22062149c4faa2c58de3c0966b6..fce42e709ab74cfefcf6d81ebff7d2ddc164ea32 100644 (file)
@@ -27,6 +27,51 @@ pub fn push(&mut self, item: T) {
             ThinVec(None) => *self = vec![item].into(),
         }
     }
+
+    /// Note: if `set_len(0)` is called on a non-empty `ThinVec`, it will
+    /// remain in the `Some` form. This is required for some code sequences
+    /// (such as the one in `flat_map_in_place`) that call `set_len(0)` before
+    /// an operation that might panic, and then call `set_len(n)` again
+    /// afterwards.
+    pub unsafe fn set_len(&mut self, new_len: usize) {
+        match *self {
+            ThinVec(None) => {
+                // A prerequisite of `Vec::set_len` is that `new_len` must be
+                // less than or equal to capacity(). The same applies here.
+                if new_len != 0 {
+                    panic!("unsafe ThinVec::set_len({})", new_len);
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.set_len(new_len),
+        }
+    }
+
+    pub fn insert(&mut self, index: usize, value: T) {
+        match *self {
+            ThinVec(None) => {
+                if index == 0 {
+                    *self = vec![value].into();
+                } else {
+                    panic!("invalid ThinVec::insert");
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.insert(index, value),
+        }
+    }
+
+    pub fn remove(&mut self, index: usize) -> T {
+        match self {
+            ThinVec(None) => panic!("invalid ThinVec::remove"),
+            ThinVec(Some(vec)) => vec.remove(index),
+        }
+    }
+
+    pub fn as_slice(&self) -> &[T] {
+        match self {
+            ThinVec(None) => &[],
+            ThinVec(Some(vec)) => vec.as_slice(),
+        }
+    }
 }
 
 impl<T> From<Vec<T>> for ThinVec<T> {
index 0ff64969b071c9954b5187adf209450124ee75dd..f016c391fe777cfc83c21e317c080db6440086e2 100644 (file)
@@ -1,45 +1,57 @@
+use crate::frozen::Frozen;
 use crate::fx::FxIndexSet;
-use crate::sync::Lock;
 use rustc_index::bit_set::BitMatrix;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
+use std::ops::Deref;
 
 #[cfg(test)]
 mod tests;
 
 #[derive(Clone, Debug)]
-pub struct TransitiveRelation<T> {
+pub struct TransitiveRelationBuilder<T> {
     // List of elements. This is used to map from a T to a usize.
     elements: FxIndexSet<T>,
 
     // List of base edges in the graph. Require to compute transitive
     // closure.
     edges: Vec<Edge>,
+}
+
+#[derive(Debug)]
+pub struct TransitiveRelation<T> {
+    // Frozen transitive relation elements and edges.
+    builder: Frozen<TransitiveRelationBuilder<T>>,
 
-    // This is a cached transitive closure derived from the edges.
-    // Currently, we build it lazily and just throw out any existing
-    // copy whenever a new edge is added. (The Lock is to permit
-    // the lazy computation.) This is kind of silly, except for the
-    // fact its size is tied to `self.elements.len()`, so I wanted to
-    // wait before building it up to avoid reallocating as new edges
-    // are added with new elements. Perhaps better would be to ask the
-    // user for a batch of edges to minimize this effect, but I
-    // already wrote the code this way. :P -nmatsakis
-    closure: Lock<Option<BitMatrix<usize, usize>>>,
+    // Cached transitive closure derived from the edges.
+    closure: Frozen<BitMatrix<usize, usize>>,
 }
 
-// HACK(eddyb) manual impl avoids `Default` bound on `T`.
-impl<T: Eq + Hash> Default for TransitiveRelation<T> {
-    fn default() -> Self {
+impl<T> Deref for TransitiveRelation<T> {
+    type Target = Frozen<TransitiveRelationBuilder<T>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.builder
+    }
+}
+
+impl<T: Clone> Clone for TransitiveRelation<T> {
+    fn clone(&self) -> Self {
         TransitiveRelation {
-            elements: Default::default(),
-            edges: Default::default(),
-            closure: Default::default(),
+            builder: Frozen::freeze(self.builder.deref().clone()),
+            closure: Frozen::freeze(self.closure.deref().clone()),
         }
     }
 }
 
+// HACK(eddyb) manual impl avoids `Default` bound on `T`.
+impl<T: Eq + Hash> Default for TransitiveRelationBuilder<T> {
+    fn default() -> Self {
+        TransitiveRelationBuilder { elements: Default::default(), edges: Default::default() }
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
 struct Index(usize);
 
@@ -49,7 +61,7 @@ struct Edge {
     target: Index,
 }
 
-impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
+impl<T: Eq + Hash + Copy> TransitiveRelationBuilder<T> {
     pub fn is_empty(&self) -> bool {
         self.edges.is_empty()
     }
@@ -63,23 +75,19 @@ fn index(&self, a: T) -> Option<Index> {
     }
 
     fn add_index(&mut self, a: T) -> Index {
-        let (index, added) = self.elements.insert_full(a);
-        if added {
-            // if we changed the dimensions, clear the cache
-            *self.closure.get_mut() = None;
-        }
+        let (index, _added) = self.elements.insert_full(a);
         Index(index)
     }
 
     /// Applies the (partial) function to each edge and returns a new
-    /// relation. If `f` returns `None` for any end-point, returns
-    /// `None`.
-    pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelation<U>>
+    /// relation builder. If `f` returns `None` for any end-point,
+    /// returns `None`.
+    pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelationBuilder<U>>
     where
         F: FnMut(T) -> Option<U>,
         U: Clone + Debug + Eq + Hash + Copy,
     {
-        let mut result = TransitiveRelation::default();
+        let mut result = TransitiveRelationBuilder::default();
         for edge in &self.edges {
             result.add(f(self.elements[edge.source.0])?, f(self.elements[edge.target.0])?);
         }
@@ -93,10 +101,38 @@ pub fn add(&mut self, a: T, b: T) {
         let edge = Edge { source: a, target: b };
         if !self.edges.contains(&edge) {
             self.edges.push(edge);
+        }
+    }
+
+    /// Compute the transitive closure derived from the edges, and converted to
+    /// the final result. After this, all elements will be immutable to maintain
+    /// the correctness of the result.
+    pub fn freeze(self) -> TransitiveRelation<T> {
+        let mut matrix = BitMatrix::new(self.elements.len(), self.elements.len());
+        let mut changed = true;
+        while changed {
+            changed = false;
+            for edge in &self.edges {
+                // add an edge from S -> T
+                changed |= matrix.insert(edge.source.0, edge.target.0);
 
-            // added an edge, clear the cache
-            *self.closure.get_mut() = None;
+                // add all outgoing edges from T into S
+                changed |= matrix.union_rows(edge.target.0, edge.source.0);
+            }
         }
+        TransitiveRelation { builder: Frozen::freeze(self), closure: Frozen::freeze(matrix) }
+    }
+}
+
+impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
+    /// Applies the (partial) function to each edge and returns a new
+    /// relation including transitive closures.
+    pub fn maybe_map<F, U>(&self, f: F) -> Option<TransitiveRelation<U>>
+    where
+        F: FnMut(T) -> Option<U>,
+        U: Clone + Debug + Eq + Hash + Copy,
+    {
+        Some(self.builder.maybe_map(f)?.freeze())
     }
 
     /// Checks whether `a < target` (transitively)
@@ -322,30 +358,7 @@ fn with_closure<OP, R>(&self, op: OP) -> R
     where
         OP: FnOnce(&BitMatrix<usize, usize>) -> R,
     {
-        let mut closure_cell = self.closure.borrow_mut();
-        let mut closure = closure_cell.take();
-        if closure.is_none() {
-            closure = Some(self.compute_closure());
-        }
-        let result = op(closure.as_ref().unwrap());
-        *closure_cell = closure;
-        result
-    }
-
-    fn compute_closure(&self) -> BitMatrix<usize, usize> {
-        let mut matrix = BitMatrix::new(self.elements.len(), self.elements.len());
-        let mut changed = true;
-        while changed {
-            changed = false;
-            for edge in &self.edges {
-                // add an edge from S -> T
-                changed |= matrix.insert(edge.source.0, edge.target.0);
-
-                // add all outgoing edges from T into S
-                changed |= matrix.union_rows(edge.target.0, edge.source.0);
-            }
-        }
-        matrix
+        op(&self.closure)
     }
 
     /// Lists all the base edges in the graph: the initial _non-transitive_ set of element
index e1f4c7ee07315cd15836497238d581bce322b05a..e756c546e41ba705f0b6fe4a839199acd8633d23 100644 (file)
@@ -10,9 +10,10 @@ fn postdom_parent(&self, a: T) -> Option<T> {
 
 #[test]
 fn test_one_step() {
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "b");
     relation.add("a", "c");
+    let relation = relation.freeze();
     assert!(relation.contains("a", "c"));
     assert!(relation.contains("a", "b"));
     assert!(!relation.contains("b", "a"));
@@ -21,7 +22,7 @@ fn test_one_step() {
 
 #[test]
 fn test_many_steps() {
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "b");
     relation.add("a", "c");
     relation.add("a", "f");
@@ -31,6 +32,7 @@ fn test_many_steps() {
     relation.add("b", "e");
 
     relation.add("e", "g");
+    let relation = relation.freeze();
 
     assert!(relation.contains("a", "b"));
     assert!(relation.contains("a", "c"));
@@ -51,9 +53,10 @@ fn mubs_triangle() {
     //      ^
     //      |
     //      b
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "tcx");
     relation.add("b", "tcx");
+    let relation = relation.freeze();
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["tcx"]);
     assert_eq!(relation.parents("a"), vec!["tcx"]);
     assert_eq!(relation.parents("b"), vec!["tcx"]);
@@ -72,7 +75,7 @@ fn mubs_best_choice1() {
     // need the second pare down call to get the right result (after
     // intersection, we have [1, 2], but 2 -> 1).
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -80,6 +83,7 @@ fn mubs_best_choice1() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["2"]);
     assert_eq!(relation.parents("0"), vec!["2"]);
@@ -99,7 +103,7 @@ fn mubs_best_choice2() {
     // Like the preceding test, but in this case intersection is [2,
     // 1], and hence we rely on the first pare down call.
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -107,6 +111,7 @@ fn mubs_best_choice2() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1"]);
     assert_eq!(relation.parents("0"), vec!["1"]);
@@ -118,12 +123,13 @@ fn mubs_best_choice2() {
 fn mubs_no_best_choice() {
     // in this case, the intersection yields [1, 2], and the "pare
     // down" calls find nothing to remove.
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1", "2"]);
     assert_eq!(relation.parents("0"), vec!["1", "2"]);
@@ -135,7 +141,7 @@ fn mubs_best_choice_scc() {
     // in this case, 1 and 2 form a cycle; we pick arbitrarily (but
     // consistently).
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -144,6 +150,7 @@ fn mubs_best_choice_scc() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1"]);
     assert_eq!(relation.parents("0"), vec!["1"]);
@@ -157,13 +164,14 @@ fn pdub_crisscross() {
     //   /\       |
     // b -> b1 ---+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("a", "b1");
     relation.add("b", "a1");
     relation.add("b", "b1");
     relation.add("a1", "x");
     relation.add("b1", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["a1", "b1"]);
     assert_eq!(relation.postdom_upper_bound("a", "b"), Some("x"));
@@ -179,7 +187,7 @@ fn pdub_crisscross_more() {
     //   /\    /\             |
     // b -> b1 -> b2 ---------+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("a", "b1");
     relation.add("b", "a1");
@@ -194,6 +202,7 @@ fn pdub_crisscross_more() {
 
     relation.add("a3", "x");
     relation.add("b2", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["a1", "b1"]);
     assert_eq!(relation.minimal_upper_bounds("a1", "b1"), vec!["a2", "b2"]);
@@ -210,11 +219,12 @@ fn pdub_lub() {
     //            |
     // b -> b1 ---+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("b", "b1");
     relation.add("a1", "x");
     relation.add("b1", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["x"]);
     assert_eq!(relation.postdom_upper_bound("a", "b"), Some("x"));
@@ -233,10 +243,11 @@ fn mubs_intermediate_node_on_one_side_only() {
     //           b
 
     // "digraph { a -> c -> d; b -> d; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("b", "d");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["d"]);
 }
@@ -252,12 +263,13 @@ fn mubs_scc_1() {
     //           b
 
     // "digraph { a -> c -> d; d -> c; a -> d; b -> d; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "c");
     relation.add("a", "d");
     relation.add("b", "d");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -272,12 +284,13 @@ fn mubs_scc_2() {
     //      +--- b
 
     // "digraph { a -> c -> d; d -> c; b -> d; b -> c; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "c");
     relation.add("b", "d");
     relation.add("b", "c");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -292,13 +305,14 @@ fn mubs_scc_3() {
     //           b ---+
 
     // "digraph { a -> c -> d -> e -> c; b -> d; b -> e; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "e");
     relation.add("e", "c");
     relation.add("b", "d");
     relation.add("b", "e");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -314,13 +328,14 @@ fn mubs_scc_4() {
     //           b ---+
 
     // "digraph { a -> c -> d -> e -> c; a -> d; b -> e; }"
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "e");
     relation.add("e", "c");
     relation.add("a", "d");
     relation.add("b", "e");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -352,10 +367,11 @@ fn parent() {
         (1, /*->*/ 3),
     ];
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     for (a, b) in pairs {
         relation.add(a, b);
     }
+    let relation = relation.freeze();
 
     let p = relation.postdom_parent(3);
     assert_eq!(p, Some(0));
index 94639bf8e1ee4f1d122cd6bf52e382d9e79d52dd..dac8df7dc55e0966d1a86f3d3ef2fb98d4589984 100644 (file)
@@ -1070,7 +1070,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     Some(matches)
 }
 
-fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec<ast::Attribute>> {
+fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::AttrVec> {
     match input {
         Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
         Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
new file mode 100644 (file)
index 0000000..db91a88
--- /dev/null
@@ -0,0 +1,93 @@
+ast_passes_forbidden_let =
+    `let` expressions are not supported here
+    .note = only supported directly in conditions of `if` and `while` expressions
+    .not_supported_or = `||` operators are not supported in let chain expressions
+    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+
+ast_passes_deprecated_where_clause_location =
+    where clause not allowed here
+
+ast_passes_forbidden_assoc_constraint =
+    associated type bounds are not allowed within structs, enums, or unions
+
+ast_passes_keyword_lifetime =
+    lifetimes cannot use keyword names
+
+ast_passes_invalid_label =
+    invalid label name `{$name}`
+
+ast_passes_invalid_visibility =
+    unnecessary visibility qualifier
+    .implied = `pub` not permitted here because it's implied
+    .individual_impl_items = place qualifiers on individual impl items instead
+    .individual_foreign_items = place qualifiers on individual foreign items instead
+
+ast_passes_trait_fn_async =
+    functions in traits cannot be declared `async`
+    .label = `async` because of this
+    .note = `async` trait functions are not currently supported
+    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+ast_passes_trait_fn_const =
+    functions in traits cannot be declared const
+    .label = functions in traits cannot be const
+
+ast_passes_forbidden_lifetime_bound =
+    lifetime bounds cannot be used in this context
+
+ast_passes_forbidden_non_lifetime_param =
+    only lifetime parameters can be used in this context
+
+ast_passes_fn_param_too_many =
+    function can not have more than {$max_num_args} arguments
+
+ast_passes_fn_param_c_var_args_only =
+    C-variadic function must be declared with at least one named argument
+
+ast_passes_fn_param_c_var_args_not_last =
+    `...` must be the last argument of a C-variadic function
+
+ast_passes_fn_param_doc_comment =
+    documentation comments cannot be applied to function parameters
+    .label = doc comments are not allowed here
+
+ast_passes_fn_param_forbidden_attr =
+    allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+
+ast_passes_fn_param_forbidden_self =
+    `self` parameter is only allowed in associated functions
+    .label = not semantically valid as function parameter
+    .note = associated functions are those in `impl` or `trait` definitions
+
+ast_passes_forbidden_default =
+    `default` is only allowed on items in trait impls
+    .label = `default` because of this
+
+ast_passes_assoc_const_without_body =
+    associated constant in `impl` without body
+    .suggestion = provide a definition for the constant
+
+ast_passes_assoc_fn_without_body =
+    associated function in `impl` without body
+    .suggestion = provide a definition for the function
+
+ast_passes_assoc_type_without_body =
+    associated type in `impl` without body
+    .suggestion = provide a definition for the type
+
+ast_passes_const_without_body =
+    free constant item without body
+    .suggestion = provide a definition for the constant
+
+ast_passes_static_without_body =
+    free static item without body
+    .suggestion = provide a definition for the static
+
+ast_passes_ty_alias_without_body =
+    free type alias without body
+    .suggestion = provide a definition for the type
+
+ast_passes_fn_without_body =
+    free function without a body
+    .suggestion = provide a definition for the function
+    .extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
index 4af40d2062d3a79c275cfe22d841105e282bbb5d..a96fe7c8a05d58710c3dbe36b4111d3dc3225e8d 100644 (file)
@@ -13,6 +13,6 @@ borrowck_could_not_normalize =
 
 borrowck_higher_ranked_subtype_error =
     higher-ranked subtype error
-  
-generic_does_not_live_long_enough =
-    `{$kind}` does not live long enough
\ No newline at end of file
+
+borrowck_generic_does_not_live_long_enough =
+    `{$kind}` does not live long enough
index ee76a4f45005d1c5ed71db9903ce3d5e541b14f3..5720591154f9914e2ff3f9ada81c45edb4252118 100644 (file)
@@ -4,10 +4,10 @@ expand_explain_doc_comment_outer =
 expand_explain_doc_comment_inner =
     inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
 
-expand_expr_repeat_no_syntax_vars = 
+expand_expr_repeat_no_syntax_vars =
     attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 
-expand_must_repeat_once = 
+expand_must_repeat_once =
     this must repeat at least once
 
 expand_count_repetition_misplaced =
@@ -19,4 +19,4 @@ expand_meta_var_expr_unrecognized_var =
 expand_var_still_repeating =
     variable '{$ident}' is still repeating at this depth
 
-expand_meta_var_dif_seq_matchers = {$msg}
\ No newline at end of file
+expand_meta_var_dif_seq_matchers = {$msg}
index ee978f04be2a5db31b3bdeb42233e8be6b63170a..3569c7f0630649d36721b26478892c5f4579aebc 100644 (file)
@@ -32,6 +32,7 @@
 
 // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
 fluent_messages! {
+    ast_passes => "../locales/en-US/ast_passes.ftl",
     borrowck => "../locales/en-US/borrowck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
     const_eval => "../locales/en-US/const_eval.ftl",
index 852ea806b20ff51c64139e3b5a2b293f7496b877..df56e032988c6e05c695e49d45b64a2d38741313 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{AssocCtxt, Visitor};
-use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind};
+use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
 use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::{self, Lrc};
@@ -71,7 +71,7 @@ pub fn span(&self) -> Span {
         }
     }
 
-    pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         match self {
             Annotatable::Item(item) => item.visit_attrs(f),
             Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f),
index 0440bca53b232c3ab0be43a664db9326cb36679a..c4890b4a9c41378e14fdc07cf4ae6a2f883a9a45 100644 (file)
@@ -575,7 +575,7 @@ pub fn item(
         &self,
         span: Span,
         name: Ident,
-        attrs: Vec<ast::Attribute>,
+        attrs: ast::AttrVec,
         kind: ast::ItemKind,
     ) -> P<ast::Item> {
         // FIXME: Would be nice if our generated code didn't violate
@@ -603,7 +603,7 @@ pub fn item_static(
         mutbl: ast::Mutability,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
-        self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
+        self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
     }
 
     pub fn item_const(
@@ -614,7 +614,7 @@ pub fn item_const(
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         let def = ast::Defaultness::Final;
-        self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
+        self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
     }
 
     pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
index 3e1acf4382d5bcd48f7f3ba0664786010ddb15a2..48ee23d2c3d18e50fb2712cfa3198f36a08ea7f1 100644 (file)
@@ -215,7 +215,7 @@ pub fn features(
     let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) {
         None => {
             // The entire crate is unconfigured.
-            krate.attrs = Vec::new();
+            krate.attrs = ast::AttrVec::new();
             krate.items = Vec::new();
             Features::default()
         }
@@ -265,7 +265,7 @@ fn try_configure_tokens<T: HasTokens>(&self, node: &mut T) {
         }
     }
 
-    fn configure_krate_attrs(&self, mut attrs: Vec<ast::Attribute>) -> Option<Vec<ast::Attribute>> {
+    fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
         attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
         if self.in_cfg(&attrs) { Some(attrs) } else { None }
     }
@@ -292,9 +292,7 @@ fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool {
             .iter()
             .flat_map(|(tree, spacing)| match tree.clone() {
                 AttrAnnotatedTokenTree::Attributes(mut data) => {
-                    let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into();
-                    attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-                    data.attrs = attrs.into();
+                    data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
 
                     if self.in_cfg(&data.attrs) {
                         data.tokens = LazyTokenStream::new(
index cc72dab84afa2a6f7b51ff64bad5dd57f6fa029c..c2add852a0679672e97a5ae8a1714d29c1ad8c1c 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind};
+use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, AttrVec, ExprKind, ForeignItemKind};
 use rustc_ast::{HasAttrs, HasNodeId};
 use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind};
 use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
@@ -1001,7 +1001,7 @@ enum AddSemicolon {
 /// of functionality used by `InvocationCollector`.
 trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     type OutputTy = SmallVec<[Self; 1]>;
-    type AttrsTy: Deref<Target = [ast::Attribute]> = Vec<ast::Attribute>;
+    type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
     const KIND: AstFragmentKind;
     fn to_annotatable(self) -> Annotatable;
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
@@ -1333,7 +1333,7 @@ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
             }
             StmtKind::Item(item) => match item.into_inner() {
                 ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
-                    (mac.args.need_semicolon(), mac, attrs.into())
+                    (mac.args.need_semicolon(), mac, attrs)
                 }
                 _ => unreachable!(),
             },
@@ -1390,7 +1390,7 @@ fn is_mac_call(&self) -> bool {
     fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
-            TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
+            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
         }
     }
@@ -1414,7 +1414,7 @@ fn is_mac_call(&self) -> bool {
     fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
-            PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
+            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
         }
     }
@@ -1646,7 +1646,11 @@ fn expand_cfg_true(
 
     fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) {
         node.visit_attrs(|attrs| {
-            attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
+            // Repeated `insert` calls is inefficient, but the number of
+            // insertions is almost always 0 or 1 in practice.
+            for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() {
+                attrs.insert(pos, cfg)
+            }
         });
     }
 
index 0315d11634c6b6b16afa213008c1c8e84ea4e30d..9002a24e42f9df671dc913fe744306dd480909ef 100644 (file)
@@ -1,6 +1,6 @@
 use crate::base::ModuleData;
 use rustc_ast::ptr::P;
-use rustc_ast::{token, Attribute, Inline, Item, ModSpans};
+use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_parse::new_parser_from_file;
 use rustc_parse::validate_attr;
@@ -48,7 +48,7 @@ pub(crate) fn parse_external_mod(
     span: Span, // The span to blame on errors.
     module: &ModuleData,
     mut dir_ownership: DirOwnership,
-    attrs: &mut Vec<Attribute>,
+    attrs: &mut AttrVec,
 ) -> ParsedExternalMod {
     // We bail on the first error, but that error does not cause a fatal error... (1)
     let result: Result<_, ModError<'_>> = try {
@@ -63,9 +63,9 @@ pub(crate) fn parse_external_mod(
 
         // Actually parse the external file as a module.
         let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span));
-        let (mut inner_attrs, items, inner_span) =
+        let (inner_attrs, items, inner_span) =
             parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
-        attrs.append(&mut inner_attrs);
+        attrs.extend(inner_attrs);
         (items, inner_span, mp.file_path)
     };
     // (1) ...instead, we return a dummy module.
index 48918541e72fcb2e4d720cb6573e9aedef854b01..3b0d5ddb97b4e184e11b2608a37dbb05a71c719d 100644 (file)
@@ -24,7 +24,7 @@ fn mac_placeholder() -> P<ast::MacCall> {
     }
 
     let ident = Ident::empty();
-    let attrs = Vec::new();
+    let attrs = ast::AttrVec::new();
     let vis = vis.unwrap_or(ast::Visibility {
         span: DUMMY_SP,
         kind: ast::VisibilityKind::Inherited,
index 8fb5f159136be5fbabbee0cd3b16e55dd2eefdb1..59ea1f3f9de456187016a69e4d8d82f51dfa26c5 100644 (file)
@@ -740,12 +740,12 @@ fn note_error_origin(
                 err.help("...or use `match` instead of `let...else`");
             }
             _ => {
-                if let ObligationCauseCode::BindingObligation(_, binding_span) =
-                    cause.code().peel_derives()
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
+                    = cause.code().peel_derives()
+                    && let TypeError::RegionsPlaceholderMismatch = terr
                 {
-                    if matches!(terr, TypeError::RegionsPlaceholderMismatch) {
-                        err.span_note(*binding_span, "the lifetime requirement is introduced here");
-                    }
+                    err.span_note(*span, "the lifetime requirement is introduced here");
                 }
             }
         }
index 893ca3cf79d70aab9dd4831073dded0785e04f21..c20b96cae2e4f000a28da7346e06c14b1b40e2f0 100644 (file)
@@ -35,7 +35,8 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorGuaran
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
         };
-        let ObligationCauseCode::BindingObligation(_def_id, binding_span) = *parent.code() else {
+        let (ObligationCauseCode::BindingObligation(_, binding_span) | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..))
+            = *parent.code() else {
             return None;
         };
         let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type");
index 998699158ff484d57c8154ae99c3793fd2748ed4..d4db0751212f7ce8033af90f00171a9ccb697fcc 100644 (file)
@@ -211,7 +211,10 @@ fn report_trait_placeholder_mismatch(
         );
         let mut err = self.tcx().sess.struct_span_err(span, &msg);
 
-        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = *cause.code() {
+        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id)
+        | ObligationCauseCode::ExprItemObligation(def_id, ..) =
+            *cause.code()
+        {
             err.span_label(span, "doesn't satisfy where-clause");
             err.span_label(
                 self.tcx().def_span(def_id),
index 9886c572a8aaf4897d0de7dca6b4244ec71e0526..f804569b0747ea0c45771f7f6be92de3fc603e02 100644 (file)
@@ -232,7 +232,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorGuaranteed> {
                 ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
                 _ => cause.code(),
             }
-            && let (&ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
+            && let (&ObligationCauseCode::ItemObligation(item_def_id) | &ObligationCauseCode::ExprItemObligation(item_def_id, ..), None) = (code, override_error_code)
         {
             // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
             // lifetime as above, but called using a fully-qualified path to the method:
index 8dabdfd55c7e8f719dddb5134581853a567bead3..8c465b087600262b7faa86f835ef1c271487052a 100644 (file)
@@ -390,10 +390,12 @@ pub(super) fn report_placeholder_failure(
                 if matches!(
                     &trace.cause.code().peel_derives(),
                     ObligationCauseCode::BindingObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
                 ) =>
             {
                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::BindingObligation(_, span) =
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
                     &trace.cause.code().peel_derives()
                 {
                     let span = *span;
index d566634a49203b9272a9ed4802f51f3d2fd70d04..728d691a2be7d27bc42121264409fe23e33a6138 100644 (file)
@@ -27,13 +27,13 @@ pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'
     }
 }
 
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug)]
 pub struct FreeRegionMap<'tcx> {
     // Stores the relation `a < b`, where `a` and `b` are regions.
     //
     // Invariant: only free regions like `'x` or `'static` are stored
     // in this relation, not scopes.
-    relation: TransitiveRelation<Region<'tcx>>,
+    pub(crate) relation: TransitiveRelation<Region<'tcx>>,
 }
 
 impl<'tcx> FreeRegionMap<'tcx> {
@@ -45,15 +45,6 @@ pub fn is_empty(&self) -> bool {
         self.relation.is_empty()
     }
 
-    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
-    // (with the exception that `'static: 'x` is not notable)
-    pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
-        debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
-        if sub.is_free_or_static() && sup.is_free() {
-            self.relation.add(sub, sup)
-        }
-    }
-
     /// Tests whether `r_a <= r_b`.
     ///
     /// Both regions must meet `is_free_or_static`.
index b2decd64f0fd9690d1bab2db52559ccb48f05d89..872886da3626108ca370bfb942d650bced1a1775 100644 (file)
@@ -2,6 +2,7 @@
 use crate::infer::{GenericKind, InferCtxt};
 use crate::traits::query::OutlivesBound;
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
 use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
 
 use super::explicit_outlives_bounds;
@@ -51,23 +52,48 @@ pub struct OutlivesEnvironment<'tcx> {
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
+/// Builder of OutlivesEnvironment.
+struct OutlivesEnvironmentBuilder<'tcx> {
+    param_env: ty::ParamEnv<'tcx>,
+    region_relation: TransitiveRelationBuilder<Region<'tcx>>,
+    region_bound_pairs: RegionBoundPairs<'tcx>,
+}
+
 /// "Region-bound pairs" tracks outlives relations that are known to
 /// be true, either because of explicit where-clauses like `T: 'a` or
 /// because of implied bounds.
 pub type RegionBoundPairs<'tcx> =
     FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
 
-impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
-    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
-        let mut env = OutlivesEnvironment {
+impl<'tcx> OutlivesEnvironment<'tcx> {
+    /// Create a builder using `ParamEnv` and add explicit outlives bounds into it.
+    fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
+        let mut builder = OutlivesEnvironmentBuilder {
             param_env,
-            free_region_map: Default::default(),
+            region_relation: Default::default(),
             region_bound_pairs: Default::default(),
         };
 
-        env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
+        builder.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
 
-        env
+        builder
+    }
+
+    #[inline]
+    /// Create a new `OutlivesEnvironment` without extra outlives bounds.
+    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
+        Self::builder(param_env).build()
+    }
+
+    /// Create a new `OutlivesEnvironment` with extra outlives bounds.
+    pub fn with_bounds<'a>(
+        param_env: ty::ParamEnv<'tcx>,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
+    ) -> Self {
+        let mut builder = Self::builder(param_env);
+        builder.add_outlives_bounds(infcx, extra_bounds);
+        builder.build()
     }
 
     /// Borrows current value of the `free_region_map`.
@@ -79,6 +105,17 @@ pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
     pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
         &self.region_bound_pairs
     }
+}
+
+impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
+    #[inline]
+    fn build(self) -> OutlivesEnvironment<'tcx> {
+        OutlivesEnvironment {
+            param_env: self.param_env,
+            free_region_map: FreeRegionMap { relation: self.region_relation.freeze() },
+            region_bound_pairs: self.region_bound_pairs,
+        }
+    }
 
     /// Processes outlives bounds that are known to hold, whether from implied or other sources.
     ///
@@ -86,11 +123,8 @@ pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    pub fn add_outlives_bounds<I>(
-        &mut self,
-        infcx: Option<&InferCtxt<'a, 'tcx>>,
-        outlives_bounds: I,
-    ) where
+    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
+    where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
@@ -122,7 +156,9 @@ pub fn add_outlives_bounds<I>(
                         // system to be more general and to make use
                         // of *every* relationship that arises here,
                         // but presently we do not.)
-                        self.free_region_map.relate_regions(r_a, r_b);
+                        if r_a.is_free_or_static() && r_b.is_free() {
+                            self.region_relation.add(r_a, r_b)
+                        }
                     }
                 }
             }
index ad052f58ca854b1c29e4369d431df194d80294fb..dded0a0a6b1b4e51a75ab741e60f5871cafe7d3b 100644 (file)
@@ -97,7 +97,8 @@ pub fn register_region_obligation_with_cause(
                 cause.span,
                 sup_type,
                 match cause.code().peel_derives() {
-                    ObligationCauseCode::BindingObligation(_, span) => Some(*span),
+                    ObligationCauseCode::BindingObligation(_, span)
+                    | ObligationCauseCode::ExprBindingObligation(_, span, ..) => Some(*span),
                     _ => None,
                 },
             )
index 580a4566869f052e34e57c311d5fcc169fd75cee..cdb5b3c4284a8d37afc0dd2f6bb7b4f8c3006937 100644 (file)
@@ -45,7 +45,7 @@ fn check_id(&mut self, id: ast::NodeId) {
                 lint_id.lint,
                 Some(span),
                 |lint| {
-                    lint.build(&msg).emit();
+                    lint.build(msg).emit();
                 },
                 diagnostic,
             );
index a826f599e9cd5f92e5384ba794c9c163bbf316c3..9e7cbba9511b206a85a76a6150a4af9bf483dc6c 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_ast::node_id::{NodeId, NodeMap};
 use rustc_ast::{AttrId, Attribute};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_error_messages::MultiSpan;
+use rustc_error_messages::{DiagnosticMessage, MultiSpan};
 use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
 use rustc_span::edition::Edition;
@@ -491,7 +491,7 @@ pub struct BufferedEarlyLint {
     pub span: MultiSpan,
 
     /// The lint message.
-    pub msg: String,
+    pub msg: DiagnosticMessage,
 
     /// The `NodeId` of the AST node that generated the lint.
     pub node_id: NodeId,
@@ -520,11 +520,11 @@ pub fn add_lint(
         lint: &'static Lint,
         node_id: NodeId,
         span: MultiSpan,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         let lint_id = LintId::of(lint);
-        let msg = msg.to_string();
+        let msg = msg.into();
         self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
     }
 
@@ -537,7 +537,7 @@ pub fn buffer_lint(
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) {
         self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
     }
@@ -547,7 +547,7 @@ pub fn buffer_lint_with_diagnostic(
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.add_lint(lint, id, sp.into(), msg, diagnostic)
index 002abb152f7597a788fa4cbb954febfa6e94d00e..ad9ecd39b9e85a29989670027afba4cdeed1bf97 100644 (file)
@@ -235,35 +235,40 @@ fn build_format(&self, input: &str, span: proc_macro2::Span) -> TokenStream {
         // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so
         // the next call to `it.next()` retrieves the next character.
         while let Some(c) = it.next() {
-            if c == '{' && *it.peek().unwrap_or(&'\0') != '{' {
-                let mut eat_argument = || -> Option<String> {
-                    let mut result = String::new();
-                    // Format specifiers look like:
-                    //
-                    //   format   := '{' [ argument ] [ ':' format_spec ] '}' .
-                    //
-                    // Therefore, we only need to eat until ':' or '}' to find the argument.
-                    while let Some(c) = it.next() {
-                        result.push(c);
-                        let next = *it.peek().unwrap_or(&'\0');
-                        if next == '}' {
-                            break;
-                        } else if next == ':' {
-                            // Eat the ':' character.
-                            assert_eq!(it.next().unwrap(), ':');
-                            break;
-                        }
-                    }
-                    // Eat until (and including) the matching '}'
-                    while it.next()? != '}' {
-                        continue;
+            if c != '{' {
+                continue;
+            }
+            if *it.peek().unwrap_or(&'\0') == '{' {
+                assert_eq!(it.next().unwrap(), '{');
+                continue;
+            }
+            let mut eat_argument = || -> Option<String> {
+                let mut result = String::new();
+                // Format specifiers look like:
+                //
+                //   format   := '{' [ argument ] [ ':' format_spec ] '}' .
+                //
+                // Therefore, we only need to eat until ':' or '}' to find the argument.
+                while let Some(c) = it.next() {
+                    result.push(c);
+                    let next = *it.peek().unwrap_or(&'\0');
+                    if next == '}' {
+                        break;
+                    } else if next == ':' {
+                        // Eat the ':' character.
+                        assert_eq!(it.next().unwrap(), ':');
+                        break;
                     }
-                    Some(result)
-                };
-
-                if let Some(referenced_field) = eat_argument() {
-                    referenced_fields.insert(referenced_field);
                 }
+                // Eat until (and including) the matching '}'
+                while it.next()? != '}' {
+                    continue;
+                }
+                Some(result)
+            };
+
+            if let Some(referenced_field) = eat_argument() {
+                referenced_fields.insert(referenced_field);
             }
         }
 
index 8a727d9a1825ad7f724f04b2ab095d96c116c57e..f78f62e31d286024d6043478e9834be9a041a0a8 100644 (file)
         desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
+    /// Returns the types assumed to be well formed while "inside" of the given item.
+    ///
+    /// Note that we've liberated the late bound regions of function signatures, so
+    /// this can not be used to check whether these types are well formed.
+    query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+        desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) }
+    }
+
     /// Computes the signature of the function.
     query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
         desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
index 72b848c3ee2dd150728d09ba9a05e1d556597b2a..9b82320e556b33fb1714e2ccc04e7672aa0f4fab 100644 (file)
@@ -234,13 +234,23 @@ pub enum ObligationCauseCode<'tcx> {
     /// This is the trait reference from the given projection.
     ProjectionWf(ty::ProjectionTy<'tcx>),
 
-    /// In an impl of trait `X` for type `Y`, type `Y` must
-    /// also implement all supertraits of `X`.
+    /// Must satisfy all of the where-clause predicates of the
+    /// given item.
     ItemObligation(DefId),
 
-    /// Like `ItemObligation`, but with extra detail on the source of the obligation.
+    /// Like `ItemObligation`, but carries the span of the
+    /// predicate when it can be identified.
     BindingObligation(DefId, Span),
 
+    /// Like `ItemObligation`, but carries the `HirId` of the
+    /// expression that caused the obligation, and the `usize`
+    /// indicates exactly which predicate it is in the list of
+    /// instantiated predicates.
+    ExprItemObligation(DefId, rustc_hir::HirId, usize),
+
+    /// Combines `ExprItemObligation` and `BindingObligation`.
+    ExprBindingObligation(DefId, Span, rustc_hir::HirId, usize),
+
     /// A type like `&'a T` is WF only if `T: 'a`.
     ReferenceOutlivesReferent(Ty<'tcx>),
 
index add2df25884e3f1b7e1406b5e503f5dd9b0f0902..823e7f22af24da43f7655910de9567c5df542f5a 100644 (file)
@@ -122,6 +122,21 @@ pub struct Generics {
 }
 
 impl<'tcx> Generics {
+    /// Looks through the generics and all parents to find the index of the
+    /// given param def-id. This is in comparison to the `param_def_id_to_index`
+    /// struct member, which only stores information about this item's own
+    /// generics.
+    pub fn param_def_id_to_index(&self, tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<u32> {
+        if let Some(idx) = self.param_def_id_to_index.get(&def_id) {
+            Some(*idx)
+        } else if let Some(parent) = self.parent {
+            let parent = tcx.generics_of(parent);
+            parent.param_def_id_to_index(tcx, def_id)
+        } else {
+            None
+        }
+    }
+
     #[inline]
     pub fn count(&self) -> usize {
         self.parent_count + self.params.len()
index db3b5cfd180565e9094b471132459ccd6a9b18b0..79365ef281be792d2b9caa72912ad25c2bae60d2 100644 (file)
@@ -65,6 +65,10 @@ pub fn empty<'a>() -> &'a List<T> {
     pub fn len(&self) -> usize {
         self.len
     }
+
+    pub fn as_slice(&self) -> &[T] {
+        self
+    }
 }
 
 impl<T: Copy> List<T> {
index 0a660ef30c88ee333bfc4cf6fc58bc77bc0b711a..443626d14b9f67c636bed05f1a7483d9366ce79d 100644 (file)
@@ -364,8 +364,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
 /// works well.
 #[derive(Clone)]
-struct PatStack<'p, 'tcx> {
-    pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
+pub(crate) struct PatStack<'p, 'tcx> {
+    pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
 }
 
 impl<'p, 'tcx> PatStack<'p, 'tcx> {
@@ -403,6 +403,21 @@ fn expand_or_pat<'a>(&'a self) -> impl Iterator<Item = PatStack<'p, 'tcx>> + Cap
         })
     }
 
+    // Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix.
+    fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) {
+        if !self.is_empty() && self.head().is_or_pat() {
+            for pat in self.head().iter_fields() {
+                let mut new_patstack = PatStack::from_pattern(pat);
+                new_patstack.pats.extend_from_slice(&self.pats[1..]);
+                if !new_patstack.is_empty() && new_patstack.head().is_or_pat() {
+                    new_patstack.expand_and_extend(matrix);
+                } else if !new_patstack.is_empty() {
+                    matrix.push(new_patstack);
+                }
+            }
+        }
+    }
+
     /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations.
     ///
     /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
@@ -436,7 +451,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// A 2D matrix.
 #[derive(Clone)]
 pub(super) struct Matrix<'p, 'tcx> {
-    patterns: Vec<PatStack<'p, 'tcx>>,
+    pub patterns: Vec<PatStack<'p, 'tcx>>,
 }
 
 impl<'p, 'tcx> Matrix<'p, 'tcx> {
@@ -453,7 +468,7 @@ pub(super) fn column_count(&self) -> Option<usize> {
     /// expands it.
     fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if !row.is_empty() && row.head().is_or_pat() {
-            self.patterns.extend(row.expand_or_pat());
+            row.expand_and_extend(self);
         } else {
             self.patterns.push(row);
         }
index f9fd6c9c56b424333800c62248928d2637c94875..d9aff94fef2f9f28ddd97ebb01a6528d40a7f038 100644 (file)
@@ -256,6 +256,7 @@ fn apply_switch_int_edge_effects(
     ///     .iterate_to_fixpoint()
     ///     .into_results_cursor(body);
     /// ```
+    #[inline]
     fn into_engine<'mir>(
         self,
         tcx: TyCtxt<'tcx>,
@@ -413,7 +414,7 @@ fn apply_switch_int_edge_effects(
     }
 
     /* Extension methods */
-
+    #[inline]
     fn into_engine<'mir>(
         self,
         tcx: TyCtxt<'tcx>,
index 96bbf5802e738c734f6dc9f3298f7dd36a34852b..82ef16a7f72fc526f5c9bbf3319e8cdd3fdb7ccc 100644 (file)
 //! #### Unsizing Casts
 //! A subtle way of introducing neighbor edges is by casting to a trait object.
 //! Since the resulting fat-pointer contains a reference to a vtable, we need to
-//! instantiate all object-save methods of the trait, as we need to store
+//! instantiate all object-safe methods of the trait, as we need to store
 //! pointers to these functions even if they never get called anywhere. This can
 //! be seen as a special case of taking a function reference.
 //!
@@ -1044,10 +1044,12 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
 /// them.
 ///
 /// For example, the source type might be `&SomeStruct` and the target type
-/// might be `&SomeTrait` in a cast like:
+/// might be `&dyn SomeTrait` in a cast like:
 ///
+/// ```rust,ignore (not real code)
 /// let src: &SomeStruct = ...;
-/// let target = src as &SomeTrait;
+/// let target = src as &dyn SomeTrait;
+/// ```
 ///
 /// Then the output of this function would be (SomeStruct, SomeTrait) since for
 /// constructing the `target` fat-pointer we need the vtable for that pair.
@@ -1068,8 +1070,10 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
 /// for the pair of `T` (which is a trait) and the concrete type that `T` was
 /// originally coerced from:
 ///
+/// ```rust,ignore (not real code)
 /// let src: &ComplexStruct<SomeStruct> = ...;
-/// let target = src as &ComplexStruct<SomeTrait>;
+/// let target = src as &ComplexStruct<dyn SomeTrait>;
+/// ```
 ///
 /// Again, we want this `find_vtable_types_for_unsizing()` to provide the pair
 /// `(SomeStruct, SomeTrait)`.
index 5924eba9f8b423b9e59484feca8f343886550ca1..3691d82a835a9d57158e101d24de1e05419e0b5d 100644 (file)
@@ -62,7 +62,7 @@ pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'
 pub fn parse_crate_attrs_from_file<'a>(
     input: &Path,
     sess: &'a ParseSess,
-) -> PResult<'a, Vec<ast::Attribute>> {
+) -> PResult<'a, ast::AttrVec> {
     let mut parser = new_parser_from_file(sess, input, None);
     parser.parse_inner_attributes()
 }
@@ -79,7 +79,7 @@ pub fn parse_crate_attrs_from_source_str(
     name: FileName,
     source: String,
     sess: &ParseSess,
-) -> PResult<'_, Vec<ast::Attribute>> {
+) -> PResult<'_, ast::AttrVec> {
     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
 }
 
index acdbddf4099e6411fd213901c027ae9e54da8aa2..72ab96b5ca67032aa9e4c83509e42a5b4ced6613 100644 (file)
@@ -34,7 +34,7 @@ enum OuterAttributeType {
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
-        let mut outer_attrs: Vec<ast::Attribute> = Vec::new();
+        let mut outer_attrs = ast::AttrVec::new();
         let mut just_parsed_doc_comment = false;
         let start_pos = self.token_cursor.num_next_calls;
         loop {
@@ -106,7 +106,7 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
                 break;
             }
         }
-        Ok(AttrWrapper::new(outer_attrs.into(), start_pos))
+        Ok(AttrWrapper::new(outer_attrs, start_pos))
     }
 
     /// Matches `attribute = # ! [ meta_item ]`.
@@ -283,8 +283,8 @@ pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::Attr
     /// terminated by a semicolon.
     ///
     /// Matches `inner_attrs*`.
-    pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
-        let mut attrs: Vec<ast::Attribute> = vec![];
+    pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
+        let mut attrs = ast::AttrVec::new();
         loop {
             let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap();
             // Only try to parse if it is an inner attribute (has `!`).
index 6c750ff428f5338acaf7b3d380d57d5e7440ed52..ed54af9f53fb7f914622ecb9ec7b7565b25ce5ac 100644 (file)
 /// for the attribute target. This allows us to perform cfg-expansion on
 /// a token stream before we invoke a derive proc-macro.
 ///
-/// This wrapper prevents direct access to the underlying `Vec<ast::Attribute>`.
+/// This wrapper prevents direct access to the underlying `ast::AttrVec>`.
 /// Parsing code can only get access to the underlying attributes
 /// by passing an `AttrWrapper` to `collect_tokens_trailing_tokens`.
 /// This makes it difficult to accidentally construct an AST node
-/// (which stores a `Vec<ast::Attribute>`) without first collecting tokens.
+/// (which stores an `ast::AttrVec`) without first collecting tokens.
 ///
 /// This struct has its own module, to ensure that the parser code
 /// cannot directly access the `attrs` field
@@ -49,9 +49,10 @@ pub(crate) fn take_for_recovery(self) -> AttrVec {
         self.attrs
     }
 
+    // Prepend `self.attrs` to `attrs`.
     // FIXME: require passing an NT to prevent misuse of this method
-    pub(crate) fn prepend_to_nt_inner(self, attrs: &mut Vec<Attribute>) {
-        let mut self_attrs: Vec<_> = self.attrs.into();
+    pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
+        let mut self_attrs = self.attrs.clone();
         std::mem::swap(attrs, &mut self_attrs);
         attrs.extend(self_attrs);
     }
@@ -196,7 +197,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
         &mut self,
         attrs: AttrWrapper,
         force_collect: ForceCollect,
-        f: impl FnOnce(&mut Self, Vec<ast::Attribute>) -> PResult<'a, (R, TrailingToken)>,
+        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, TrailingToken)>,
     ) -> PResult<'a, R> {
         // We only bail out when nothing could possibly observe the collected tokens:
         // 1. We cannot be force collecting tokens (since force-collecting requires tokens
@@ -212,7 +213,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
             // or `#[cfg_attr]` attributes.
             && !self.capture_cfg
         {
-            return Ok(f(self, attrs.attrs.into())?.0);
+            return Ok(f(self, attrs.attrs)?.0);
         }
 
         let start_token = (self.token.clone(), self.token_spacing);
@@ -222,7 +223,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
         let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes);
         let replace_ranges_start = self.capture_state.replace_ranges.len();
 
-        let ret = f(self, attrs.attrs.into());
+        let ret = f(self, attrs.attrs);
 
         self.capture_state.capturing = prev_capturing;
 
@@ -352,7 +353,7 @@ pub fn collect_tokens_trailing_token<R: HasAttrs + HasTokens>(
         // on the captured token stream.
         if self.capture_cfg
             && matches!(self.capture_state.capturing, Capturing::Yes)
-            && has_cfg_or_cfg_attr(&final_attrs)
+            && has_cfg_or_cfg_attr(final_attrs)
         {
             let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens };
 
index cdf9f1d7cb98951ef079ba29e2c82744f5f57824..2c9f9a2c2c2006f8cb6f03d645e7e2cbe6ebcfc7 100644 (file)
@@ -2713,7 +2713,7 @@ pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>>
 
     fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
         let snapshot = self.create_snapshot_for_diagnostic();
-        let param = match self.parse_const_param(vec![]) {
+        let param = match self.parse_const_param(AttrVec::new()) {
             Ok(param) => param,
             Err(err) => {
                 err.cancel();
index 8645f179b1514f56303f50586e02faa378232417..17117cbc8fbe6682e71b47a2274ce0cf1588db14 100644 (file)
@@ -939,15 +939,15 @@ pub(super) fn parse_dot_or_call_expr_with(
         &mut self,
         e0: P<Expr>,
         lo: Span,
-        mut attrs: Vec<ast::Attribute>,
+        mut attrs: ast::AttrVec,
     ) -> PResult<'a, P<Expr>> {
         // Stitch the list of outer attributes onto the return value.
         // A little bit ugly, but the best way given the current code
         // structure
         self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| {
             expr.map(|mut expr| {
-                attrs.extend::<Vec<_>>(expr.attrs.into());
-                expr.attrs = attrs.into();
+                attrs.extend(expr.attrs);
+                expr.attrs = attrs;
                 expr
             })
         })
@@ -2164,7 +2164,7 @@ fn parse_fn_block_param(&mut self) -> PResult<'a, Param> {
 
             Ok((
                 Param {
-                    attrs: attrs.into(),
+                    attrs,
                     ty,
                     pat,
                     span: lo.to(this.prev_token.span),
@@ -2641,7 +2641,7 @@ fn check_let_expr(expr: &Expr) -> bool {
                     let span = body.span;
                     return Ok((
                         ast::Arm {
-                            attrs: attrs.into(),
+                            attrs,
                             pat,
                             guard,
                             body,
@@ -2711,7 +2711,7 @@ fn check_let_expr(expr: &Expr) -> bool {
 
             Ok((
                 ast::Arm {
-                    attrs: attrs.into(),
+                    attrs,
                     pat,
                     guard,
                     body: expr,
@@ -3010,7 +3010,7 @@ fn parse_expr_field(&mut self) -> PResult<'a, ExprField> {
                     span: lo.to(expr.span),
                     expr,
                     is_shorthand,
-                    attrs: attrs.into(),
+                    attrs,
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
@@ -3081,14 +3081,10 @@ fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
         await_expr
     }
 
-    pub(crate) fn mk_expr_with_attrs<A>(&self, span: Span, kind: ExprKind, attrs: A) -> P<Expr>
-    where
-        A: Into<AttrVec>,
-    {
-        P(Expr { kind, span, attrs: attrs.into(), id: DUMMY_NODE_ID, tokens: None })
+    pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
+        P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
     }
 
-    // njn: rename
     pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
         P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None })
     }
@@ -3110,7 +3106,7 @@ fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, rhs_span: Span) -> Span {
     fn collect_tokens_for_expr(
         &mut self,
         attrs: AttrWrapper,
-        f: impl FnOnce(&mut Self, Vec<ast::Attribute>) -> PResult<'a, P<Expr>>,
+        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>,
     ) -> PResult<'a, P<Expr>> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let res = f(this, attrs)?;
index 5e5f2fd7d9f8df7faed6c3e53719c9547029f8a2..4d0a8b05eb0271a573affbb80dbbd2312bf7cc59 100644 (file)
@@ -1,9 +1,7 @@
 use super::{ForceCollect, Parser, TrailingToken};
 
 use rustc_ast::token;
-use rustc_ast::{
-    self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
-};
+use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause};
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::kw;
 
@@ -26,7 +24,7 @@ fn parse_lt_param_bounds(&mut self) -> GenericBounds {
     }
 
     /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
-    fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+    fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
         let ident = self.parse_ident()?;
 
         // Parse optional colon and param bounds.
@@ -43,7 +41,7 @@ fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, Gen
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
+            attrs: preceding_attrs,
             bounds,
             kind: GenericParamKind::Type { default },
             is_placeholder: false,
@@ -53,7 +51,7 @@ fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, Gen
 
     pub(crate) fn parse_const_param(
         &mut self,
-        preceding_attrs: Vec<Attribute>,
+        preceding_attrs: AttrVec,
     ) -> PResult<'a, GenericParam> {
         let const_span = self.token.span;
 
@@ -68,7 +66,7 @@ pub(crate) fn parse_const_param(
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
+            attrs: preceding_attrs,
             bounds: Vec::new(),
             kind: GenericParamKind::Const { ty, kw_span: const_span, default },
             is_placeholder: false,
@@ -109,7 +107,7 @@ pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericPar
                         Some(ast::GenericParam {
                             ident: lifetime.ident,
                             id: lifetime.id,
-                            attrs: attrs.into(),
+                            attrs,
                             bounds,
                             kind: ast::GenericParamKind::Lifetime,
                             is_placeholder: false,
index cd3c982ce817c7579e89ee27d51a386a018b1004..b743162a7e4d0809a234454ccea601335bb9cc2a 100644 (file)
@@ -32,7 +32,7 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
+    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
         self.expect_keyword(kw::Mod)?;
         let id = self.parse_ident()?;
@@ -40,9 +40,9 @@ fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo
             ModKind::Unloaded
         } else {
             self.expect(&token::OpenDelim(Delimiter::Brace))?;
-            let (mut inner_attrs, items, inner_span) =
+            let (inner_attrs, items, inner_span) =
                 self.parse_mod(&token::CloseDelim(Delimiter::Brace))?;
-            attrs.append(&mut inner_attrs);
+            attrs.extend(inner_attrs);
             ModKind::Loaded(items, Inline::Yes, inner_span)
         };
         Ok((id, ItemKind::Mod(unsafety, mod_kind)))
@@ -52,7 +52,7 @@ fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo
     pub fn parse_mod(
         &mut self,
         term: &TokenKind,
-    ) -> PResult<'a, (Vec<Attribute>, Vec<P<Item>>, ModSpans)> {
+    ) -> PResult<'a, (AttrVec, Vec<P<Item>>, ModSpans)> {
         let lo = self.token.span;
         let attrs = self.parse_inner_attributes()?;
 
@@ -134,7 +134,7 @@ pub(super) fn parse_item_common(
 
     fn parse_item_common_(
         &mut self,
-        mut attrs: Vec<Attribute>,
+        mut attrs: AttrVec,
         mac_allowed: bool,
         attrs_allowed: bool,
         fn_parse_mode: FnParseMode,
@@ -198,7 +198,7 @@ fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) {
     /// Parses one of the items allowed by the flags.
     fn parse_item_kind(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         macros_allowed: bool,
         lo: Span,
         vis: &Visibility,
@@ -534,7 +534,7 @@ fn parse_polarity(&mut self) -> ast::ImplPolarity {
     /// ```
     fn parse_item_impl(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
@@ -661,12 +661,12 @@ fn parse_item_impl(
 
     fn parse_item_list<T>(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
     ) -> PResult<'a, Vec<T>> {
         let open_brace_span = self.token.span;
         self.expect(&token::OpenDelim(Delimiter::Brace))?;
-        attrs.append(&mut self.parse_inner_attributes()?);
+        attrs.extend(self.parse_inner_attributes()?);
 
         let mut items = Vec::new();
         while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
@@ -775,7 +775,7 @@ fn check_auto_or_unsafe_trait_item(&mut self) -> bool {
     }
 
     /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
@@ -1061,7 +1061,7 @@ fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, Ident> {
     /// ```
     fn parse_item_foreign_mod(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         mut unsafety: Unsafe,
     ) -> PResult<'a, ItemInfo> {
         let abi = self.parse_abi(); // ABI?
@@ -1179,7 +1179,7 @@ fn recover_const_mut(&mut self, const_span: Span) {
     fn recover_const_impl(
         &mut self,
         const_span: Span,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         let impl_span = self.token.span;
@@ -1337,7 +1337,7 @@ fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> {
                     ident,
                     vis,
                     id: DUMMY_NODE_ID,
-                    attrs: variant_attrs.into(),
+                    attrs: variant_attrs,
                     data: struct_def,
                     disr_expr,
                     span: vlo.to(this.prev_token.span),
@@ -1494,7 +1494,7 @@ fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<FieldDef>> {
                         ident: None,
                         id: DUMMY_NODE_ID,
                         ty,
-                        attrs: attrs.into(),
+                        attrs,
                         is_placeholder: false,
                     },
                     TrailingToken::MaybeComma,
@@ -1520,7 +1520,7 @@ fn parse_single_struct_field(
         adt_ty: &str,
         lo: Span,
         vis: Visibility,
-        attrs: Vec<Attribute>,
+        attrs: AttrVec,
     ) -> PResult<'a, FieldDef> {
         let mut seen_comma: bool = false;
         let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?;
@@ -1650,7 +1650,7 @@ fn parse_name_and_ty(
         adt_ty: &str,
         lo: Span,
         vis: Visibility,
-        attrs: Vec<Attribute>,
+        attrs: AttrVec,
     ) -> PResult<'a, FieldDef> {
         let name = self.parse_field_ident(adt_ty, lo)?;
         self.expect_field_ty_separator()?;
@@ -1684,7 +1684,7 @@ fn parse_name_and_ty(
             vis,
             id: DUMMY_NODE_ID,
             ty,
-            attrs: attrs.into(),
+            attrs,
             is_placeholder: false,
         })
     }
@@ -1703,7 +1703,7 @@ fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
                 if let Err(mut db) =
-                    self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis)
+                    self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
                 {
                     db.delay_as_bug();
                 }
@@ -1979,7 +1979,7 @@ impl<'a> Parser<'a> {
     /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
     fn parse_fn(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         fn_parse_mode: FnParseMode,
         sig_lo: Span,
         vis: &Visibility,
@@ -2002,7 +2002,7 @@ fn parse_fn(
     /// or e.g. a block when the function is a provided one.
     fn parse_fn_body(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         ident: &Ident,
         sig_hi: &mut Span,
         req_body: bool,
@@ -2017,7 +2017,7 @@ fn parse_fn_body(
             // Include the trailing semicolon in the span of the signature
             self.expect_semi()?;
             *sig_hi = self.prev_token.span;
-            (Vec::new(), None)
+            (AttrVec::new(), None)
         } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() {
             self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
         } else if self.token.kind == token::Eq {
@@ -2034,7 +2034,7 @@ fn parse_fn_body(
                     Applicability::MachineApplicable,
                 )
                 .emit();
-            (Vec::new(), Some(self.mk_block_err(span)))
+            (AttrVec::new(), Some(self.mk_block_err(span)))
         } else {
             let expected = if req_body {
                 &[token::OpenDelim(Delimiter::Brace)][..]
@@ -2051,7 +2051,7 @@ fn parse_fn_body(
                     return Err(err);
                 }
             }
-            (Vec::new(), None)
+            (AttrVec::new(), None)
         };
         attrs.extend(inner_attrs);
         Ok(body)
@@ -2280,7 +2280,7 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
             if let Some(mut param) = this.parse_self_param()? {
-                param.attrs = attrs.into();
+                param.attrs = attrs;
                 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
                 return Ok((res?, TrailingToken::None));
             }
@@ -2341,14 +2341,7 @@ fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResu
             let span = lo.to(this.prev_token.span);
 
             Ok((
-                Param {
-                    attrs: attrs.into(),
-                    id: ast::DUMMY_NODE_ID,
-                    is_placeholder: false,
-                    pat,
-                    span,
-                    ty,
-                },
+                Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
                 TrailingToken::None,
             ))
         })
index 42bf889844710a3ed9d679f5cb369b7203124606..8b3200d45fccd76b99b17ebebf0150cdf47eee89 100644 (file)
@@ -4,8 +4,8 @@
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::{
-    self as ast, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
-    PatKind, Path, QSelf, RangeEnd, RangeSyntax,
+    self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind,
+    Path, QSelf, RangeEnd, RangeSyntax,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
@@ -1093,7 +1093,7 @@ fn recover_one_fewer_dotdot(&self) {
             .emit();
     }
 
-    fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, PatField> {
+    fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let hi;
         let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
@@ -1134,7 +1134,7 @@ fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Pa
             ident: fieldname,
             pat: subpat,
             is_shorthand,
-            attrs: attrs.into(),
+            attrs,
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
             is_placeholder: false,
index 12b1a37e0224719aaa88a01e1499c1b742058d0e..3d957406b19d88a98d844962967fb53fb6ea064b 100644 (file)
@@ -130,7 +130,7 @@ fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a,
             let path = this.parse_path(PathStyle::Expr)?;
 
             if this.eat(&token::Not) {
-                let stmt_mac = this.parse_stmt_mac(lo, attrs.into(), path)?;
+                let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
                 if this.token == token::Semi {
                     return Ok((stmt_mac, TrailingToken::Semi));
                 } else {
@@ -190,7 +190,7 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
-            let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+            let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
             StmtKind::Expr(e)
         };
@@ -229,7 +229,7 @@ fn parse_local_mk(
     ) -> PResult<'a, Stmt> {
         self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
             this.expect_keyword(kw::Let)?;
-            let local = this.parse_local(attrs.into())?;
+            let local = this.parse_local(attrs)?;
             let trailing = if capture_semi && this.token.kind == token::Semi {
                 TrailingToken::Semi
             } else {
@@ -241,7 +241,7 @@ fn parse_local_mk(
 
     fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
-            let local = this.parse_local(attrs.into())?;
+            let local = this.parse_local(attrs)?;
             // FIXME - maybe capture semicolon in recovery?
             Ok((
                 this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)),
@@ -509,9 +509,7 @@ fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
     }
 
     /// Parses a block. Inner attributes are allowed.
-    pub(super) fn parse_inner_attrs_and_block(
-        &mut self,
-    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
+    pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (AttrVec, P<Block>)> {
         self.parse_block_common(self.token.span, BlockCheckMode::Default)
     }
 
@@ -520,8 +518,8 @@ pub(super) fn parse_block_common(
         &mut self,
         lo: Span,
         blk_mode: BlockCheckMode,
-    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
-        maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
+    ) -> PResult<'a, (AttrVec, P<Block>)> {
+        maybe_whole!(self, NtBlock, |x| (AttrVec::new(), x));
 
         self.maybe_recover_unexpected_block_label();
         if !self.eat(&token::OpenDelim(Delimiter::Brace)) {
index 76b710095d798da61d36feb4a8e1e1e8d47978e9..4a2cf74905bf593617d8a3b40b05b449ae2db664 100644 (file)
@@ -640,7 +640,13 @@ fn parse_generic_bounds_common(
         let mut bounds = Vec::new();
         let mut negative_bounds = Vec::new();
 
-        while self.can_begin_bound() || self.token.is_keyword(kw::Dyn) {
+        while self.can_begin_bound()
+            // Continue even if we find a keyword.
+            // This is necessary for error recover on, for example, `impl fn()`.
+            //
+            // The only keyword that can go after generic bounds is `where`, so stop if it's it.
+            || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
+        {
             if self.token.is_keyword(kw::Dyn) {
                 // Account for `&dyn Trait + dyn Other`.
                 self.struct_span_err(self.token.span, "invalid `dyn` keyword")
@@ -803,6 +809,20 @@ fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
             self.expect_keyword(kw::Const)?;
             let span = tilde.to(self.prev_token.span);
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            Some(span)
+        } else if self.eat_keyword(kw::Const) {
+            let span = self.prev_token.span;
+            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+
+            self.struct_span_err(span, "const bounds must start with `~`")
+                .span_suggestion(
+                    span.shrink_to_lo(),
+                    "add `~`",
+                    "~",
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+
             Some(span)
         } else {
             None
index 36585b8d77e0ad2c58fe3359270d7b5f723a1059..9bd5550038fc605a24cd9aa510b668f46f4cf6ea 100644 (file)
@@ -273,7 +273,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
         unsafe {
             let ptr: *mut T = vec.as_mut_ptr();
             for i in 0..len {
-                std::ptr::write(ptr.offset(i as isize), Decodable::decode(d));
+                std::ptr::write(ptr.add(i), Decodable::decode(d));
             }
             vec.set_len(len);
         }
index b9b2356130a594be5f51b0b77412c7f75f6774a9..17866dc6bddcbf2cbb89adf7d1a4df188efa4abe 100644 (file)
@@ -360,6 +360,17 @@ pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
         self.create_warning(warning).emit()
     }
 
+    pub fn create_fatal<'a>(
+        &'a self,
+        fatal: impl SessionDiagnostic<'a, !>,
+    ) -> DiagnosticBuilder<'a, !> {
+        fatal.into_diagnostic(self)
+    }
+
+    pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+        self.create_fatal(fatal).emit()
+    }
+
     #[rustc_lint_diagnostics]
     pub fn struct_err(
         &self,
@@ -373,6 +384,11 @@ pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilde
         self.span_diagnostic.struct_warn(msg)
     }
 
+    #[rustc_lint_diagnostics]
+    pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
+        self.span_diagnostic.struct_fatal(msg)
+    }
+
     #[rustc_lint_diagnostics]
     pub fn struct_diagnostic<G: EmissionGuarantee>(
         &self,
index 80de451276c2c71e47d601b53feef202923808f4..4972ae2014d506e3ce200d4baa5a7f4f20a917bf 100644 (file)
@@ -482,6 +482,15 @@ pub fn create_warning<'a>(
     pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
         self.parse_sess.emit_warning(warning)
     }
+    pub fn create_fatal<'a>(
+        &'a self,
+        fatal: impl SessionDiagnostic<'a, !>,
+    ) -> DiagnosticBuilder<'a, !> {
+        self.parse_sess.create_fatal(fatal)
+    }
+    pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+        self.parse_sess.emit_fatal(fatal)
+    }
     #[inline]
     pub fn err_count(&self) -> usize {
         self.diagnostic().err_count()
index d14e28e85be1a5407dc22b6788f5986c445d1a07..860af7fe93a077959f1377c70d642af5e8709a9e 100644 (file)
@@ -664,6 +664,16 @@ pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
         Some(self)
     }
 
+    /// Like `find_ancestor_inside`, but specifically for when spans might not
+    /// overlaps. Take care when using this, and prefer `find_ancestor_inside`
+    /// when you know that the spans are nested (modulo macro expansion).
+    pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> {
+        while !Span::eq_ctxt(self, other) {
+            self = self.parent_callsite()?;
+        }
+        Some(self)
+    }
+
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
         self.ctxt().edition()
index 6c177f6388704a943548eb824a97e5df6ab2b46d..136b94321459ee062840443e9534b30dc101f835 100644 (file)
@@ -3,7 +3,8 @@
 use super::TraitEngine;
 use super::{ChalkFulfillmentContext, FulfillmentContext};
 use crate::infer::InferCtxtExt;
-use rustc_hir::def_id::DefId;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::{
     FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
@@ -12,6 +13,7 @@
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
 
 pub trait TraitEngineExt<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
@@ -109,4 +111,23 @@ pub fn equate_types(
     pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
+
+    pub fn assumed_wf_types(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        span: Span,
+        def_id: LocalDefId,
+    ) -> FxHashSet<Ty<'tcx>> {
+        let tcx = self.infcx.tcx;
+        let assumed_wf_types = tcx.assumed_wf_types(def_id);
+        let mut implied_bounds = FxHashSet::default();
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+        let cause = ObligationCause::misc(span, hir_id);
+        for ty in assumed_wf_types {
+            implied_bounds.insert(ty);
+            let normalized = self.normalize(cause.clone(), param_env, ty);
+            implied_bounds.insert(normalized);
+        }
+        implied_bounds
+    }
 }
index 1a39a1680384dced9379ddbeb194c840cfe09330..70fac83325a9c693d406138744c84e869e7f342c 100644 (file)
@@ -860,8 +860,7 @@ fn report_selection_error(
                             }
                         }
 
-                        err.emit();
-                        return;
+                        err
                     }
 
                     ty::PredicateKind::WellFormed(ty) => {
@@ -1564,6 +1563,8 @@ fn report_projection_error(
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
+                        | ObligationCauseCode::ExprItemObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
@@ -2091,13 +2092,11 @@ fn maybe_report_ambiguity(
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id) = *obligation.cause.code() {
+                if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    &ObligationCauseCode::BindingObligation(def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code())
+                } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
+                    && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
+                        = *obligation.cause.code()
                 {
                     let generics = self.tcx.generics_of(def_id);
                     if generics.params.iter().any(|p| p.name != kw::SelfUpper)
@@ -2520,15 +2519,10 @@ fn suggest_unsized_bound_if_applicable(
         err: &mut Diagnostic,
         obligation: &PredicateObligation<'tcx>,
     ) {
-        let (
-            ty::PredicateKind::Trait(pred),
-            &ObligationCauseCode::BindingObligation(item_def_id, span),
-        ) = (
-            obligation.predicate.kind().skip_binder(),
-            obligation.cause.code().peel_derives(),
-        )  else {
-            return;
-        };
+        let ty::PredicateKind::Trait(pred) = obligation.predicate.kind().skip_binder() else { return; };
+        let (ObligationCauseCode::BindingObligation(item_def_id, span)
+        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..))
+            = *obligation.cause.code().peel_derives() else { return; };
         debug!(?pred, ?item_def_id, ?span);
 
         let (Some(node), true) = (
index e6907637c57b628fbd6dca7622411f3b2b97b968..6b03555bc6985b689c103c2247a70f4effc43976 100644 (file)
@@ -143,7 +143,9 @@ fn on_unimplemented_note(
         }
 
         if let ObligationCauseCode::ItemObligation(item)
-        | ObligationCauseCode::BindingObligation(item, _) = *obligation.cause.code()
+        | ObligationCauseCode::BindingObligation(item, _)
+        | ObligationCauseCode::ExprItemObligation(item, ..)
+        | ObligationCauseCode::ExprBindingObligation(item, ..) = *obligation.cause.code()
         {
             // FIXME: maybe also have some way of handling methods
             // from other traits? That would require name resolution,
index 0d279069694a90ecf197a7ee03342a4c98e62415..a93f9ec0397d2649400b408a0e0c26cbec9b691a 100644 (file)
@@ -671,11 +671,16 @@ fn suggest_dereferences(
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else {
-            return false;
-        };
-        let param_env = obligation.param_env;
-        let body_id = obligation.cause.body_id;
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+            else { return false; };
+        let Some(typeck_results) = self.in_progress_typeck_results
+            else { return false; };
+        let typeck_results = typeck_results.borrow();
+        let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
+            else { return false; };
+        let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
+            else { return false; };
+
         let span = obligation.cause.span;
         let mut real_trait_pred = trait_pred;
         let mut code = obligation.cause.code();
@@ -687,9 +692,19 @@ fn suggest_dereferences(
 
             // Skipping binder here, remapping below
             let real_ty = real_trait_pred.self_ty().skip_binder();
+            if self.can_eq(obligation.param_env, real_ty, arg_ty).is_err() {
+                continue;
+            }
 
             if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
-                let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span);
+                let mut autoderef = Autoderef::new(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.body_id,
+                    span,
+                    base_ty,
+                    span,
+                );
                 if let Some(steps) = autoderef.find_map(|(ty, steps)| {
                     // Re-add the `&`
                     let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
@@ -697,8 +712,10 @@ fn suggest_dereferences(
                     // Remapping bound vars here
                     let real_trait_pred_and_ty =
                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
-                    let obligation = self
-                        .mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred_and_ty);
+                    let obligation = self.mk_trait_obligation_with_new_self_ty(
+                        obligation.param_env,
+                        real_trait_pred_and_ty,
+                    );
                     Some(steps).filter(|_| self.predicate_may_hold(&obligation))
                 }) {
                     if steps > 0 {
@@ -727,7 +744,7 @@ fn suggest_dereferences(
                     let real_trait_pred_and_base_ty =
                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, base_ty));
                     let obligation = self.mk_trait_obligation_with_new_self_ty(
-                        param_env,
+                        obligation.param_env,
                         real_trait_pred_and_base_ty,
                     );
                     if self.predicate_may_hold(&obligation) {
@@ -855,6 +872,7 @@ fn suggest_fn_call(
             _ => return false,
         };
         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
+            && obligation.cause.span.can_be_used_for_suggestions()
         {
             // When the obligation error has been ensured to have been caused by
             // an argument, the `obligation.cause.span` points at the expression
@@ -885,7 +903,9 @@ fn suggest_add_reference_to_arg(
             obligation.cause.code()
         {
             &parent_code
-        } else if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code() {
+        } else if let ObligationCauseCode::ItemObligation(_)
+        | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
+        {
             obligation.cause.code()
         } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
             span.ctxt().outer_expn_data().kind
@@ -911,35 +931,36 @@ fn suggest_add_reference_to_arg(
         let param_env = obligation.param_env;
 
         // Try to apply the original trait binding obligation by borrowing.
-        let mut try_borrowing =
-            |old_pred: ty::PolyTraitPredicate<'tcx>, blacklist: &[DefId]| -> bool {
-                if blacklist.contains(&old_pred.def_id()) {
-                    return false;
-                }
-                // We map bounds to `&T` and `&mut T`
-                let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
-                    (
-                        trait_pred,
-                        self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
-                    )
-                });
-                let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
-                    (
-                        trait_pred,
-                        self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
-                    )
-                });
+        let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
+                                 blacklist: &[DefId]|
+         -> bool {
+            if blacklist.contains(&old_pred.def_id()) {
+                return false;
+            }
+            // We map bounds to `&T` and `&mut T`
+            let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
+                (
+                    trait_pred,
+                    self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
+                )
+            });
+            let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
+                (
+                    trait_pred,
+                    self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
+                )
+            });
 
-                let mk_result = |trait_pred_and_new_ty| {
-                    let obligation =
-                        self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
-                    self.predicate_must_hold_modulo_regions(&obligation)
-                };
-                let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
-                let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
+            let mk_result = |trait_pred_and_new_ty| {
+                let obligation =
+                    self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
+                self.predicate_must_hold_modulo_regions(&obligation)
+            };
+            let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
+            let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
 
-                let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
-                if let ObligationCauseCode::ItemObligation(_) = obligation.cause.code()
+            let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
+                if let ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
                     && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
                 {
                     (
@@ -950,79 +971,81 @@ fn suggest_add_reference_to_arg(
                     (false, false)
                 };
 
-                if imm_ref_self_ty_satisfies_pred
-                    || mut_ref_self_ty_satisfies_pred
-                    || ref_inner_ty_satisfies_pred
-                {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        // We have a very specific type of error, where just borrowing this argument
-                        // might solve the problem. In cases like this, the important part is the
-                        // original type obligation, not the last one that failed, which is arbitrary.
-                        // Because of this, we modify the error to refer to the original obligation and
-                        // return early in the caller.
-
-                        let msg = format!("the trait bound `{}` is not satisfied", old_pred);
-                        if has_custom_message {
-                            err.note(&msg);
-                        } else {
-                            err.message =
-                                vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
-                        }
-                        if snippet.starts_with('&') {
-                            // This is already a literal borrow and the obligation is failing
-                            // somewhere else in the obligation chain. Do not suggest non-sense.
-                            return false;
-                        }
-                        err.span_label(
-                            span,
+            if imm_ref_self_ty_satisfies_pred
+                || mut_ref_self_ty_satisfies_pred
+                || ref_inner_ty_satisfies_pred
+            {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We don't want a borrowing suggestion on the fields in structs,
+                    // ```
+                    // struct Foo {
+                    //  the_foos: Vec<Foo>
+                    // }
+                    // ```
+                    if !matches!(
+                        span.ctxt().outer_expn_data().kind,
+                        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
+                    ) {
+                        return false;
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+
+                    let msg = format!("the trait bound `{}` is not satisfied", old_pred);
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message =
+                            vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
+                    }
+                    err.span_label(
+                        span,
+                        format!(
+                            "the trait `{}` is not implemented for `{}`",
+                            old_pred.print_modifiers_and_trait_path(),
+                            old_pred.self_ty().skip_binder(),
+                        ),
+                    );
+
+                    if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
+                        err.span_suggestions(
+                            span.shrink_to_lo(),
+                            "consider borrowing here",
+                            ["&".to_string(), "&mut ".to_string()].into_iter(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
+                        err.span_suggestion_verbose(
+                            span.shrink_to_lo(),
                             &format!(
-                                "expected an implementor of trait `{}`",
-                                old_pred.print_modifiers_and_trait_path(),
+                                "consider{} borrowing here",
+                                if is_mut { " mutably" } else { "" }
                             ),
+                            format!("&{}", if is_mut { "mut " } else { "" }),
+                            Applicability::MaybeIncorrect,
                         );
-
-                        // This if is to prevent a special edge-case
-                        if matches!(
-                            span.ctxt().outer_expn_data().kind,
-                            ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
-                        ) {
-                            // We don't want a borrowing suggestion on the fields in structs,
-                            // ```
-                            // struct Foo {
-                            //  the_foos: Vec<Foo>
-                            // }
-                            // ```
-
-                            if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
-                                err.span_suggestions(
-                                    span.shrink_to_lo(),
-                                    "consider borrowing here",
-                                    ["&".to_string(), "&mut ".to_string()].into_iter(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
-                                err.span_suggestion_verbose(
-                                    span.shrink_to_lo(),
-                                    &format!(
-                                        "consider{} borrowing here",
-                                        if is_mut { " mutably" } else { "" }
-                                    ),
-                                    format!("&{}", if is_mut { "mut " } else { "" }),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                        }
-                        return true;
                     }
+                    return true;
                 }
-                return false;
-            };
+            }
+            return false;
+        };
 
         if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
             try_borrowing(cause.derived.parent_trait_pred, &[])
         } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(..) = code
+        | ObligationCauseCode::ItemObligation(_)
+        | ObligationCauseCode::ExprItemObligation(..)
+        | ObligationCauseCode::ExprBindingObligation(..) = code
         {
             try_borrowing(poly_trait_pred, &never_suggest_borrow)
         } else {
@@ -2244,11 +2267,13 @@ fn note_obligation_cause_code<T>(
                     region, object_ty,
                 ));
             }
-            ObligationCauseCode::ItemObligation(_item_def_id) => {
+            ObligationCauseCode::ItemObligation(_)
+            | ObligationCauseCode::ExprItemObligation(..) => {
                 // We hold the `DefId` of the item introducing the obligation, but displaying it
                 // doesn't add user usable information. It always point at an associated item.
             }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+            ObligationCauseCode::BindingObligation(item_def_id, span)
+            | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
                 let mut multispan = MultiSpan::from(span);
                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
index b6d6df1eec6a12a56d3bd570f4a61eb04a25793d..85ff6e23711ca4624e8490ab81ff2edb61d2854c 100644 (file)
@@ -117,11 +117,21 @@ pub enum TraitQueryMode {
 
 /// Creates predicate obligations from the generic bounds.
 pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
+    cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     generic_bounds: ty::InstantiatedPredicates<'tcx>,
 ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
+    let generic_bounds = generic_bounds;
+    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
+
+    std::iter::zip(generic_bounds.predicates, generic_bounds.spans).enumerate().map(
+        move |(idx, (predicate, span))| Obligation {
+            cause: cause(idx, span),
+            recursion_depth: 0,
+            param_env: param_env,
+            predicate,
+        },
+    )
 }
 
 /// Determines whether the type `ty` is known to meet `bound` and
index 715b97492683b59d24ccf25419a824f349dce366..aeaccffd5f5f77a0132d4e957a56545143060e08 100644 (file)
@@ -554,6 +554,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .flatten()
                     .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self)))
                 };
+                // For cases like #95134 we would like to catch overflows early
+                // otherwise they slip away away and cause ICE.
+                let recursion_limit = self.tcx().recursion_limit();
+                if !recursion_limit.value_within_limit(self.depth) {
+                    let obligation = Obligation::with_depth(
+                        self.cause.clone(),
+                        recursion_limit.0,
+                        self.param_env,
+                        ty,
+                    );
+                    self.selcx.infcx().report_overflow_error(&obligation, true);
+                }
                 debug!(
                     ?self.depth,
                     ?ty,
index d25006016629c907bf0d0f60d489900610ac3dd8..0f5dff01c6625387b24c2bc5e521be2b1095b0f6 100644 (file)
@@ -11,8 +11,6 @@
 use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 pub use rustc_infer::traits::{self, util::*};
 
-use std::iter;
-
 ///////////////////////////////////////////////////////////////////////////
 // `TraitAliasExpander` iterator
 ///////////////////////////////////////////////////////////////////////////
@@ -210,7 +208,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     let Normalized { value: predicates, obligations: normalization_obligations2 } =
         super::normalize(selcx, param_env, ObligationCause::dummy(), predicates);
     let impl_obligations =
-        predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
+        super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates);
 
     let impl_obligations = impl_obligations
         .chain(normalization_obligations1.into_iter())
@@ -219,27 +217,6 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     (subject, impl_obligations)
 }
 
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    recursion_depth: usize,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: ty::InstantiatedPredicates<'tcx>,
-) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
-    iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| {
-        let cause = match *cause.code() {
-            traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new(
-                cause.span,
-                cause.body_id,
-                traits::BindingObligation(def_id, span),
-            ),
-            _ => cause.clone(),
-        };
-        Obligation { cause, recursion_depth, param_env, predicate }
-    })
-}
-
 pub fn predicate_for_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
     cause: ObligationCause<'tcx>,
index 7a5e67ff74b32daa78845d419948750b035633eb..4bd179d23913143dd663bd7c7899677264f5c3ba 100644 (file)
@@ -711,7 +711,7 @@ fn nominal_obligations_inner(
         iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
             .map(|((mut pred, span), origin_def_id)| {
                 let code = if span.is_dummy() {
-                    traits::MiscObligation
+                    traits::ItemObligation(origin_def_id)
                 } else {
                     traits::BindingObligation(origin_def_id, span)
                 };
index cfc7c752a6bd60bf6c4d5444faa8568c41885dee..32e6cb9c64f7f3f804c0fd9ffbcb5c0101284098 100644 (file)
@@ -7,6 +7,8 @@
     result_into_ok_or_err
 )]
 #![allow(dead_code, unused_variables)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
new file mode 100644 (file)
index 0000000..a77ea44
--- /dev/null
@@ -0,0 +1,60 @@
+use crate::rustc_middle::ty::DefIdTree;
+use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { assumed_wf_types, ..*providers };
+}
+
+fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+    match tcx.def_kind(def_id) {
+        DefKind::Fn => {
+            let sig = tcx.fn_sig(def_id);
+            let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
+            liberated_sig.inputs_and_output
+        }
+        DefKind::AssocFn => {
+            let sig = tcx.fn_sig(def_id);
+            let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
+            let mut assumed_wf_types: Vec<_> =
+                tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
+            assumed_wf_types.extend(liberated_sig.inputs_and_output);
+            tcx.intern_type_list(&assumed_wf_types)
+        }
+        DefKind::Impl => match tcx.impl_trait_ref(def_id) {
+            Some(trait_ref) => {
+                let types: Vec<_> = trait_ref.substs.types().collect();
+                tcx.intern_type_list(&types)
+            }
+            // Only the impl self type
+            None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
+        },
+        DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::TyParam
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static(_)
+        | DefKind::Ctor(_, _)
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Closure
+        | DefKind::Generator => ty::List::empty(),
+    }
+}
index 09f5c2a11aaa808d835133a4ffdd6df86b4360c7..55d8269399403d1c1ea094978ca838ce7e962fc5 100644 (file)
@@ -21,6 +21,7 @@
 mod assoc;
 mod common_traits;
 mod consts;
+mod implied_bounds;
 pub mod instance;
 mod needs_drop;
 pub mod representability;
@@ -30,6 +31,7 @@ pub fn provide(providers: &mut Providers) {
     assoc::provide(providers);
     common_traits::provide(providers);
     consts::provide(providers);
+    implied_bounds::provide(providers);
     needs_drop::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
index ec8d22e81d1c01dd702c8a2e513df63ba221ed99..dfef924f6993a568478d3ce864ac609a8da0f3b9 100644 (file)
@@ -1,7 +1,6 @@
 use super::potentially_plural_count;
-use crate::check::regionck::OutlivesEnvironmentExt;
-use crate::check::wfcheck;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -71,6 +70,72 @@ pub(crate) fn compare_impl_method<'tcx>(
     }
 }
 
+/// This function is best explained by example. Consider a trait:
+///
+///     trait Trait<'t, T> {
+///         // `trait_m`
+///         fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
+///     }
+///
+/// And an impl:
+///
+///     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+///          // `impl_m`
+///          fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
+///     }
+///
+/// We wish to decide if those two method types are compatible.
+/// For this we have to show that, assuming the bounds of the impl hold, the
+/// bounds of `trait_m` imply the bounds of `impl_m`.
+///
+/// We start out with `trait_to_impl_substs`, that maps the trait
+/// type parameters to impl type parameters. This is taken from the
+/// impl trait reference:
+///
+///     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+///
+/// We create a mapping `dummy_substs` that maps from the impl type
+/// parameters to fresh types and regions. For type parameters,
+/// this is the identity transform, but we could as well use any
+/// placeholder types. For regions, we convert from bound to free
+/// regions (Note: but only early-bound regions, i.e., those
+/// declared on the impl or used in type parameter bounds).
+///
+///     impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+///
+/// Now we can apply `placeholder_substs` to the type of the impl method
+/// to yield a new function type in terms of our fresh, placeholder
+/// types:
+///
+///     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+///
+/// We now want to extract and substitute the type of the *trait*
+/// method and compare it. To do so, we must create a compound
+/// substitution by combining `trait_to_impl_substs` and
+/// `impl_to_placeholder_substs`, and also adding a mapping for the method
+/// type parameters. We extend the mapping to also include
+/// the method parameters.
+///
+///     trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+///
+/// Applying this to the trait method type yields:
+///
+///     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+///
+/// This type is also the same but the name of the bound region (`'a`
+/// vs `'b`).  However, the normal subtyping rules on fn types handle
+/// this kind of equivalency just fine.
+///
+/// We now use these substitutions to ensure that all declared bounds are
+/// satisfied by the implementation's method.
+///
+/// We do this by creating a parameter environment which contains a
+/// substitution corresponding to `impl_to_placeholder_substs`. We then build
+/// `trait_to_placeholder_substs` and use it to convert the predicates contained
+/// in the `trait_m` generics to the placeholder form.
+///
+/// Finally we register each of these predicates as an obligation and check that
+/// they hold.
 fn compare_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
@@ -97,69 +162,6 @@ fn compare_predicate_entailment<'tcx>(
         },
     );
 
-    // This code is best explained by example. Consider a trait:
-    //
-    //     trait Trait<'t, T> {
-    //         fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
-    //     }
-    //
-    // And an impl:
-    //
-    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
-    //          fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
-    //     }
-    //
-    // We wish to decide if those two method types are compatible.
-    //
-    // We start out with trait_to_impl_substs, that maps the trait
-    // type parameters to impl type parameters. This is taken from the
-    // impl trait reference:
-    //
-    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
-    //
-    // We create a mapping `dummy_substs` that maps from the impl type
-    // parameters to fresh types and regions. For type parameters,
-    // this is the identity transform, but we could as well use any
-    // placeholder types. For regions, we convert from bound to free
-    // regions (Note: but only early-bound regions, i.e., those
-    // declared on the impl or used in type parameter bounds).
-    //
-    //     impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
-    //
-    // Now we can apply placeholder_substs to the type of the impl method
-    // to yield a new function type in terms of our fresh, placeholder
-    // types:
-    //
-    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
-    //
-    // We now want to extract and substitute the type of the *trait*
-    // method and compare it. To do so, we must create a compound
-    // substitution by combining trait_to_impl_substs and
-    // impl_to_placeholder_substs, and also adding a mapping for the method
-    // type parameters. We extend the mapping to also include
-    // the method parameters.
-    //
-    //     trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
-    //
-    // Applying this to the trait method type yields:
-    //
-    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
-    //
-    // This type is also the same but the name of the bound region ('a
-    // vs 'b).  However, the normal subtyping rules on fn types handle
-    // this kind of equivalency just fine.
-    //
-    // We now use these substitutions to ensure that all declared bounds are
-    // satisfied by the implementation's method.
-    //
-    // We do this by creating a parameter environment which contains a
-    // substitution corresponding to impl_to_placeholder_substs. We then build
-    // trait_to_placeholder_substs and use it to convert the predicates contained
-    // in the trait_m.generics to the placeholder form.
-    //
-    // Finally we register each of these predicates as an obligation in
-    // a fresh FulfillmentCtxt, and invoke select_all_or_error.
-
     // Create mapping from impl to placeholder.
     let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
 
@@ -399,8 +401,11 @@ fn compare_predicate_entailment<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(infcx),
+            infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+        );
         infcx.check_region_obligations_and_report_errors(
             impl_m.def_id.expect_local(),
             &outlives_environment,
@@ -1445,14 +1450,17 @@ pub fn check_type_bounds<'tcx>(
     };
     debug!(?normalize_param_env);
 
+    let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
     let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
     let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
         let ocx = ObligationCtxt::new(&infcx);
 
+        let assumed_wf_types =
+            ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
+
         let mut selcx = traits::SelectionContext::new(&infcx);
-        let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
         let normalize_cause = ObligationCause::new(
             impl_ty_span,
             impl_ty_hir_id,
@@ -1463,7 +1471,7 @@ pub fn check_type_bounds<'tcx>(
         );
         let mk_cause = |span: Span| {
             let code = if span.is_dummy() {
-                traits::MiscObligation
+                traits::ItemObligation(trait_ty.def_id)
             } else {
                 traits::BindingObligation(trait_ty.def_id, span)
             };
@@ -1508,17 +1516,10 @@ pub fn check_type_bounds<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let implied_bounds = match impl_ty.container {
-            ty::TraitContainer => FxHashSet::default(),
-            ty::ImplContainer => wfcheck::impl_implied_bounds(
-                tcx,
-                param_env,
-                container_id.expect_local(),
-                impl_ty_span,
-            ),
-        };
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
+        let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_hir_id, assumed_wf_types);
+        let outlives_environment =
+            OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
+
         infcx.check_region_obligations_and_report_errors(
             impl_ty.def_id.expect_local(),
             &outlives_environment,
index 1d9d04ceec0d76fc44caa13553895848bcba437f..20d25d508d224e9749e631f3e8a4cfb5905cbe1e 100644 (file)
@@ -607,9 +607,10 @@ pub(in super::super) fn resolve_generator_interiors(&self, def_id: DefId) {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn select_all_obligations_or_error(&self) {
-        let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self);
+        let mut errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self);
 
         if !errors.is_empty() {
+            self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
             self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
@@ -623,6 +624,7 @@ pub(in super::super) fn select_obligations_where_possible(
         let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
         if !result.is_empty() {
             mutate_fulfillment_errors(&mut result);
+            self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
             self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
         }
     }
@@ -820,23 +822,25 @@ pub(in super::super) fn resolve_lang_item_path(
         let ty = item_ty.subst(self.tcx, substs);
 
         self.write_resolution(hir_id, Ok((def_kind, def_id)));
-        self.add_required_obligations_with_code(
-            span,
-            def_id,
-            &substs,
-            match lang_item {
-                hir::LangItem::IntoFutureIntoFuture => {
-                    ObligationCauseCode::AwaitableExpr(expr_hir_id)
-                }
-                hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
-                    ObligationCauseCode::ForLoopIterator
-                }
-                hir::LangItem::TryTraitFromOutput
-                | hir::LangItem::TryTraitFromResidual
-                | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark,
-                _ => traits::ItemObligation(def_id),
-            },
-        );
+
+        let code = match lang_item {
+            hir::LangItem::IntoFutureIntoFuture => {
+                Some(ObligationCauseCode::AwaitableExpr(expr_hir_id))
+            }
+            hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
+                Some(ObligationCauseCode::ForLoopIterator)
+            }
+            hir::LangItem::TryTraitFromOutput
+            | hir::LangItem::TryTraitFromResidual
+            | hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark),
+            _ => None,
+        };
+        if let Some(code) = code {
+            self.add_required_obligations_with_code(span, def_id, substs, move |_, _| code.clone());
+        } else {
+            self.add_required_obligations_for_hir(span, def_id, substs, hir_id);
+        }
+
         (Res::Def(def_kind, def_id), ty)
     }
 
@@ -1348,7 +1352,7 @@ fn inferred_kind(
         // First, store the "user substs" for later.
         self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
 
-        self.add_required_obligations(span, def_id, &substs);
+        self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
 
         // Substitute the values for the type parameters into the type of
         // the referenced item.
@@ -1385,32 +1389,36 @@ fn inferred_kind(
     }
 
     /// Add all the obligations that are required, substituting and normalized appropriately.
-    pub(crate) fn add_required_obligations(
+    pub(crate) fn add_required_obligations_for_hir(
         &self,
         span: Span,
         def_id: DefId,
-        substs: &SubstsRef<'tcx>,
+        substs: SubstsRef<'tcx>,
+        hir_id: hir::HirId,
     ) {
-        self.add_required_obligations_with_code(
-            span,
-            def_id,
-            substs,
-            traits::ItemObligation(def_id),
-        )
+        self.add_required_obligations_with_code(span, def_id, substs, |idx, span| {
+            if span.is_dummy() {
+                ObligationCauseCode::ExprItemObligation(def_id, hir_id, idx)
+            } else {
+                ObligationCauseCode::ExprBindingObligation(def_id, span, hir_id, idx)
+            }
+        })
     }
 
-    #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))]
+    #[tracing::instrument(level = "debug", skip(self, code, span, def_id, substs))]
     fn add_required_obligations_with_code(
         &self,
         span: Span,
         def_id: DefId,
-        substs: &SubstsRef<'tcx>,
-        code: ObligationCauseCode<'tcx>,
+        substs: SubstsRef<'tcx>,
+        code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>,
     ) {
         let (bounds, _) = self.instantiate_bounds(span, def_id, &substs);
 
         for obligation in traits::predicates_for_generics(
-            traits::ObligationCause::new(span, self.body_id, code),
+            |idx, predicate_span| {
+                traits::ObligationCause::new(span, self.body_id, code(idx, predicate_span))
+            },
             self.param_env,
             bounds,
         ) {
index aab60de80ef14e65592dea4556e3495a5e11367a..3642b2ab03bfafb732432aeee67adac598f268c8 100644 (file)
@@ -15,6 +15,7 @@
 use crate::structured_errors::StructuredDiagnostic;
 
 use rustc_ast as ast;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_infer::infer::TypeTrace;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
+use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::{self, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
+use std::ops::ControlFlow;
 use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -247,17 +249,7 @@ pub(in super::super) fn check_argument_types(
             // Cause selection errors caused by resolving a single argument to point at the
             // argument and not the call. This lets us customize the span pointed to in the
             // fulfillment error to be more accurate.
-            let coerced_ty =
-                self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
-                    self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
-                    self.point_at_arg_instead_of_call_if_possible(
-                        errors,
-                        call_expr,
-                        call_span,
-                        provided_args,
-                        &expected_input_tys,
-                    );
-                });
+            let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
 
             let coerce_error = self
                 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
@@ -312,16 +304,7 @@ pub(in super::super) fn check_argument_types(
             // an "opportunistic" trait resolution of any trait bounds on
             // the call. This helps coercions.
             if check_closures {
-                self.select_obligations_where_possible(false, |errors| {
-                    self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
-                    self.point_at_arg_instead_of_call_if_possible(
-                        errors,
-                        call_expr,
-                        call_span,
-                        &provided_args,
-                        &expected_input_tys,
-                    );
-                })
+                self.select_obligations_where_possible(false, |_| {})
             }
 
             // Check each argument, to satisfy the input it was provided for
@@ -674,7 +657,13 @@ fn has_error_or_infer<'tcx>(tys: impl IntoIterator<Item = Ty<'tcx>>) -> bool {
                             Applicability::MachineApplicable,
                         );
                     };
-                    self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(mismatch_idx), is_method);
+                    self.label_fn_like(
+                        &mut err,
+                        fn_def_id,
+                        callee_ty,
+                        Some(mismatch_idx),
+                        is_method,
+                    );
                     err.emit();
                     return;
                 }
@@ -1081,8 +1070,7 @@ enum SuggestionText {
                 }
                 let suggestion_text = if let Some(provided_idx) = provided_idx
                     && let (_, provided_span) = provided_arg_tys[*provided_idx]
-                    && let Ok(arg_text) =
-                        source_map.span_to_snippet(provided_span)
+                    && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
                 {
                     arg_text
                 } else {
@@ -1183,7 +1171,7 @@ pub fn check_struct_path(
             self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
 
             // Check bounds on type arguments used in the path.
-            self.add_required_obligations(path_span, did, substs);
+            self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
 
             Some((variant, ty))
         } else {
@@ -1620,183 +1608,406 @@ fn finish_resolving_struct_path(
         }
     }
 
-    /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
-    /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
-    /// reference a type argument. The reason to walk also the checked type is that the coerced type
-    /// can be not easily comparable with predicate type (because of coercion). If the types match
-    /// for either checked or coerced type, and there's only *one* argument that does, we point at
-    /// the corresponding argument's expression span instead of the `fn` call path span.
-    fn point_at_arg_instead_of_call_if_possible(
+    /// Given a vector of fulfillment errors, try to adjust the spans of the
+    /// errors to more accurately point at the cause of the failure.
+    ///
+    /// This applies to calls, methods, and struct expressions. This will also
+    /// try to deduplicate errors that are due to the same cause but might
+    /// have been created with different [`ObligationCause`][traits::ObligationCause]s.
+    pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
         &self,
         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
-        expr: &'tcx hir::Expr<'tcx>,
-        call_sp: Span,
-        args: &'tcx [hir::Expr<'tcx>],
-        expected_tys: &[Ty<'tcx>],
     ) {
-        // We *do not* do this for desugared call spans to keep good diagnostics when involving
-        // the `?` operator.
-        if call_sp.desugaring_kind().is_some() {
-            return;
+        // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
+        // other errors that have the same span and predicate can also get fixed,
+        // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
+        // This is important since if we adjust one span but not the other, then
+        // we will have "duplicated" the error on the UI side.
+        let mut remap_cause = FxHashSet::default();
+        let mut not_adjusted = vec![];
+
+        for error in errors {
+            let before_span = error.obligation.cause.span;
+            if self.adjust_fulfillment_error_for_expr_obligation(error)
+                || before_span != error.obligation.cause.span
+            {
+                // Store both the predicate and the predicate *without constness*
+                // since sometimes we instantiate and check both of these in a
+                // method call, for example.
+                remap_cause.insert((
+                    before_span,
+                    error.obligation.predicate,
+                    error.obligation.cause.clone(),
+                ));
+                remap_cause.insert((
+                    before_span,
+                    error.obligation.predicate.without_const(self.tcx),
+                    error.obligation.cause.clone(),
+                ));
+            } else {
+                // If it failed to be adjusted once around, it may be adjusted
+                // via the "remap cause" mapping the second time...
+                not_adjusted.push(error);
+            }
         }
 
-        'outer: for error in errors {
-            // Only if the cause is somewhere inside the expression we want try to point at arg.
-            // Otherwise, it means that the cause is somewhere else and we should not change
-            // anything because we can break the correct span.
-            if !call_sp.contains(error.obligation.cause.span) {
-                continue;
+        for error in not_adjusted {
+            for (span, predicate, cause) in &remap_cause {
+                if *predicate == error.obligation.predicate
+                    && span.contains(error.obligation.cause.span)
+                {
+                    error.obligation.cause = cause.clone();
+                    continue;
+                }
             }
+        }
+    }
 
-            // Peel derived obligation, because it's the type that originally
-            // started this inference chain that matters, not the one we wound
-            // up with at the end.
-            fn unpeel_to_top<'a, 'tcx>(
-                mut code: &'a ObligationCauseCode<'tcx>,
-            ) -> &'a ObligationCauseCode<'tcx> {
-                let mut result_code = code;
-                loop {
-                    let parent = match code {
-                        ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
-                        ObligationCauseCode::BuiltinDerivedObligation(c)
-                        | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
-                        _ => break result_code,
-                    };
-                    (result_code, code) = (code, parent);
+    fn adjust_fulfillment_error_for_expr_obligation(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+    ) -> bool {
+        let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
+            = *error.obligation.cause.code().peel_derives() else { return false; };
+        let hir = self.tcx.hir();
+        let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
+
+        // Skip over mentioning async lang item
+        if Some(def_id) == self.tcx.lang_items().from_generator_fn()
+            && error.obligation.cause.span.desugaring_kind()
+                == Some(rustc_span::DesugaringKind::Async)
+        {
+            return false;
+        }
+
+        let Some(unsubstituted_pred) =
+            self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
+            else { return false; };
+
+        let generics = self.tcx.generics_of(def_id);
+        let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
+            ty::PredicateKind::Trait(pred) => pred.trait_ref.substs,
+            ty::PredicateKind::Projection(pred) => pred.projection_ty.substs,
+            _ => ty::List::empty(),
+        };
+
+        let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
+            predicate_substs.types().find_map(|ty| {
+                ty.walk().find_map(|arg| {
+                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                        && let ty::Param(param_ty) = ty.kind()
+                        && matches(param_ty)
+                    {
+                        Some(arg)
+                    } else {
+                        None
+                    }
+                })
+            })
+        };
+
+        // Prefer generics that are local to the fn item, since these are likely
+        // to be the cause of the unsatisfied predicate.
+        let mut param_to_point_at = find_param_matching(&|param_ty| {
+            self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
+        });
+        // Fall back to generic that isn't local to the fn item. This will come
+        // from a trait or impl, for example.
+        let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
+            self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
+                && param_ty.name != rustc_span::symbol::kw::SelfUpper
+        });
+        // Finally, the `Self` parameter is possibly the reason that the predicate
+        // is unsatisfied. This is less likely to be true for methods, because
+        // method probe means that we already kinda check that the predicates due
+        // to the `Self` type are true.
+        let mut self_param_to_point_at =
+            find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
+
+        // Finally, for ambiguity-related errors, we actually want to look
+        // for a parameter that is the source of the inference type left
+        // over in this predicate.
+        if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
+            fallback_param_to_point_at = None;
+            self_param_to_point_at = None;
+            param_to_point_at =
+                self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
+        }
+
+        if self.closure_span_overlaps_error(error, expr.span) {
+            return false;
+        }
+
+        match &expr.kind {
+            hir::ExprKind::Path(qpath) => {
+                if let hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Call(callee, args),
+                    hir_id: call_hir_id,
+                    span: call_span,
+                    ..
+                }) = hir.get(hir.get_parent_node(expr.hir_id))
+                    && callee.hir_id == expr.hir_id
+                {
+                    if self.closure_span_overlaps_error(error, *call_span) {
+                        return false;
+                    }
+
+                    for param in
+                        [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                        .into_iter()
+                        .flatten()
+                    {
+                        if self.point_at_arg_if_possible(
+                                error,
+                                def_id,
+                                param,
+                                *call_hir_id,
+                                callee.span,
+                                args,
+                            )
+                        {
+                            return true;
+                        }
+                    }
+                    // Notably, we only point to params that are local to the
+                    // item we're checking, since those are the ones we are able
+                    // to look in the final `hir::PathSegment` for. Everything else
+                    // would require a deeper search into the `qpath` than I think
+                    // is worthwhile.
+                    if let Some(param_to_point_at) = param_to_point_at
+                        && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+                    {
+                        return true;
+                    }
                 }
             }
-            let self_: ty::subst::GenericArg<'_> =
-                match unpeel_to_top(error.obligation.cause.code()) {
-                    ObligationCauseCode::BuiltinDerivedObligation(code)
-                    | ObligationCauseCode::DerivedObligation(code) => {
-                        code.parent_trait_pred.self_ty().skip_binder().into()
-                    }
-                    ObligationCauseCode::ImplDerivedObligation(code) => {
-                        code.derived.parent_trait_pred.self_ty().skip_binder().into()
+            hir::ExprKind::MethodCall(segment, args, ..) => {
+                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                    .into_iter()
+                    .flatten()
+                {
+                    if self.point_at_arg_if_possible(
+                        error,
+                        def_id,
+                        param,
+                        hir_id,
+                        segment.ident.span,
+                        args,
+                    ) {
+                        return true;
                     }
-                    _ => match error.obligation.predicate.kind().skip_binder() {
-                        ty::PredicateKind::Trait(predicate) => predicate.self_ty().into(),
-                        ty::PredicateKind::Projection(predicate) => {
-                            predicate.projection_ty.self_ty().into()
+                }
+                if let Some(param_to_point_at) = param_to_point_at
+                    && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
+                {
+                    return true;
+                }
+            }
+            hir::ExprKind::Struct(qpath, fields, ..) => {
+                if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
+                    self.typeck_results.borrow().qpath_res(qpath, hir_id)
+                {
+                    for param in
+                        [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                    {
+                        if let Some(param) = param
+                            && self.point_at_field_if_possible(
+                                error,
+                                def_id,
+                                param,
+                                variant_def_id,
+                                fields,
+                            )
+                        {
+                            return true;
                         }
-                        _ => continue,
-                    },
-                };
-            let self_ = self.resolve_vars_if_possible(self_);
-            let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
-
-            let typeck_results = self.typeck_results.borrow();
-
-            for (idx, arg) in args.iter().enumerate() {
-                // Don't adjust the span if we already have a more precise span
-                // within one of the args.
-                if arg.span.contains(error.obligation.cause.span) {
-                    let references_arg =
-                        typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
-                            || expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
-                    if references_arg && !arg.span.from_expansion() {
-                        error.obligation.cause.map_code(|parent_code| {
-                            ObligationCauseCode::FunctionArgumentObligation {
-                                arg_hir_id: args[idx].hir_id,
-                                call_hir_id: expr.hir_id,
-                                parent_code,
-                            }
-                        })
                     }
-                    continue 'outer;
+                }
+                if let Some(param_to_point_at) = param_to_point_at
+                    && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+                {
+                    return true;
                 }
             }
+            _ => {}
+        }
 
-            // Collect the argument position for all arguments that could have caused this
-            // `FulfillmentError`.
-            let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
-                .enumerate()
-                .flat_map(|(idx, (expected_ty, arg))| {
-                    if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) {
-                        vec![(idx, arg_ty), (idx, *expected_ty)]
-                    } else {
-                        vec![]
-                    }
-                })
-                .filter_map(|(i, ty)| {
-                    let ty = self.resolve_vars_if_possible(ty);
-                    // We walk the argument type because the argument's type could have
-                    // been `Option<T>`, but the `FulfillmentError` references `T`.
-                    if ty_matches_self(ty) { Some(i) } else { None }
-                })
-                .collect();
+        false
+    }
 
-            // Both checked and coerced types could have matched, thus we need to remove
-            // duplicates.
+    fn closure_span_overlaps_error(
+        &self,
+        error: &traits::FulfillmentError<'tcx>,
+        span: Span,
+    ) -> bool {
+        if let traits::FulfillmentErrorCode::CodeSelectionError(
+            traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
+        ) = error.code
+            && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
+            && span.overlaps(self.tcx.def_span(*def_id))
+        {
+            true
+        } else {
+            false
+        }
+    }
 
-            // We sort primitive type usize here and can use unstable sort
-            referenced_in.sort_unstable();
-            referenced_in.dedup();
+    fn point_at_arg_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        call_hir_id: hir::HirId,
+        callee_span: Span,
+        args: &[hir::Expr<'tcx>],
+    ) -> bool {
+        let sig = self.tcx.fn_sig(def_id).skip_binder();
+        let args_referencing_param: Vec<_> = sig
+            .inputs()
+            .iter()
+            .enumerate()
+            .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
+            .collect();
 
-            if let &[idx] = &referenced_in[..] {
-                // Do not point at the inside of a macro.
-                // That would often result in poor error messages.
-                if args[idx].span.from_expansion() {
-                    continue;
+        // If there's one field that references the given generic, great!
+        if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) {
+            error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
+            error.obligation.cause.map_code(|parent_code| {
+                ObligationCauseCode::FunctionArgumentObligation {
+                    arg_hir_id: arg.hir_id,
+                    call_hir_id,
+                    parent_code,
                 }
-                // We make sure that only *one* argument matches the obligation failure
-                // and we assign the obligation's span to its expression's.
-                error.obligation.cause.span = args[idx].span;
-                error.obligation.cause.map_code(|parent_code| {
-                    ObligationCauseCode::FunctionArgumentObligation {
-                        arg_hir_id: args[idx].hir_id,
-                        call_hir_id: expr.hir_id,
-                        parent_code,
-                    }
-                });
-            } else if error.obligation.cause.span == call_sp {
-                // Make function calls point at the callee, not the whole thing.
-                if let hir::ExprKind::Call(callee, _) = expr.kind {
-                    error.obligation.cause.span = callee.span;
+            });
+            return true;
+        } else if args_referencing_param.len() > 0 {
+            // If more than one argument applies, then point to the callee span at least...
+            // We have chance to fix this up further in `point_at_generics_if_possible`
+            error.obligation.cause.span = callee_span;
+        }
+
+        false
+    }
+
+    fn point_at_field_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        variant_def_id: DefId,
+        expr_fields: &[hir::ExprField<'tcx>],
+    ) -> bool {
+        let def = self.tcx.adt_def(def_id);
+
+        let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
+        let fields_referencing_param: Vec<_> = def
+            .variant_with_id(variant_def_id)
+            .fields
+            .iter()
+            .filter(|field| {
+                let field_ty = field.ty(self.tcx, identity_substs);
+                find_param_in_ty(field_ty, param_to_point_at)
+            })
+            .collect();
+
+        if let [field] = fields_referencing_param.as_slice() {
+            for expr_field in expr_fields {
+                // Look for the ExprField that matches the field, using the
+                // same rules that check_expr_struct uses for macro hygiene.
+                if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
+                {
+                    error.obligation.cause.span = expr_field
+                        .expr
+                        .span
+                        .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+                        .unwrap_or(expr_field.span);
+                    return true;
                 }
             }
         }
+
+        false
     }
 
-    /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
-    /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
-    /// were caused by them. If they were, we point at the corresponding type argument's span
-    /// instead of the `fn` call path span.
-    fn point_at_type_arg_instead_of_call_if_possible(
+    fn point_at_path_if_possible(
         &self,
-        errors: &mut Vec<traits::FulfillmentError<'tcx>>,
-        call_expr: &'tcx hir::Expr<'tcx>,
-    ) {
-        if let hir::ExprKind::Call(path, _) = &call_expr.kind {
-            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
-                for error in errors {
-                    let self_ty = match error.obligation.predicate.kind().skip_binder() {
-                        ty::PredicateKind::Trait(predicate) => predicate.self_ty(),
-                        ty::PredicateKind::Projection(predicate) => {
-                            predicate.projection_ty.self_ty()
-                        }
-                        _ => continue,
-                    };
-                    // If any of the type arguments in this path segment caused the
-                    // `FulfillmentError`, point at its span (#61860).
-                    for arg in path
-                        .segments
-                        .iter()
-                        .filter_map(|seg| seg.args.as_ref())
-                        .flat_map(|a| a.args.iter())
-                    {
-                        if let hir::GenericArg::Type(hir_ty) = &arg
-                            && let Some(ty) =
-                                self.typeck_results.borrow().node_type_opt(hir_ty.hir_id)
-                            && self.resolve_vars_if_possible(ty) == self_ty
-                        {
-                            error.obligation.cause.span = hir_ty.span;
-                            break;
-                        }
-                    }
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param: ty::GenericArg<'tcx>,
+        qpath: &QPath<'tcx>,
+    ) -> bool {
+        match qpath {
+            hir::QPath::Resolved(_, path) => {
+                if let Some(segment) = path.segments.last()
+                    && self.point_at_generic_if_possible(error, def_id, param, segment)
+                {
+                    return true;
+                }
+            }
+            hir::QPath::TypeRelative(_, segment) => {
+                if self.point_at_generic_if_possible(error, def_id, param, segment) {
+                    return true;
+                }
+            }
+            _ => {}
+        }
+
+        false
+    }
+
+    fn point_at_generic_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        segment: &hir::PathSegment<'tcx>,
+    ) -> bool {
+        let own_substs = self
+            .tcx
+            .generics_of(def_id)
+            .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
+        let Some((index, _)) = own_substs
+            .iter()
+            .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
+            .enumerate()
+            .find(|(_, arg)| **arg == param_to_point_at) else { return false };
+        let Some(arg) = segment
+            .args()
+            .args
+            .iter()
+            .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
+            .nth(index) else { return false; };
+        error.obligation.cause.span = arg
+            .span()
+            .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+            .unwrap_or(arg.span());
+        true
+    }
+
+    fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
+        &self,
+        item_def_id: DefId,
+        t: T,
+    ) -> Option<ty::GenericArg<'tcx>> {
+        struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
+        impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
+            type BreakTy = ty::GenericArg<'tcx>;
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+                if let Some(origin) = self.0.type_var_origin(ty)
+                    && let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
+                        origin.kind
+                    && let generics = self.0.tcx.generics_of(self.1)
+                    && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
+                    && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
+                        .get(index as usize)
+                {
+                    ControlFlow::Break(*subst)
+                } else {
+                    ty.super_visit_with(self)
                 }
             }
         }
+        t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
     }
 
     fn label_fn_like(
@@ -1864,14 +2075,17 @@ fn label_fn_like(
                     let new_def_id = self.probe(|_| {
                         let trait_ref = ty::TraitRef::new(
                             call_kind.to_def_id(self.tcx),
-                            self.tcx.mk_substs([
-                                ty::GenericArg::from(callee_ty),
-                                self.next_ty_var(TypeVariableOrigin {
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                    span: rustc_span::DUMMY_SP,
-                                })
-                                .into(),
-                            ].into_iter()),
+                            self.tcx.mk_substs(
+                                [
+                                    ty::GenericArg::from(callee_ty),
+                                    self.next_ty_var(TypeVariableOrigin {
+                                        kind: TypeVariableOriginKind::MiscVariable,
+                                        span: rustc_span::DUMMY_SP,
+                                    })
+                                    .into(),
+                                ]
+                                .into_iter(),
+                            ),
                         );
                         let obligation = traits::Obligation::new(
                             traits::ObligationCause::dummy(),
@@ -1886,7 +2100,7 @@ fn label_fn_like(
                             Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
                                 Some(impl_source.impl_def_id)
                             }
-                            _ => None
+                            _ => None,
                         }
                     });
                     if let Some(new_def_id) = new_def_id {
@@ -1940,3 +2154,23 @@ fn label_fn_like(
         }
     }
 }
+
+fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>) -> bool {
+    let mut walk = ty.walk();
+    while let Some(arg) = walk.next() {
+        if arg == param_to_point_at {
+            return true;
+        } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
+            && let ty::Projection(..) = ty.kind()
+        {
+            // This logic may seem a bit strange, but typically when
+            // we have a projection type in a function signature, the
+            // argument that's being passed into that signature is
+            // not actually constraining that projection's substs in
+            // a meaningful way. So we skip it, and see improvements
+            // in some UI tests.
+            walk.skip_current_subtree();
+        }
+    }
+    false
+}
index 2c89b63ae84f813be5350bfbb200bede9c163548..59fd5c315ae63ca9c3bad180b4bacbbe3ce8b8ff 100644 (file)
@@ -491,7 +491,19 @@ fn add_obligations(
         // so we just call `predicates_for_generics` directly to avoid redoing work.
         // `self.add_required_obligations(self.span, def_id, &all_substs);`
         for obligation in traits::predicates_for_generics(
-            traits::ObligationCause::new(self.span, self.body_id, traits::ItemObligation(def_id)),
+            |idx, span| {
+                let code = if span.is_dummy() {
+                    ObligationCauseCode::ExprItemObligation(def_id, self.call_expr.hir_id, idx)
+                } else {
+                    ObligationCauseCode::ExprBindingObligation(
+                        def_id,
+                        span,
+                        self.call_expr.hir_id,
+                        idx,
+                    )
+                };
+                traits::ObligationCause::new(self.span, self.body_id, code)
+            },
             self.param_env,
             method_predicates,
         ) {
index 0e678c41f8b40047d66a6a18ecda35ad46b50092..de26a9e56e2d6b57275d2060fb475c540677eda0 100644 (file)
@@ -534,7 +534,12 @@ fn construct_obligation_for_trait(
         } else {
             traits::ObligationCause::misc(span, self.body_id)
         };
-        obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
+        let predicates_cause = cause.clone();
+        obligations.extend(traits::predicates_for_generics(
+            move |_, _| predicates_cause.clone(),
+            self.param_env,
+            bounds,
+        ));
 
         // Also add an obligation for the method type being well-formed.
         let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig));
index efe15fec7cbfa0ba88a6e0f281cff93bf665e81d..d9870060a40bbb974922ac85bce1f00c9d21f838 100644 (file)
@@ -1514,8 +1514,11 @@ fn consider_probe(
                         traits::normalize(selcx, self.param_env, cause.clone(), impl_bounds);
 
                     // Convert the bounds into obligations.
-                    let impl_obligations =
-                        traits::predicates_for_generics(cause, self.param_env, impl_bounds);
+                    let impl_obligations = traits::predicates_for_generics(
+                        move |_, _| cause.clone(),
+                        self.param_env,
+                        impl_bounds,
+                    );
 
                     let candidate_obligations = impl_obligations
                         .chain(norm_obligations.into_iter())
index dfbef544b1d28835fe0100009824f3c23581fe12..fb675212e3ffb4607215ddc7ff0f9003f2e63e87 100644 (file)
@@ -87,7 +87,6 @@
 mod pat;
 mod place_op;
 mod region;
-pub mod regionck;
 pub mod rvalue_scopes;
 mod upvar;
 pub mod wfcheck;
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
deleted file mode 100644 (file)
index d49a613..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::outlives::outlives_bounds::InferCtxtExt as _;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::Ty;
-
-pub(crate) trait OutlivesEnvironmentExt<'tcx> {
-    fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    );
-}
-
-impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
-    #[instrument(level = "debug", skip(self, infcx))]
-    fn add_implied_bounds<'a>(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    ) {
-        for ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-}
index d0334cd0df7bbf97f1818038469215160b5c4a3a..ed653f0f9c82d70c1dc7bbddfa65916af368dfaf 100644 (file)
@@ -1,5 +1,5 @@
-use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -10,7 +10,6 @@
 use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::Normalized;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -24,8 +23,6 @@
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::normalize::AtExt;
-use rustc_trait_selection::traits::query::NoSolution;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
 };
@@ -72,9 +69,11 @@ fn register_wf_obligation(
     ) {
         let cause =
             traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc));
+        // for a type to be WF, we do not need to check if const trait predicates satisfy.
+        let param_env = self.param_env.without_const();
         self.ocx.register_obligation(traits::Obligation::new(
             cause,
-            self.param_env,
+            param_env,
             ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
         ));
     }
@@ -86,26 +85,31 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     body_def_id: LocalDefId,
     f: F,
 ) where
-    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet<Ty<'tcx>>,
+    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
 {
     let param_env = tcx.param_env(body_def_id);
     let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
     tcx.infer_ctxt().enter(|ref infcx| {
         let ocx = ObligationCtxt::new(infcx);
+
+        let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
+
         let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
 
         if !tcx.features().trivial_bounds {
             wfcx.check_false_global_bounds()
         }
-        let wf_tys = f(&mut wfcx);
+        f(&mut wfcx);
         let errors = wfcx.select_all_or_error();
         if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
+        let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+        let outlives_environment =
+            OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+
         infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
     })
 }
@@ -694,8 +698,11 @@ fn resolve_regions_with_wf_tys<'tcx>(
     // region constraints get added and solved there and we need to test each
     // call individually.
     tcx.infer_ctxt().enter(|infcx| {
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(&infcx),
+            infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
+        );
         let region_bound_pairs = outlives_environment.region_bound_pairs();
 
         add_constraints(&infcx, region_bound_pairs);
@@ -976,15 +983,9 @@ fn check_associated_item(
     enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
         let item = tcx.associated_item(item_id);
 
-        let (mut implied_bounds, self_ty) = match item.container {
-            ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param),
-            ty::ImplContainer => {
-                let def_id = item.container_id(tcx);
-                (
-                    impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
-                    tcx.type_of(def_id),
-                )
-            }
+        let self_ty = match item.container {
+            ty::TraitContainer => tcx.types.self_param,
+            ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
         };
 
         match item.kind {
@@ -1002,7 +1003,6 @@ fn check_associated_item(
                     sig,
                     hir_sig.decl,
                     item.def_id.expect_local(),
-                    &mut implied_bounds,
                 );
                 check_method_receiver(wfcx, hir_sig, item, self_ty);
             }
@@ -1017,8 +1017,6 @@ fn check_associated_item(
                 }
             }
         }
-
-        implied_bounds
     })
 }
 
@@ -1118,9 +1116,6 @@ fn check_type_defn<'tcx, F>(
         }
 
         check_where_clauses(wfcx, item.span, item.def_id);
-
-        // No implied bounds in a struct definition.
-        FxHashSet::default()
     });
 }
 
@@ -1144,9 +1139,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     }
 
     enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
-        check_where_clauses(wfcx, item.span, item.def_id);
-
-        FxHashSet::default()
+        check_where_clauses(wfcx, item.span, item.def_id)
     });
 
     // Only check traits, don't check trait aliases
@@ -1186,9 +1179,7 @@ fn check_item_fn(
 ) {
     enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
         let sig = tcx.fn_sig(def_id);
-        let mut implied_bounds = FxHashSet::default();
-        check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds);
-        implied_bounds
+        check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
     })
 }
 
@@ -1231,9 +1222,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
                 tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
             );
         }
-
-        // No implied bounds in a const, etc.
-        FxHashSet::default()
     });
 }
 
@@ -1284,8 +1272,6 @@ fn check_impl<'tcx>(
         }
 
         check_where_clauses(wfcx, item.span, item.def_id);
-
-        impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span)
     });
 }
 
@@ -1465,7 +1451,13 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
     assert_eq!(predicates.predicates.len(), predicates.spans.len());
     let wf_obligations =
         iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
-            traits::wf::predicate_obligations(infcx, wfcx.param_env, wfcx.body_id, p, sp)
+            traits::wf::predicate_obligations(
+                infcx,
+                wfcx.param_env.without_const(),
+                wfcx.body_id,
+                p,
+                sp,
+            )
         });
 
     let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
@@ -1479,7 +1471,6 @@ fn check_fn_or_method<'tcx>(
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
     def_id: LocalDefId,
-    implied_bounds: &mut FxHashSet<Ty<'tcx>>,
 ) {
     let tcx = wfcx.tcx();
     let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@@ -1521,15 +1512,8 @@ fn check_fn_or_method<'tcx>(
         );
     }
 
-    implied_bounds.extend(sig.inputs());
-
     wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into());
 
-    // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.insert(sig.output());
-
-    debug!(?implied_bounds);
-
     check_where_clauses(wfcx, span, def_id);
 }
 
@@ -1924,40 +1908,6 @@ fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
     }
 }
 
-pub fn impl_implied_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: LocalDefId,
-    span: Span,
-) -> FxHashSet<Ty<'tcx>> {
-    // We completely ignore any obligations caused by normalizing the types
-    // we assume to be well formed. Considering that the user of the implied
-    // bounds will also normalize them, we leave it to them to emit errors
-    // which should result in better causes and spans.
-    tcx.infer_ctxt().enter(|infcx| {
-        let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id));
-        match tcx.impl_trait_ref(impl_def_id) {
-            Some(trait_ref) => {
-                // Trait impl: take implied bounds from all types that
-                // appear in the trait reference.
-                match infcx.at(&cause, param_env).normalize(trait_ref) {
-                    Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(),
-                    Err(NoSolution) => FxHashSet::default(),
-                }
-            }
-
-            None => {
-                // Inherent impl: take implied bounds from the `self` type.
-                let self_ty = tcx.type_of(impl_def_id);
-                match infcx.at(&cause, param_env).normalize(self_ty) {
-                    Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]),
-                    Err(NoSolution) => FxHashSet::default(),
-                }
-            }
-        }
-    })
-}
-
 fn error_392(
     tcx: TyCtxt<'_>,
     span: Span,
index 74abb71a18e76f876d51008f4efef7cdcae80349..6240024d49c74eb47c2eae2952f37a23eb667c18 100644 (file)
 //! cause use after frees with purely safe code in the same way as specializing
 //! on traits with methods can.
 
-use crate::check::regionck::OutlivesEnvironmentExt;
-use crate::check::wfcheck::impl_implied_bounds;
 use crate::constrained_generic_params as cgp;
 use crate::errors::SubstsOnOverriddenImpl;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::specialization_graph::Node;
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
 use rustc_span::Span;
-use rustc_trait_selection::traits::{self, translate_substs, wf};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
 
 pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
-        tcx.infer_ctxt().enter(|infcx| {
-            check_always_applicable(&infcx, impl_def_id, node);
-        });
+        check_always_applicable(tcx, impl_def_id, node);
     }
 }
 
@@ -105,16 +103,14 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
 }
 
 /// Check that `impl1` is a sound specialization
-fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) {
-    if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) {
+fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+    if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
         let impl2_def_id = impl2_node.def_id();
         debug!(
             "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
             impl1_def_id, impl2_def_id, impl2_substs
         );
 
-        let tcx = infcx.tcx;
-
         let parent_substs = if impl2_node.is_from_trait() {
             impl2_substs.to_vec()
         } else {
@@ -124,7 +120,7 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
         let span = tcx.def_span(impl1_def_id);
         check_static_lifetimes(tcx, &parent_substs, span);
         check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
-        check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+        check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
     }
 }
 
@@ -139,32 +135,38 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
 ///
 /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
 fn get_impl_substs<'tcx>(
-    infcx: &InferCtxt<'_, 'tcx>,
+    tcx: TyCtxt<'tcx>,
     impl1_def_id: LocalDefId,
     impl2_node: Node,
 ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
-    let tcx = infcx.tcx;
-    let param_env = tcx.param_env(impl1_def_id);
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let ocx = ObligationCtxt::new(infcx);
+        let param_env = tcx.param_env(impl1_def_id);
+        let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id);
 
-    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
-    let impl2_substs =
-        translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+        let assumed_wf_types =
+            ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
 
-    let mut outlives_env = OutlivesEnvironment::new(param_env);
-    let implied_bounds =
-        impl_implied_bounds(infcx.tcx, param_env, impl1_def_id, tcx.def_span(impl1_def_id));
-    outlives_env.add_implied_bounds(
-        infcx,
-        implied_bounds,
-        tcx.hir().local_def_id_to_hir_id(impl1_def_id),
-    );
-    infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
-    let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
-        let span = tcx.def_span(impl1_def_id);
-        tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
-        return None;
-    };
-    Some((impl1_substs, impl2_substs))
+        let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+        let impl2_substs =
+            translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            ocx.infcx.report_fulfillment_errors(&errors, None, false);
+            return None;
+        }
+
+        let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
+        let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+        infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+        let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+            let span = tcx.def_span(impl1_def_id);
+            tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
+            return None;
+        };
+        Some((impl1_substs, impl2_substs))
+    })
 }
 
 /// Returns a list of all of the unconstrained subst of the given impl.
@@ -279,14 +281,13 @@ fn check_static_lifetimes<'tcx>(
 /// * a well-formed predicate of a type argument of the trait being implemented,
 ///   including the `Self`-type.
 fn check_predicates<'tcx>(
-    infcx: &InferCtxt<'_, 'tcx>,
+    tcx: TyCtxt<'tcx>,
     impl1_def_id: LocalDefId,
     impl1_substs: SubstsRef<'tcx>,
     impl2_node: Node,
     impl2_substs: SubstsRef<'tcx>,
     span: Span,
 ) {
-    let tcx = infcx.tcx;
     let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
     let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
         tcx,
@@ -343,19 +344,23 @@ fn check_predicates<'tcx>(
 
     // Include the well-formed predicates of the type parameters of the impl.
     for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs {
-        if let Some(obligations) = wf::obligations(
-            infcx,
-            tcx.param_env(impl1_def_id),
-            tcx.hir().local_def_id_to_hir_id(impl1_def_id),
-            0,
-            arg,
-            span,
-        ) {
+        tcx.infer_ctxt().enter(|ref infcx| {
+            let obligations = wf::obligations(
+                infcx,
+                tcx.param_env(impl1_def_id),
+                tcx.hir().local_def_id_to_hir_id(impl1_def_id),
+                0,
+                arg,
+                span,
+            )
+            .unwrap();
+
+            assert!(!obligations.needs_infer());
             impl2_predicates.extend(
                 traits::elaborate_obligations(tcx, obligations)
                     .map(|obligation| obligation.predicate),
             )
-        }
+        })
     }
     impl2_predicates.extend(
         traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
index 8c6fb6a77181d9b76044040d20d000674407f2dc..1ff9c6271316ab3afecb10400857c57a0341ffc6 100644 (file)
@@ -72,6 +72,7 @@
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
 #![feature(is_some_with)]
+#![feature(type_alias_impl_trait)]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 229a64650848cff7eae1401fe3a5cff720d1354a..024e20d92234b6ab36ee3820586a70769031721e 100644 (file)
@@ -1,5 +1,7 @@
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::ty::{self, Ty};
+use rustc_hir::HirId;
+use rustc_middle::ty::{self, ParamEnv, Ty};
 use rustc_trait_selection::infer::InferCtxt;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::NoSolution;
@@ -7,16 +9,24 @@
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
-pub trait InferCtxtExt<'tcx> {
+type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
+pub trait InferCtxtExt<'a, 'tcx> {
     fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: hir::HirId,
         ty: Ty<'tcx>,
     ) -> Vec<OutlivesBound<'tcx>>;
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        tys: FxHashSet<Ty<'tcx>>,
+    ) -> Bounds<'a, 'tcx>;
 }
 
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
     /// automatically. The idea is that (e.g.) a caller must check that a
     /// function's argument types are well-formed immediately before
@@ -87,4 +97,18 @@ fn implied_outlives_bounds(
 
         output
     }
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ParamEnv<'tcx>,
+        body_id: HirId,
+        tys: FxHashSet<Ty<'tcx>>,
+    ) -> Bounds<'a, 'tcx> {
+        tys.into_iter()
+            .map(move |ty| {
+                let ty = self.resolve_vars_if_possible(ty);
+                self.implied_outlives_bounds(param_env, body_id, ty)
+            })
+            .flatten()
+    }
 }
index 7d560964d85be7108d99a51e50a3a180ae684858..b2f0194599b287057f41023545a244749eaf232f 100644 (file)
@@ -15,7 +15,7 @@ fn allocate_zeroed() {
         let end = i.add(layout.size());
         while i < end {
             assert_eq!(*i, 0);
-            i = i.offset(1);
+            i = i.add(1);
         }
         Global.deallocate(ptr.as_non_null_ptr(), layout);
     }
index c1ceeb0deb837100e2b77cccfc7312a7889c5f00..6955d863c99e792df84660d50d14203ceb9b9848 100644 (file)
@@ -1,4 +1,4 @@
-//! A pointer type for heap allocation.
+//! The `Box<T>` type for heap allocation.
 //!
 //! [`Box<T>`], casually referred to as a 'box', provides the simplest form of
 //! heap allocation in Rust. Boxes provide ownership for this allocation, and
index 197e7aaaccf3d34d59d180582ee54426ef6c0e1b..4583bc9a158efc02c059e239c40962faf529f9ce 100644 (file)
@@ -1010,7 +1010,8 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE
     /// current length. The allocator may reserve more space to speculatively
     /// avoid frequent allocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
index 4d895d83745b219951368e91196794cc97cdd249..347a938fd0c5896b92650c5aecd6901431c1918b 100644 (file)
@@ -794,7 +794,8 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE
     /// in the given deque. The collection may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
@@ -2447,8 +2448,8 @@ pub fn make_contiguous(&mut self) -> &mut [T] {
                     let mut right_offset = 0;
                     for i in left_edge..right_edge {
                         right_offset = (i - left_edge) % (cap - right_edge);
-                        let src: isize = (right_edge + right_offset) as isize;
-                        ptr::swap(buf.add(i), buf.offset(src));
+                        let src = right_edge + right_offset;
+                        ptr::swap(buf.add(i), buf.add(src));
                     }
                     let n_ops = right_edge - left_edge;
                     left_edge += n_ops;
index ae61b1f1e8ed5f43496f959fb52108231dff61dd..be21d8c722d78217c8f27617f09b5a183f6f0f40 100644 (file)
@@ -436,9 +436,9 @@ pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
     ///
     /// unsafe {
     ///     assert_eq!(b'f', *ptr as u8);
-    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
-    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
-    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
+    ///     assert_eq!(b'o', *ptr.add(1) as u8);
+    ///     assert_eq!(b'o', *ptr.add(2) as u8);
+    ///     assert_eq!(b'\0', *ptr.add(3) as u8);
     ///
     ///     // retake pointer to free memory
     ///     let _ = CString::from_raw(ptr);
index 63d4d94529008dbf8fca0c1fe305cc060d9f1069..bcd3f49e208928b9119ac40af6d3a822dddf7f3a 100644 (file)
@@ -1,82 +1,12 @@
-//! A dynamically-sized view into a contiguous sequence, `[T]`.
+//! Utilities for the slice primitive type.
 //!
 //! *[See also the slice primitive type](slice).*
 //!
-//! Slices are a view into a block of memory represented as a pointer and a
-//! length.
+//! Most of the structs in this module are iterator types which can only be created
+//! using a certain function. For example, `slice.iter()` yields an [`Iter`].
 //!
-//! ```
-//! // slicing a Vec
-//! let vec = vec![1, 2, 3];
-//! let int_slice = &vec[..];
-//! // coercing an array to a slice
-//! let str_slice: &[&str] = &["one", "two", "three"];
-//! ```
-//!
-//! Slices are either mutable or shared. The shared slice type is `&[T]`,
-//! while the mutable slice type is `&mut [T]`, where `T` represents the element
-//! type. For example, you can mutate the block of memory that a mutable slice
-//! points to:
-//!
-//! ```
-//! let x = &mut [1, 2, 3];
-//! x[1] = 7;
-//! assert_eq!(x, &[1, 7, 3]);
-//! ```
-//!
-//! Here are some of the things this module contains:
-//!
-//! ## Structs
-//!
-//! There are several structs that are useful for slices, such as [`Iter`], which
-//! represents iteration over a slice.
-//!
-//! ## Trait Implementations
-//!
-//! There are several implementations of common traits for slices. Some examples
-//! include:
-//!
-//! * [`Clone`]
-//! * [`Eq`], [`Ord`] - for slices whose element type are [`Eq`] or [`Ord`].
-//! * [`Hash`] - for slices whose element type is [`Hash`].
-//!
-//! ## Iteration
-//!
-//! The slices implement `IntoIterator`. The iterator yields references to the
-//! slice elements.
-//!
-//! ```
-//! let numbers = &[0, 1, 2];
-//! for n in numbers {
-//!     println!("{n} is a number!");
-//! }
-//! ```
-//!
-//! The mutable slice yields mutable references to the elements:
-//!
-//! ```
-//! let mut scores = [7, 8, 9];
-//! for score in &mut scores[..] {
-//!     *score += 1;
-//! }
-//! ```
-//!
-//! This iterator yields mutable references to the slice's elements, so while
-//! the element type of the slice is `i32`, the element type of the iterator is
-//! `&mut i32`.
-//!
-//! * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
-//!   iterators.
-//! * Further methods that return iterators are [`.split`], [`.splitn`],
-//!   [`.chunks`], [`.windows`] and more.
-//!
-//! [`Hash`]: core::hash::Hash
-//! [`.iter`]: slice::iter
-//! [`.iter_mut`]: slice::iter_mut
-//! [`.split`]: slice::split
-//! [`.splitn`]: slice::splitn
-//! [`.chunks`]: slice::chunks
-//! [`.windows`]: slice::windows
+//! A few functions are provided to create a slice from a value reference
+//! or from a raw pointer.
 #![stable(feature = "rust1", since = "1.0.0")]
 // Many of the usings in this module are only used in the test configuration.
 // It's cleaner to just turn off the unused_imports warning than to fix them.
@@ -1024,7 +954,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
             // Consume the greater side.
             // If equal, prefer the right run to maintain stability.
             unsafe {
-                let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) {
+                let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
                     decrement_and_get(left)
                 } else {
                     decrement_and_get(right)
@@ -1038,12 +968,12 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
 
     unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
         let old = *ptr;
-        *ptr = unsafe { ptr.offset(1) };
+        *ptr = unsafe { ptr.add(1) };
         old
     }
 
     unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
-        *ptr = unsafe { ptr.offset(-1) };
+        *ptr = unsafe { ptr.sub(1) };
         *ptr
     }
 
index b94b1b1ce216a0630d402bfc97c65816fb5cca46..b28d20cda179ec32054515d56dad13d303e387ee 100644 (file)
@@ -1,26 +1,6 @@
-//! Unicode string slices.
+//! Utilities for the `str` primitive type.
 //!
 //! *[See also the `str` primitive type](str).*
-//!
-//! The `&str` type is one of the two main string types, the other being `String`.
-//! Unlike its `String` counterpart, its contents are borrowed.
-//!
-//! # Basic Usage
-//!
-//! A basic string declaration of `&str` type:
-//!
-//! ```
-//! let hello_world = "Hello, World!";
-//! ```
-//!
-//! Here we have declared a string literal, also known as a string slice.
-//! String literals have a static lifetime, which means the string `hello_world`
-//! is guaranteed to be valid for the duration of the entire program.
-//! We can explicitly specify `hello_world`'s lifetime as well:
-//!
-//! ```
-//! let hello_world: &'static str = "Hello, world!";
-//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 // Many of the usings in this module are only used in the test configuration.
index 7bee894d3e404e98840b289869460ced1ddb5a04..e28ace4795f994aaf89123fc443087bef8075dfc 100644 (file)
@@ -1080,7 +1080,8 @@ pub fn reserve_exact(&mut self, additional: usize) {
     /// current length. The allocator may reserve more space to speculatively
     /// avoid frequent allocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
index 55dcb84ad16f922d55d198a620ea151ab8e10d91..b211421b20270f3787646651dd99025ca21903fc 100644 (file)
@@ -267,7 +267,7 @@ fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
             // one slot in the underlying storage will have been freed up and we can immediately
             // write back the result.
             unsafe {
-                let dst = dst_buf.offset(i as isize);
+                let dst = dst_buf.add(i);
                 debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation");
                 ptr::write(dst, self.__iterator_get_unchecked(i));
                 // Since this executes user code which can panic we have to bump the pointer
index 1b483e3fc7793a499fcc236781eea1e5f96f8123..e02ad391a595fae24192ab21931d64e38f47e00c 100644 (file)
@@ -160,7 +160,7 @@ fn next(&mut self) -> Option<T> {
             Some(unsafe { mem::zeroed() })
         } else {
             let old = self.ptr;
-            self.ptr = unsafe { self.ptr.offset(1) };
+            self.ptr = unsafe { self.ptr.add(1) };
 
             Some(unsafe { ptr::read(old) })
         }
@@ -272,7 +272,7 @@ fn next_back(&mut self) -> Option<T> {
             // Make up a value of this ZST.
             Some(unsafe { mem::zeroed() })
         } else {
-            self.end = unsafe { self.end.offset(-1) };
+            self.end = unsafe { self.end.sub(1) };
 
             Some(unsafe { ptr::read(self.end) })
         }
@@ -288,7 +288,7 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
             }
         } else {
             // SAFETY: same as for advance_by()
-            self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) };
+            self.end = unsafe { self.end.sub(step_size) };
         }
         let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
         // SAFETY: same as for advance_by()
index fa9f2131c0c1d3e2db6896e9925677d1692507e2..fe983274b5c721dec8784afca7424bf0b4a4baad 100644 (file)
@@ -542,8 +542,8 @@ pub fn with_capacity(capacity: usize) -> Self {
     ///
     /// unsafe {
     ///     // Overwrite memory with 4, 5, 6
-    ///     for i in 0..len as isize {
-    ///         ptr::write(p.offset(i), 4 + i);
+    ///     for i in 0..len {
+    ///         ptr::write(p.add(i), 4 + i);
     ///     }
     ///
     ///     // Put everything back together into a Vec
@@ -702,8 +702,8 @@ pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
     ///
     /// unsafe {
     ///     // Overwrite memory with 4, 5, 6
-    ///     for i in 0..len as isize {
-    ///         ptr::write(p.offset(i), 4 + i);
+    ///     for i in 0..len {
+    ///         ptr::write(p.add(i), 4 + i);
     ///     }
     ///
     ///     // Put everything back together into a Vec
@@ -875,7 +875,8 @@ pub fn reserve_exact(&mut self, additional: usize) {
     /// in the given `Vec<T>`. The collection may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
@@ -1393,7 +1394,7 @@ fn assert_failed(index: usize, len: usize) -> ! {
                 if index < len {
                     // Shift everything over to make space. (Duplicating the
                     // `index`th element into two consecutive places.)
-                    ptr::copy(p, p.offset(1), len - index);
+                    ptr::copy(p, p.add(1), len - index);
                 } else if index == len {
                     // No elements need shifting.
                 } else {
@@ -1455,7 +1456,7 @@ fn assert_failed(index: usize, len: usize) -> ! {
                 ret = ptr::read(ptr);
 
                 // Shift everything down to fill in that spot.
-                ptr::copy(ptr.offset(1), ptr, len - index - 1);
+                ptr::copy(ptr.add(1), ptr, len - index - 1);
             }
             self.set_len(len - 1);
             ret
@@ -2408,7 +2409,7 @@ fn extend_with<E: ExtendWith<T>>(&mut self, n: usize, mut value: E) {
             // Write all elements except the last one
             for _ in 1..n {
                 ptr::write(ptr, value.next());
-                ptr = ptr.offset(1);
+                ptr = ptr.add(1);
                 // Increment the length in every step in case next() panics
                 local_len.increment_len(1);
             }
index 506ee0ecfa279c7693cc9a19e58d98a668425b7d..1ea9c827afd70702f1254b843d6ed2e3b48e472a 100644 (file)
@@ -39,7 +39,7 @@ impl<T, I, A: Allocator> SpecExtend<T, I> for Vec<T, A>
                 let mut local_len = SetLenOnDrop::new(&mut self.len);
                 iterator.for_each(move |element| {
                     ptr::write(ptr, element);
-                    ptr = ptr.offset(1);
+                    ptr = ptr.add(1);
                     // Since the loop executes user code which can panic we have to bump the pointer
                     // after each step.
                     // NB can't overflow since we would have had to alloc the address space
index 7379569dd68fe4a189f4218c860fab7d482f9164..e30329aa1cb6c78e46c8952eae1f839763ec8df4 100644 (file)
@@ -1010,11 +1010,11 @@ fn test_as_bytes_fail() {
 fn test_as_ptr() {
     let buf = "hello".as_ptr();
     unsafe {
-        assert_eq!(*buf.offset(0), b'h');
-        assert_eq!(*buf.offset(1), b'e');
-        assert_eq!(*buf.offset(2), b'l');
-        assert_eq!(*buf.offset(3), b'l');
-        assert_eq!(*buf.offset(4), b'o');
+        assert_eq!(*buf.add(0), b'h');
+        assert_eq!(*buf.add(1), b'e');
+        assert_eq!(*buf.add(2), b'l');
+        assert_eq!(*buf.add(3), b'l');
+        assert_eq!(*buf.add(4), b'o');
     }
 }
 
index d94da8f5f5a0eac6731a298606f33715bd95f932..5be4d5f1279e555de2cc1ad125e1fdfc82c4bd22 100644 (file)
@@ -293,6 +293,22 @@ fn test_retain() {
     assert_eq!(vec, [2, 4]);
 }
 
+#[test]
+fn test_retain_predicate_order() {
+    for to_keep in [true, false] {
+        let mut number_of_executions = 0;
+        let mut vec = vec![1, 2, 3, 4];
+        let mut next_expected = 1;
+        vec.retain(|&x| {
+            assert_eq!(next_expected, x);
+            next_expected += 1;
+            number_of_executions += 1;
+            to_keep
+        });
+        assert_eq!(number_of_executions, 4);
+    }
+}
+
 #[test]
 fn test_retain_pred_panic_with_hole() {
     let v = (0..5).map(Rc::new).collect::<Vec<_>>();
@@ -354,6 +370,35 @@ fn drop(&mut self) {
     assert!(v.iter().all(|r| Rc::strong_count(r) == 1));
 }
 
+#[test]
+fn test_retain_maybeuninits() {
+    // This test aimed to be run under miri.
+    use core::mem::MaybeUninit;
+    let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into();
+    vec.retain(|x| {
+        // SAFETY: Retain must visit every element of Vec in original order and exactly once.
+        // Our values is initialized at creation of Vec.
+        let v = unsafe { x.assume_init_ref()[0] };
+        if v & 1 == 0 {
+            return true;
+        }
+        // SAFETY: Value is initialized.
+        // Value wouldn't be dropped by `Vec::retain`
+        // because `MaybeUninit` doesn't drop content.
+        drop(unsafe { x.assume_init_read() });
+        false
+    });
+    let vec: Vec<i32> = vec
+        .into_iter()
+        .map(|x| unsafe {
+            // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`.
+            // Remaining values are initialized.
+            x.assume_init()[0]
+        })
+        .collect();
+    assert_eq!(vec, [2, 4]);
+}
+
 #[test]
 fn test_dedup() {
     fn case(a: Vec<i32>, b: Vec<i32>) {
index f20c497a183b2c07a246170116b4ea6651df9fd3..e54f6c912d5945eacdc096a27c4b5b52222a6575 100644 (file)
@@ -1,7 +1,4 @@
-//! This module contains the `Any` trait, which enables dynamic typing
-//! of any `'static` type through runtime reflection. It also contains the
-//! `Provider` trait and accompanying API, which enable trait objects to provide
-//! data based on typed requests, an alternate form of runtime reflection.
+//! Utilities for dynamic typing or type reflection.
 //!
 //! # `Any` and `TypeId`
 //!
index c9823a136bc4214dd6d918dab330497c0537c735..db5bfcab9d2b163c1a3e6e07234fd7a9682019d4 100644 (file)
@@ -1,4 +1,4 @@
-//! Helper functions and types for fixed-length arrays.
+//! Utilities for the array primitive type.
 //!
 //! *[See also the array primitive type](array).*
 
index 58eabecf3f091c4e3c3ddff9ae444e32dbcb734b..8378611eb18c306b237f9f568610fc5a91cfbd58 100644 (file)
@@ -1,4 +1,4 @@
-//! A module for working with borrowed data.
+//! Utilities for working with borrowed data.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 0df23e7bbe695ded0602984d2afc6c2c7ac09305..a4bdd38f6553095c91a26e2ba4691c8d6a26ae63 100644 (file)
@@ -1,4 +1,6 @@
-//! A character type.
+//! Utilities for the `char` primitive type.
+//!
+//! *[See also the `char` primitive type](primitive@char).*
 //!
 //! The `char` type represents a single character. More specifically, since
 //! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
index 5ca5b5fde16048d6d41dab32b2ad7553bdd2aaee..8a30bb6745060c22a01c947752bbc15e45ff2a6f 100644 (file)
@@ -1,6 +1,6 @@
-//! Functionality for ordering and comparison.
+//! Utilities for comparing and ordering values.
 //!
-//! This module contains various tools for ordering and comparing values. In
+//! This module contains various tools for comparing and ordering values. In
 //! summary:
 //!
 //! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and
index 1ce00828bf3449c248c12b5a3f18ff07a62dab48..b53cd6074b5327d18e6044b11a27cffc3eb2a7df 100644 (file)
@@ -1,4 +1,4 @@
-//! The `Default` trait for types which may have meaningful default values.
+//! The `Default` trait for types with a default value.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 15467e0191dbf432bb8f6439c145ec412b7c196b..3d7b875eac15d1f6756e240f07a7cb484cfc8da7 100644 (file)
@@ -2209,9 +2209,9 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 ///     dst.reserve(src_len);
 ///
 ///     unsafe {
-///         // The call to offset is always safe because `Vec` will never
+///         // The call to add is always safe because `Vec` will never
 ///         // allocate more than `isize::MAX` bytes.
-///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
+///         let dst_ptr = dst.as_mut_ptr().add(dst_len);
 ///         let src_ptr = src.as_ptr();
 ///
 ///         // Truncate `src` without dropping its contents. We do this first,
index 23c46f1a74a314f9fc9f5b2fe21aaee46564b130..509a6c3cac545fc82d36416bde877b01ee419eff 100644 (file)
@@ -1,4 +1,4 @@
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type][f32].*
 //!
@@ -1282,15 +1282,14 @@ pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
-    pub fn clamp(self, min: f32, max: f32) -> f32 {
+    pub fn clamp(mut self, min: f32, max: f32) -> f32 {
         assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
+        if self < min {
+            self = min;
         }
-        if x > max {
-            x = max;
+        if self > max {
+            self = max;
         }
-        x
+        self
     }
 }
index b5c8241d2943dedebb6f21393cfb49502aadaf3b..5aeaa4b9ada441c95f6523caf09f999fb5d67a8c 100644 (file)
@@ -1,4 +1,4 @@
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type][f64].*
 //!
@@ -1280,15 +1280,14 @@ pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
-    pub fn clamp(self, min: f64, max: f64) -> f64 {
+    pub fn clamp(mut self, min: f64, max: f64) -> f64 {
         assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
+        if self < min {
+            self = min;
         }
-        if x > max {
-            x = max;
+        if self > max {
+            self = max;
         }
-        x
+        self
     }
 }
index 1c14b9341cac8e435a0cd8746f41e712d3ac8893..2b2ef64fdb1c3f31cacc27592ee7fc8f43d5d108 100644 (file)
@@ -801,11 +801,53 @@ mod prim_array {}
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
 /// ```
+///
+/// ## Trait Implementations
+///
+/// Some traits are implemented for slices if the element type implements
+/// that trait. This includes [`Eq`], [`Hash`] and [`Ord`].
+///
+/// ## Iteration
+///
+/// The slices implement `IntoIterator`. The iterator yields references to the
+/// slice elements.
+///
+/// ```
+/// let numbers: &[i32] = &[0, 1, 2];
+/// for n in numbers {
+///     println!("{n} is a number!");
+/// }
+/// ```
+///
+/// The mutable slice yields mutable references to the elements:
+///
+/// ```
+/// let mut scores: &mut [i32] = &mut [7, 8, 9];
+/// for score in scores {
+///     *score += 1;
+/// }
+/// ```
+///
+/// This iterator yields mutable references to the slice's elements, so while
+/// the element type of the slice is `i32`, the element type of the iterator is
+/// `&mut i32`.
+///
+/// * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
+///   iterators.
+/// * Further methods that return iterators are [`.split`], [`.splitn`],
+///   [`.chunks`], [`.windows`] and more.
+///
+/// [`Hash`]: core::hash::Hash
+/// [`.iter`]: slice::iter
+/// [`.iter_mut`]: slice::iter_mut
+/// [`.split`]: slice::split
+/// [`.splitn`]: slice::splitn
+/// [`.chunks`]: slice::chunks
+/// [`.windows`]: slice::windows
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
 #[doc(primitive = "str")]
-//
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -816,19 +858,22 @@ mod prim_slice {}
 ///
 /// String slices are always valid UTF-8.
 ///
-/// # Examples
+/// # Basic Usage
 ///
 /// String literals are string slices:
 ///
 /// ```
-/// let hello = "Hello, world!";
-///
-/// // with an explicit type annotation
-/// let hello: &'static str = "Hello, world!";
+/// let hello_world = "Hello, World!";
 /// ```
 ///
-/// They are `'static` because they're stored directly in the final binary, and
-/// so will be valid for the `'static` duration.
+/// Here we have declared a string slice initialized with a string literal.
+/// String literals have a static lifetime, which means the string `hello_world`
+/// is guaranteed to be valid for the duration of the entire program.
+/// We can explicitly specify `hello_world`'s lifetime as well:
+///
+/// ```
+/// let hello_world: &'static str = "Hello, world!";
+/// ```
 ///
 /// # Representation
 ///
index e79d47c9f98cdf0c234c3dafed3359104043ede5..ea6a70c2f4e741db18b951125b257e2200c75f4e 100644 (file)
@@ -674,8 +674,9 @@ pub const fn swap(&mut self, a: usize, b: usize) {
     /// assert!(v == [3, 2, 1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_reverse", issue = "100784")]
     #[inline]
-    pub fn reverse(&mut self) {
+    pub const fn reverse(&mut self) {
         let half_len = self.len() / 2;
         let Range { start, end } = self.as_mut_ptr_range();
 
@@ -698,9 +699,9 @@ pub fn reverse(&mut self) {
         revswap(front_half, back_half, half_len);
 
         #[inline]
-        fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
-            debug_assert_eq!(a.len(), n);
-            debug_assert_eq!(b.len(), n);
+        const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
+            debug_assert!(a.len() == n);
+            debug_assert!(b.len() == n);
 
             // Because this function is first compiled in isolation,
             // this check tells LLVM that the indexing below is
@@ -708,8 +709,10 @@ fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
             // lengths of the slices are known -- it's removed.
             let (a, b) = (&mut a[..n], &mut b[..n]);
 
-            for i in 0..n {
+            let mut i = 0;
+            while i < n {
                 mem::swap(&mut a[i], &mut b[n - 1 - i]);
+                i += 1;
             }
         }
     }
@@ -2921,7 +2924,7 @@ pub fn partition_dedup_by<F>(&mut self, mut same_bucket: F) -> (&mut [T], &mut [
                 let prev_ptr_write = ptr.add(next_write - 1);
                 if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) {
                     if next_read != next_write {
-                        let ptr_write = prev_ptr_write.offset(1);
+                        let ptr_write = prev_ptr_write.add(1);
                         mem::swap(&mut *ptr_read, &mut *ptr_write);
                     }
                     next_write += 1;
index 6a201834b8e688e059d106686ffbfe80906a0321..8b025da2a46ed02968b037e1fc122147500eefa0 100644 (file)
@@ -326,8 +326,8 @@ fn width<T>(l: *mut T, r: *mut T) -> usize {
                 unsafe {
                     // Branchless comparison.
                     *end_l = i as u8;
-                    end_l = end_l.offset(!is_less(&*elem, pivot) as isize);
-                    elem = elem.offset(1);
+                    end_l = end_l.add(!is_less(&*elem, pivot) as usize);
+                    elem = elem.add(1);
                 }
             }
         }
@@ -352,9 +352,9 @@ fn width<T>(l: *mut T, r: *mut T) -> usize {
                 //        Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice.
                 unsafe {
                     // Branchless comparison.
-                    elem = elem.offset(-1);
+                    elem = elem.sub(1);
                     *end_r = i as u8;
-                    end_r = end_r.offset(is_less(&*elem, pivot) as isize);
+                    end_r = end_r.add(is_less(&*elem, pivot) as usize);
                 }
             }
         }
@@ -365,12 +365,12 @@ fn width<T>(l: *mut T, r: *mut T) -> usize {
         if count > 0 {
             macro_rules! left {
                 () => {
-                    l.offset(*start_l as isize)
+                    l.add(*start_l as usize)
                 };
             }
             macro_rules! right {
                 () => {
-                    r.offset(-(*start_r as isize) - 1)
+                    r.sub((*start_r as usize) + 1)
                 };
             }
 
@@ -398,16 +398,16 @@ macro_rules! right {
                 ptr::copy_nonoverlapping(right!(), left!(), 1);
 
                 for _ in 1..count {
-                    start_l = start_l.offset(1);
+                    start_l = start_l.add(1);
                     ptr::copy_nonoverlapping(left!(), right!(), 1);
-                    start_r = start_r.offset(1);
+                    start_r = start_r.add(1);
                     ptr::copy_nonoverlapping(right!(), left!(), 1);
                 }
 
                 ptr::copy_nonoverlapping(&tmp, right!(), 1);
                 mem::forget(tmp);
-                start_l = start_l.offset(1);
-                start_r = start_r.offset(1);
+                start_l = start_l.add(1);
+                start_r = start_r.add(1);
             }
         }
 
@@ -420,7 +420,7 @@ macro_rules! right {
             // safe. Otherwise, the debug assertions in the `is_done` case guarantee that
             // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
             // for the smaller number of remaining elements.
-            l = unsafe { l.offset(block_l as isize) };
+            l = unsafe { l.add(block_l) };
         }
 
         if start_r == end_r {
@@ -428,7 +428,7 @@ macro_rules! right {
 
             // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
             // or `block_r` has been adjusted for the last handful of elements.
-            r = unsafe { r.offset(-(block_r as isize)) };
+            r = unsafe { r.sub(block_r) };
         }
 
         if is_done {
@@ -457,9 +457,9 @@ macro_rules! right {
             //  - `offsets_l` contains valid offsets into `v` collected during the partitioning of
             //    the last block, so the `l.offset` calls are valid.
             unsafe {
-                end_l = end_l.offset(-1);
-                ptr::swap(l.offset(*end_l as isize), r.offset(-1));
-                r = r.offset(-1);
+                end_l = end_l.sub(1);
+                ptr::swap(l.add(*end_l as usize), r.sub(1));
+                r = r.sub(1);
             }
         }
         width(v.as_mut_ptr(), r)
@@ -470,9 +470,9 @@ macro_rules! right {
         while start_r < end_r {
             // SAFETY: See the reasoning in [remaining-elements-safety].
             unsafe {
-                end_r = end_r.offset(-1);
-                ptr::swap(l, r.offset(-(*end_r as isize) - 1));
-                l = l.offset(1);
+                end_r = end_r.sub(1);
+                ptr::swap(l, r.sub((*end_r as usize) + 1));
+                l = l.add(1);
             }
         }
         width(v.as_mut_ptr(), l)
index 04bc665233e385dc859f466730c030cf9b64ac20..2acef432f2063a7978d7163f60e80a0b8f4d4460 100644 (file)
@@ -216,12 +216,12 @@ macro_rules! next {
                     // SAFETY: since `align - index` and `ascii_block_size` are
                     // multiples of `usize_bytes`, `block = ptr.add(index)` is
                     // always aligned with a `usize` so it's safe to dereference
-                    // both `block` and `block.offset(1)`.
+                    // both `block` and `block.add(1)`.
                     unsafe {
                         let block = ptr.add(index) as *const usize;
                         // break if there is a nonascii byte
                         let zu = contains_nonascii(*block);
-                        let zv = contains_nonascii(*block.offset(1));
+                        let zv = contains_nonascii(*block.add(1));
                         if zu || zv {
                             break;
                         }
index 40ca9abd6bdc9a5ed9b059e47d709f1d63f5ea2c..3c96290fc537e19bbe1e2b400a5eabf13ece5a0c 100644 (file)
@@ -1554,8 +1554,8 @@ pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
     /// Offsets the pointer's address by adding `val` *bytes*, returning the
     /// previous pointer.
     ///
-    /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically
-    /// perform `ptr = ptr.cast::<u8>().wrapping_add(val).cast::<T>()`.
+    /// This is equivalent to using [`wrapping_byte_add`] to atomically
+    /// perform `ptr = ptr.wrapping_byte_add(val)`.
     ///
     /// `fetch_byte_add` takes an [`Ordering`] argument which describes the
     /// memory ordering of this operation. All ordering modes are possible. Note
@@ -1565,8 +1565,7 @@ pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
     /// **Note**: This method is only available on platforms that support atomic
     /// operations on [`AtomicPtr`].
     ///
-    /// [`wrapping_add`]: pointer::wrapping_add
-    /// [`cast`]: pointer::cast
+    /// [`wrapping_byte_add`]: pointer::wrapping_byte_add
     ///
     /// # Examples
     ///
@@ -1591,8 +1590,8 @@ pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
     /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
     /// previous pointer.
     ///
-    /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically
-    /// perform `ptr = ptr.cast::<u8>().wrapping_sub(val).cast::<T>()`.
+    /// This is equivalent to using [`wrapping_byte_sub`] to atomically
+    /// perform `ptr = ptr.wrapping_byte_sub(val)`.
     ///
     /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the
     /// memory ordering of this operation. All ordering modes are possible. Note
@@ -1602,8 +1601,7 @@ pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
     /// **Note**: This method is only available on platforms that support atomic
     /// operations on [`AtomicPtr`].
     ///
-    /// [`wrapping_sub`]: pointer::wrapping_sub
-    /// [`cast`]: pointer::cast
+    /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub
     ///
     /// # Examples
     ///
index 18bb932f10ea94f31dce137097bbdd16c2619ff8..0fd824f8a458da3f19d77899e6aea18bd282f96f 100644 (file)
@@ -42,7 +42,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
         return; // allocation failure
     }
     copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len());
-    buf.offset(msg.len() as isize).write(0);
+    buf.add(msg.len()).write(0);
 
     let func = transmute::<usize, SetAbortMessageType>(func_addr);
     func(buf);
index 7394feab82f223c7161bdcd8ebe475eda730ebe9..9aa966b5063b1a0f91492db0deac919a026a2f28 100644 (file)
@@ -75,7 +75,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
 
     let call_site_encoding = reader.read::<u8>();
     let call_site_table_length = reader.read_uleb128();
-    let action_table = reader.ptr.offset(call_site_table_length as isize);
+    let action_table = reader.ptr.add(call_site_table_length as usize);
     let ip = context.ip;
 
     if !USING_SJLJ_EXCEPTIONS {
index df7a49d258282488ff8e1e8e54d13da68bdb0f61..4fbcfd85d7c04060cf8612577c32709eecc154ed 100644 (file)
@@ -1,4 +1,4 @@
-//! Interfaces for working with Errors.
+//! The `Error` trait provides common functionality for errors.
 //!
 //! # Error Handling In Rust
 //!
index 933b52b4dccbb2b4d810b0485a7279590f6aa18a..3dd5b12507fb2b136692e8e7220fda047d4fb261 100644 (file)
@@ -1,4 +1,4 @@
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type](primitive@f32).*
 //!
index a9aa84f70d19e08fcc4341a2a52ffb984afe43d4..31351a87978c918dcaec443c092ef60b5b853272 100644 (file)
@@ -1,4 +1,4 @@
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type](primitive@f64).*
 //!
index a0a5c003d281ad394403ebb1b5d1e74e33beb920..80ed34157e6dcd24b221c81a9dd50a12827dc892 100644 (file)
@@ -290,7 +290,8 @@ pub fn reserve(&mut self, additional: usize) {
     /// in the given `OsString`. The string may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
-    /// Does nothing if capacity is already sufficient.
+    /// Does nothing if capacity is already sufficient. This method preserves
+    /// the contents even if an error occurs.
     ///
     /// See the main `OsString` documentation information about encoding and capacity units.
     ///
index 189754a161e71860dba0614ad0e150fa040a8599..6004810655ebb65ac9c2c725eb7cb767357b1730 100644 (file)
@@ -620,25 +620,31 @@ pub const fn is_link_local(&self) -> bool {
         matches!(self.octets(), [169, 254, ..])
     }
 
-    /// Returns [`true`] if the address appears to be globally routable.
-    /// See [iana-ipv4-special-registry][ipv4-sr].
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
+    ///
+    /// Most IPv4 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
     ///
-    /// The following return [`false`]:
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
     ///
-    /// - private addresses (see [`Ipv4Addr::is_private()`])
-    /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
-    /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
-    /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
-    /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
-    /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
-    ///   `0.0.0.0/8` block
-    /// - addresses reserved for future protocols, except
-    /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
-    /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
-    /// - addresses reserved for networking devices benchmarking (see
-    /// [`Ipv4Addr::is_benchmarking()`])
+    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
+    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
+    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
+    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
+    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
+    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
+    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
+    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
     ///
-    /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
+    ///
+    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+    /// [unspecified address]: Ipv4Addr::UNSPECIFIED
+    /// [broadcast address]: Ipv4Addr::BROADCAST
+
     ///
     /// # Examples
     ///
@@ -647,71 +653,61 @@ pub const fn is_link_local(&self) -> bool {
     ///
     /// use std::net::Ipv4Addr;
     ///
-    /// // private addresses are not global
+    /// // Most IPv4 addresses are globally reachable:
+    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`0.0.0.0`)
+    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
     /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
     ///
-    /// // the 0.0.0.0/8 block is not global
-    /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
-    /// // in particular, the unspecified address is not global
-    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+    /// // Addresses in the shared address space (`100.64.0.0/10`)
+    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
     ///
-    /// // the loopback address is not global
-    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+    /// // The loopback addresses (`127.0.0.0/8`)
+    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
     ///
-    /// // link local addresses are not global
+    /// // Link-local addresses (`169.254.0.0/16`)
     /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
     ///
-    /// // the broadcast address is not global
-    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
-    ///
-    /// // the address space designated for documentation is not global
+    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
     ///
-    /// // shared addresses are not global
-    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
-    ///
-    /// // addresses reserved for protocol assignment are not global
-    /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+    /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
+    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
     ///
-    /// // addresses reserved for future use are not global
+    /// // Reserved addresses (`240.0.0.0/4`)
     /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
     ///
-    /// // addresses reserved for network devices benchmarking are not global
-    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+    /// // The broadcast address (`255.255.255.255`)
+    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
     ///
-    /// // All the other addresses are global
-    /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
-    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[unstable(feature = "ip", issue = "27709")]
     #[must_use]
     #[inline]
     pub const fn is_global(&self) -> bool {
-        // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
-        // globally routable addresses in the 192.0.0.0/24 range.
-        if u32::from_be_bytes(self.octets()) == 0xc0000009
-            || u32::from_be_bytes(self.octets()) == 0xc000000a
-        {
-            return true;
-        }
-        !self.is_private()
-            && !self.is_loopback()
-            && !self.is_link_local()
-            && !self.is_broadcast()
-            && !self.is_documentation()
-            && !self.is_shared()
+        !(self.octets()[0] == 0 // "This network"
+            || self.is_private()
+            || self.is_shared()
+            || self.is_loopback()
+            || self.is_link_local()
             // addresses reserved for future protocols (`192.0.0.0/24`)
-            && !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
-            && !self.is_reserved()
-            && !self.is_benchmarking()
-            // Make sure the address is not in 0.0.0.0/8
-            && self.octets()[0] != 0
+            ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+            || self.is_documentation()
+            || self.is_benchmarking()
+            || self.is_reserved()
+            || self.is_broadcast())
     }
 
     /// Returns [`true`] if this address is part of the Shared Address Space defined in
@@ -1300,13 +1296,33 @@ pub const fn is_loopback(&self) -> bool {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
     }
 
-    /// Returns [`true`] if the address appears to be globally routable.
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
     ///
-    /// The following return [`false`]:
+    /// Most IPv6 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
     ///
-    /// - the loopback address
-    /// - link-local and unique local unicast addresses
-    /// - interface-, link-, realm-, admin- and site-local multicast addresses
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
+    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
+    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
+    /// - IPv4-mapped addresses
+    /// - Addresses reserved for benchmarking
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
+    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
+    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
+    ///
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
+    ///
+    /// Note that an address having global scope is not the same as being globally reachable,
+    /// and there is no direct relation between the two concepts: There exist addresses with global scope
+    /// that are not globally reachable (for example unique local addresses),
+    /// and addresses that are globally reachable without having global scope
+    /// (multicast addresses with non-global scope).
+    ///
+    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+    /// [unspecified address]: Ipv6Addr::UNSPECIFIED
+    /// [loopback address]: Ipv6Addr::LOCALHOST
     ///
     /// # Examples
     ///
@@ -1315,20 +1331,65 @@ pub const fn is_loopback(&self) -> bool {
     ///
     /// use std::net::Ipv6Addr;
     ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
+    /// // Most IPv6 addresses are globally reachable:
+    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`::`)
+    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // The loopback address (`::1`)
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
+    ///
+    /// // IPv4-mapped addresses (`::ffff:0:0/96`)
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
+    ///
+    /// // Addresses reserved for benchmarking (`2001:2::/48`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
+    ///
+    /// // Addresses reserved for documentation (`2001:db8::/32`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unique local addresses (`fc00::/7`)
+    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unicast addresses with link-local scope (`fe80::/10`)
+    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
     #[unstable(feature = "ip", issue = "27709")]
     #[must_use]
     #[inline]
     pub const fn is_global(&self) -> bool {
-        match self.multicast_scope() {
-            Some(Ipv6MulticastScope::Global) => true,
-            None => self.is_unicast_global(),
-            _ => false,
-        }
+        !(self.is_unspecified()
+            || self.is_loopback()
+            // IPv4-mapped Address (`::ffff:0:0/96`)
+            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
+            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
+            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
+            // Discard-Only Address Block (`100::/64`)
+            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
+            // IETF Protocol Assignments (`2001::/23`)
+            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
+                && !(
+                    // Port Control Protocol Anycast (`2001:1::1`)
+                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
+                    // Traversal Using Relays around NAT Anycast (`2001:1::2`)
+                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
+                    // AMT (`2001:3::/32`)
+                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
+                    // AS112-v6 (`2001:4:112::/48`)
+                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
+                    // ORCHIDv2 (`2001:20::/28`)
+                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
+                ))
+            || self.is_documentation()
+            || self.is_unique_local()
+            || self.is_unicast_link_local())
     }
 
     /// Returns [`true`] if this is a unique local address (`fc00::/7`).
@@ -1525,6 +1586,7 @@ pub const fn is_unicast_global(&self) -> bool {
             && !self.is_unique_local()
             && !self.is_unspecified()
             && !self.is_documentation()
+            && !self.is_benchmarking()
     }
 
     /// Returns the address's multicast scope if the address is multicast.
index c29509331d7a9eaa13fdad6e9c85463bdd22c8f2..7c3430b2b217c5b838e22a63bf3511e846bc0f56 100644 (file)
@@ -321,15 +321,15 @@ macro_rules! check {
     check!("fe80:ffff::");
     check!("febf:ffff::");
     check!("fec0::", global);
-    check!("ff01::", multicast);
-    check!("ff02::", multicast);
-    check!("ff03::", multicast);
-    check!("ff04::", multicast);
-    check!("ff05::", multicast);
-    check!("ff08::", multicast);
+    check!("ff01::", global | multicast);
+    check!("ff02::", global | multicast);
+    check!("ff03::", global | multicast);
+    check!("ff04::", global | multicast);
+    check!("ff05::", global | multicast);
+    check!("ff08::", global | multicast);
     check!("ff0e::", global | multicast);
     check!("2001:db8:85a3::8a2e:370:7334", doc);
-    check!("2001:2::ac32:23ff:21", global | benchmarking);
+    check!("2001:2::ac32:23ff:21", benchmarking);
     check!("102:304:506:708:90a:b0c:d0e:f10", global);
 }
 
@@ -609,6 +609,60 @@ macro_rules! check {
 
     check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
 
+    check!(
+        "::ffff:127.0.0.1",
+        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
+        unicast_global
+    );
+
+    check!(
+        "64:ff9b:1::",
+        &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_global
+    );
+
+    check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:1::1",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:1::2",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:3::",
+        &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:4:112::",
+        &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:20::",
+        &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:200::",
+        &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
     check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
 
     check!(
@@ -666,21 +720,37 @@ macro_rules! check {
     check!(
         "ff01::",
         &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_interface_local
+        multicast_interface_local | global
     );
 
-    check!("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_link_local);
+    check!(
+        "ff02::",
+        &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_link_local | global
+    );
 
-    check!("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_realm_local);
+    check!(
+        "ff03::",
+        &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_realm_local | global
+    );
 
-    check!("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_admin_local);
+    check!(
+        "ff04::",
+        &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_admin_local | global
+    );
 
-    check!("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_site_local);
+    check!(
+        "ff05::",
+        &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_site_local | global
+    );
 
     check!(
         "ff08::",
         &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_organization_local
+        multicast_organization_local | global
     );
 
     check!(
@@ -698,7 +768,7 @@ macro_rules! check {
     check!(
         "2001:2::ac32:23ff:21",
         &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
-        global | unicast_global | benchmarking
+        benchmarking
     );
 
     check!(
index 9aeae4b2cae691f1a578fa69ffb80337de5f92e7..bb313c7597b6c87991a6da351698de7543e1a437 100644 (file)
@@ -329,7 +329,7 @@ pub fn from_abstract_namespace(namespace: &[u8]) -> io::Result<SocketAddr> {
 
             crate::ptr::copy_nonoverlapping(
                 namespace.as_ptr(),
-                addr.sun_path.as_mut_ptr().offset(1) as *mut u8,
+                addr.sun_path.as_mut_ptr().add(1) as *mut u8,
                 namespace.len(),
             );
             let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t;
index 1c14b9341cac8e435a0cd8746f41e712d3ac8893..2b2ef64fdb1c3f31cacc27592ee7fc8f43d5d108 100644 (file)
@@ -801,11 +801,53 @@ mod prim_array {}
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
 /// ```
+///
+/// ## Trait Implementations
+///
+/// Some traits are implemented for slices if the element type implements
+/// that trait. This includes [`Eq`], [`Hash`] and [`Ord`].
+///
+/// ## Iteration
+///
+/// The slices implement `IntoIterator`. The iterator yields references to the
+/// slice elements.
+///
+/// ```
+/// let numbers: &[i32] = &[0, 1, 2];
+/// for n in numbers {
+///     println!("{n} is a number!");
+/// }
+/// ```
+///
+/// The mutable slice yields mutable references to the elements:
+///
+/// ```
+/// let mut scores: &mut [i32] = &mut [7, 8, 9];
+/// for score in scores {
+///     *score += 1;
+/// }
+/// ```
+///
+/// This iterator yields mutable references to the slice's elements, so while
+/// the element type of the slice is `i32`, the element type of the iterator is
+/// `&mut i32`.
+///
+/// * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
+///   iterators.
+/// * Further methods that return iterators are [`.split`], [`.splitn`],
+///   [`.chunks`], [`.windows`] and more.
+///
+/// [`Hash`]: core::hash::Hash
+/// [`.iter`]: slice::iter
+/// [`.iter_mut`]: slice::iter_mut
+/// [`.split`]: slice::split
+/// [`.splitn`]: slice::splitn
+/// [`.chunks`]: slice::chunks
+/// [`.windows`]: slice::windows
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
 #[doc(primitive = "str")]
-//
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -816,19 +858,22 @@ mod prim_slice {}
 ///
 /// String slices are always valid UTF-8.
 ///
-/// # Examples
+/// # Basic Usage
 ///
 /// String literals are string slices:
 ///
 /// ```
-/// let hello = "Hello, world!";
-///
-/// // with an explicit type annotation
-/// let hello: &'static str = "Hello, world!";
+/// let hello_world = "Hello, World!";
 /// ```
 ///
-/// They are `'static` because they're stored directly in the final binary, and
-/// so will be valid for the `'static` duration.
+/// Here we have declared a string slice initialized with a string literal.
+/// String literals have a static lifetime, which means the string `hello_world`
+/// is guaranteed to be valid for the duration of the entire program.
+/// We can explicitly specify `hello_world`'s lifetime as well:
+///
+/// ```
+/// let hello_world: &'static str = "Hello, world!";
+/// ```
 ///
 /// # Representation
 ///
index d6cba7e7598f682be946c0446fcbc42f67ce2186..d91d4fa64caa587300380f2ec6b689c5f7d17a3a 100644 (file)
 pub struct Child {
     pub(crate) handle: imp::Process,
 
-    /// The handle for writing to the child's standard input (stdin), if it has
-    /// been captured. To avoid partially moving
-    /// the `child` and thus blocking yourself from calling
-    /// functions on `child` while using `stdin`,
-    /// you might find it helpful:
+    /// The handle for writing to the child's standard input (stdin), if it
+    /// has been captured. You might find it helpful to do
     ///
     /// ```compile_fail,E0425
     /// let stdin = child.stdin.take().unwrap();
     /// ```
+    ///
+    /// to avoid partially moving the `child` and thus blocking yourself from calling
+    /// functions on `child` while using `stdin`.
     #[stable(feature = "process", since = "1.0.0")]
     pub stdin: Option<ChildStdin>,
 
index 4320f0bccd199b99b3301393508b04e56a74e0d8..58b8eb215d73cc97fe29f4342d050ac5ffc5d8e8 100644 (file)
@@ -17,12 +17,12 @@ fn test_copy_to_userspace_function() {
             dst.copy_from_enclave(&[0u8; 100]);
 
             // Copy src[0..size] to dst + offset
-            unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().offset(offset), size) };
+            unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().add(offset), size) };
 
             // Verify copy
             for byte in 0..size {
                 unsafe {
-                    assert_eq!(*dst.as_ptr().offset(offset + byte as isize), src[byte as usize]);
+                    assert_eq!(*dst.as_ptr().add(offset + byte), src[byte as usize]);
                 }
             }
         }
index fdc81cdea7dec36fcb690dabffb4d88dc4d6f246..fe00c08aa6a9ae19c15d7035bd65624587a6fed6 100644 (file)
@@ -168,7 +168,7 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
         // SAFETY: Because the size and alignment of a header is <= `MIN_ALIGN` and `aligned`
         // is aligned to at least `MIN_ALIGN` and has at least `MIN_ALIGN` bytes of padding before
         // it, it is safe to write a header directly before it.
-        unsafe { ptr::write((aligned as *mut Header).offset(-1), Header(ptr)) };
+        unsafe { ptr::write((aligned as *mut Header).sub(1), Header(ptr)) };
 
         // SAFETY: The returned pointer does not point to the to the start of an allocated block,
         // but there is a header readable directly before it containing the location of the start
@@ -213,7 +213,7 @@ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
 
                 // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null
                 // and have a header readable directly before it.
-                unsafe { ptr::read((ptr as *mut Header).offset(-1)).0 }
+                unsafe { ptr::read((ptr as *mut Header).sub(1)).0 }
             }
         };
 
index aed082b3e0abf9919cd045d9fd9a700a22e40348..1361b9c90c021879e2cc097ae5437fcf47278dc5 100644 (file)
@@ -512,7 +512,7 @@ fn readlink(&self) -> io::Result<PathBuf> {
                     ));
                 }
             };
-            let subst_ptr = path_buffer.offset(subst_off as isize);
+            let subst_ptr = path_buffer.add(subst_off.into());
             let mut subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
             // Absolute paths start with an NT internal namespace prefix `\??\`
             // We should not let it leak through.
@@ -1345,10 +1345,10 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
         let v = br"\??\";
         let v = v.iter().map(|x| *x as u16);
         for c in v.chain(original.as_os_str().encode_wide()) {
-            *buf.offset(i) = c;
+            *buf.add(i) = c;
             i += 1;
         }
-        *buf.offset(i) = 0;
+        *buf.add(i) = 0;
         i += 1;
         (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
         (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD;
index bcac996c024ec34fe84d70b249b22082e68a44ac..352337ba322371d77b89aedc5d1a7cc756351f0d 100644 (file)
@@ -99,11 +99,11 @@ fn next(&mut self) -> Option<(OsString, OsString)> {
                 }
                 let p = self.cur as *const u16;
                 let mut len = 0;
-                while *p.offset(len) != 0 {
+                while *p.add(len) != 0 {
                     len += 1;
                 }
-                let s = slice::from_raw_parts(p, len as usize);
-                self.cur = self.cur.offset(len + 1);
+                let s = slice::from_raw_parts(p, len);
+                self.cur = self.cur.add(len + 1);
 
                 // Windows allows environment variables to start with an equals
                 // symbol (in any other position, this is the separator between
index 57fa4989358a4f5d880aa142a6dcfdf907693610..33e20756163fd8761989eb9cf209053909575ed5 100644 (file)
@@ -236,7 +236,8 @@ pub fn reserve(&mut self, additional: usize) {
     /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
+    /// capacity is already sufficient. This method preserves the contents even
+    /// if an error occurs.
     ///
     /// # Errors
     ///
index a94520b121926e254adfe628c76a889063ea4783..5441a7bd29ec00624512afd0681506dedc4a8e74 100644 (file)
@@ -551,13 +551,15 @@ fn param_env_to_generics(
                 }
                 WherePredicate::EqPredicate { lhs, rhs } => {
                     match lhs {
-                        Type::QPath { ref assoc, ref self_type, ref trait_, .. } => {
+                        Type::QPath(box QPathData {
+                            ref assoc, ref self_type, ref trait_, ..
+                        }) => {
                             let ty = &*self_type;
                             let mut new_trait = trait_.clone();
 
                             if self.is_fn_trait(trait_) && assoc.name == sym::Output {
                                 ty_to_fn
-                                    .entry(*ty.clone())
+                                    .entry(ty.clone())
                                     .and_modify(|e| {
                                         *e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
                                     })
@@ -582,7 +584,7 @@ fn param_env_to_generics(
                                 // to 'T: Iterator<Item=u8>'
                                 GenericArgs::AngleBracketed { ref mut bindings, .. } => {
                                     bindings.push(TypeBinding {
-                                        assoc: *assoc.clone(),
+                                        assoc: assoc.clone(),
                                         kind: TypeBindingKind::Equality { term: rhs },
                                     });
                                 }
@@ -596,7 +598,7 @@ fn param_env_to_generics(
                                 }
                             }
 
-                            let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
+                            let bounds = ty_to_bounds.entry(ty.clone()).or_default();
 
                             bounds.insert(GenericBound::TraitBound(
                                 PolyTrait { trait_: new_trait, generic_params: Vec::new() },
@@ -613,7 +615,7 @@ fn param_env_to_generics(
                             ));
                             // Avoid creating any new duplicate bounds later in the outer
                             // loop
-                            ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone());
+                            ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone());
                         }
                         _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
                     }
index e56a715e85780668e0a0a5915390d5c320300a35..a7048e788b65abb5aa9e939167439208c077cf1a 100644 (file)
@@ -62,7 +62,7 @@ pub(crate) fn try_inline(
         Res::Def(DefKind::Trait, did) => {
             record_extern_fqn(cx, did, ItemType::Trait);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
-            clean::TraitItem(build_external_trait(cx, did))
+            clean::TraitItem(Box::new(build_external_trait(cx, did)))
         }
         Res::Def(DefKind::Fn, did) => {
             record_extern_fqn(cx, did, ItemType::Function);
@@ -672,7 +672,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
 
     g.where_predicates.retain(|pred| match pred {
         clean::WherePredicate::BoundPredicate {
-            ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. },
+            ty: clean::QPath(box clean::QPathData { self_type: clean::Generic(ref s), trait_, .. }),
             bounds,
             ..
         } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
index 971617a8400366d732e86d9d614870289b295234..5507ffb871b6ea25818b11098fb0648867aeb313 100644 (file)
@@ -410,12 +410,12 @@ fn clean_projection<'tcx>(
         self_type.def_id(&cx.cache)
     };
     let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
-    Type::QPath {
-        assoc: Box::new(projection_to_path_segment(ty, cx)),
+    Type::QPath(Box::new(QPathData {
+        assoc: projection_to_path_segment(ty, cx),
         should_show_cast,
-        self_type: Box::new(self_type),
+        self_type,
         trait_,
-    }
+    }))
 }
 
 fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
@@ -1182,7 +1182,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                     .where_predicates
                     .drain_filter(|pred| match *pred {
                         WherePredicate::BoundPredicate {
-                            ty: QPath { ref assoc, ref self_type, ref trait_, .. },
+                            ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }),
                             ..
                         } => {
                             if assoc.name != my_name {
@@ -1191,7 +1191,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
                             if trait_.def_id() != assoc_item.container_id(tcx) {
                                 return false;
                             }
-                            match **self_type {
+                            match *self_type {
                                 Generic(ref s) if *s == kw::SelfUpper => {}
                                 _ => return false,
                             }
@@ -1324,15 +1324,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
             let self_type = clean_ty(qself, cx);
             let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
-            Type::QPath {
-                assoc: Box::new(clean_path_segment(
-                    p.segments.last().expect("segments were empty"),
-                    cx,
-                )),
+            Type::QPath(Box::new(QPathData {
+                assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
                 should_show_cast,
-                self_type: Box::new(self_type),
+                self_type,
                 trait_,
-            }
+            }))
         }
         hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
@@ -1347,12 +1344,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             let self_def_id = res.opt_def_id();
             let self_type = clean_ty(qself, cx);
             let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
-            Type::QPath {
-                assoc: Box::new(clean_path_segment(segment, cx)),
+            Type::QPath(Box::new(QPathData {
+                assoc: clean_path_segment(segment, cx),
                 should_show_cast,
-                self_type: Box::new(self_type),
+                self_type,
                 trait_,
-            }
+            }))
         }
         hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
     }
@@ -1954,12 +1951,12 @@ fn clean_maybe_renamed_item<'tcx>(
                     .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
                     .collect();
 
-                TraitItem(Trait {
+                TraitItem(Box::new(Trait {
                     def_id,
                     items,
                     generics: clean_generics(generics, cx),
                     bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
-                })
+                }))
             }
             ItemKind::ExternCrate(orig_name) => {
                 return clean_extern_crate(item, name, orig_name, cx);
index 2a38713d43b8a082e025f6a4dc5938a99b354918..4c39021903c5b185790b2ed7e53b5817d69f362e 100644 (file)
@@ -727,7 +727,7 @@ pub(crate) enum ItemKind {
     OpaqueTyItem(OpaqueTy),
     StaticItem(Static),
     ConstantItem(Constant),
-    TraitItem(Trait),
+    TraitItem(Box<Trait>),
     TraitAliasItem(TraitAlias),
     ImplItem(Box<Impl>),
     /// A required method in a trait declaration meaning it's only a function signature.
@@ -1130,7 +1130,7 @@ pub struct RenderedLink {
 #[derive(Clone, Debug, Default)]
 pub(crate) struct Attributes {
     pub(crate) doc_strings: Vec<DocFragment>,
-    pub(crate) other_attrs: Vec<ast::Attribute>,
+    pub(crate) other_attrs: ast::AttrVec,
 }
 
 impl Attributes {
@@ -1173,7 +1173,7 @@ pub(crate) fn from_ast_iter<'a>(
         doc_only: bool,
     ) -> Attributes {
         let mut doc_strings = Vec::new();
-        let mut other_attrs = Vec::new();
+        let mut other_attrs = ast::AttrVec::new();
         for (attr, parent_module) in attrs {
             if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
                 trace!("got doc_str={doc_str:?}");
@@ -1550,13 +1550,7 @@ pub(crate) enum Type {
     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
 
     /// A qualified path to an associated item: `<Type as Trait>::Name`
-    QPath {
-        assoc: Box<PathSegment>,
-        self_type: Box<Type>,
-        /// FIXME: compute this field on demand.
-        should_show_cast: bool,
-        trait_: Path,
-    },
+    QPath(Box<QPathData>),
 
     /// A type that is inferred: `_`
     Infer,
@@ -1654,8 +1648,8 @@ pub(crate) fn is_impl_trait(&self) -> bool {
     }
 
     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
-        if let QPath { self_type, trait_, assoc, .. } = self {
-            Some((self_type, trait_.def_id(), *assoc.clone()))
+        if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
+            Some((self_type, trait_.def_id(), assoc.clone()))
         } else {
             None
         }
@@ -1679,7 +1673,7 @@ fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
             Slice(..) => PrimitiveType::Slice,
             Array(..) => PrimitiveType::Array,
             RawPointer(..) => PrimitiveType::RawPointer,
-            QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
+            QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
             Generic(_) | Infer | ImplTrait(_) => return None,
         };
         cache.and_then(|c| Primitive(t).def_id(c))
@@ -1693,6 +1687,15 @@ pub(crate) fn def_id(&self, cache: &Cache) -> Option<DefId> {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub(crate) struct QPathData {
+    pub assoc: PathSegment,
+    pub self_type: Type,
+    /// FIXME: compute this field on demand.
+    pub should_show_cast: bool,
+    pub trait_: Path,
+}
+
 /// A primitive (aka, builtin) type.
 ///
 /// This represents things like `i32`, `str`, etc.
@@ -2484,11 +2487,11 @@ mod size_asserts {
     // These are in alphabetical order, which is easy to maintain.
     static_assert_size!(Crate, 72); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
-    static_assert_size!(GenericArg, 80);
+    static_assert_size!(GenericArg, 64);
     static_assert_size!(GenericArgs, 32);
     static_assert_size!(GenericParamDef, 56);
     static_assert_size!(Item, 56);
-    static_assert_size!(ItemKind, 112);
+    static_assert_size!(ItemKind, 96);
     static_assert_size!(PathSegment, 40);
-    static_assert_size!(Type, 72);
+    static_assert_size!(Type, 56);
 }
index 2b2691e53bbcc900a01f2297a2f44dc82992f5cc..86392610d2c28cb36fbb0608d1fd325443791f20 100644 (file)
@@ -227,7 +227,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         if let clean::TraitItem(ref t) = *item.kind {
             self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
                 clean::TraitWithExtraInfo {
-                    trait_: t.clone(),
+                    trait_: *t.clone(),
                     is_notable: item.attrs.has_doc_flag(sym::notable_trait),
                 }
             });
index 3dee4d1acc819f4a5ac7fcbdfda502cffe64e1d2..b023792e95a58e4292478c2db0eab95a010eec27 100644 (file)
@@ -1079,7 +1079,12 @@ fn fmt_type<'cx>(
                 write!(f, "impl {}", print_generic_bounds(bounds, cx))
             }
         }
-        clean::QPath { ref assoc, ref self_type, ref trait_, should_show_cast } => {
+        clean::QPath(box clean::QPathData {
+            ref assoc,
+            ref self_type,
+            ref trait_,
+            should_show_cast,
+        }) => {
             if f.alternate() {
                 if should_show_cast {
                     write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
index 9d8ee52a3faf861d3609f615427a6475eb7b996f..4a12d74ddef5a5844dd89255ed451eee1f43e7af 100644 (file)
@@ -111,53 +111,6 @@ fn write_header(out: &mut Buffer, class: &str, extra_content: Option<Buffer>) {
     write!(out, "<code>");
 }
 
-/// Write all the pending elements sharing a same (or at mergeable) `Class`.
-///
-/// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged
-/// with the elements' class, then we simply write the elements since the `ExitSpan` event will
-/// close the tag.
-///
-/// Otherwise, if there is only one pending element, we let the `string` function handle both
-/// opening and closing the tag, otherwise we do it into this function.
-fn write_pending_elems(
-    out: &mut Buffer,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
-    pending_elems: &mut Vec<(&str, Option<Class>)>,
-    current_class: &mut Option<Class>,
-    closing_tags: &[(&str, Class)],
-) {
-    if pending_elems.is_empty() {
-        return;
-    }
-    let mut done = false;
-    if let Some((_, parent_class)) = closing_tags.last() {
-        if can_merge(*current_class, Some(*parent_class), "") {
-            for (text, class) in pending_elems.iter() {
-                string(out, Escape(text), *class, &href_context, false);
-            }
-            done = true;
-        }
-    }
-    if !done {
-        // We only want to "open" the tag ourselves if we have more than one pending and if the current
-        // parent tag is not the same as our pending content.
-        let open_tag_ourselves = pending_elems.len() > 1;
-        let close_tag = if open_tag_ourselves {
-            enter_span(out, current_class.unwrap(), &href_context)
-        } else {
-            ""
-        };
-        for (text, class) in pending_elems.iter() {
-            string(out, Escape(text), *class, &href_context, !open_tag_ourselves);
-        }
-        if open_tag_ourselves {
-            exit_span(out, close_tag);
-        }
-    }
-    pending_elems.clear();
-    *current_class = None;
-}
-
 /// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None`
 /// basically (since it's `Option<Class>`). The following rules apply:
 ///
@@ -171,7 +124,88 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
         (Some(c1), Some(c2)) => c1.is_equal_to(c2),
         (Some(Class::Ident(_)), None) | (None, Some(Class::Ident(_))) => true,
         (Some(_), None) | (None, Some(_)) => text.trim().is_empty(),
-        _ => false,
+        (None, None) => true,
+    }
+}
+
+/// This type is used as a conveniency to prevent having to pass all its fields as arguments into
+/// the various functions (which became its methods).
+struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    out: &'a mut Buffer,
+    /// It contains the closing tag and the associated `Class`.
+    closing_tags: Vec<(&'static str, Class)>,
+    /// This is used because we don't automatically generate the closing tag on `ExitSpan` in
+    /// case an `EnterSpan` event with the same class follows.
+    pending_exit_span: Option<Class>,
+    /// `current_class` and `pending_elems` are used to group HTML elements with same `class`
+    /// attributes to reduce the DOM size.
+    current_class: Option<Class>,
+    /// We need to keep the `Class` for each element because it could contain a `Span` which is
+    /// used to generate links.
+    pending_elems: Vec<(&'b str, Option<Class>)>,
+    href_context: Option<HrefContext<'c, 'd, 'e>>,
+}
+
+impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    fn handle_exit_span(&mut self) {
+        // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
+        // being used in `write_pending_elems`.
+        let class = self.closing_tags.last().expect("ExitSpan without EnterSpan").1;
+        // We flush everything just in case...
+        self.write_pending_elems(Some(class));
+
+        exit_span(self.out, self.closing_tags.pop().expect("ExitSpan without EnterSpan").0);
+        self.pending_exit_span = None;
+    }
+
+    /// Write all the pending elements sharing a same (or at mergeable) `Class`.
+    ///
+    /// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged
+    /// with the elements' class, then we simply write the elements since the `ExitSpan` event will
+    /// close the tag.
+    ///
+    /// Otherwise, if there is only one pending element, we let the `string` function handle both
+    /// opening and closing the tag, otherwise we do it into this function.
+    ///
+    /// It returns `true` if `current_class` must be set to `None` afterwards.
+    fn write_pending_elems(&mut self, current_class: Option<Class>) -> bool {
+        if self.pending_elems.is_empty() {
+            return false;
+        }
+        if let Some((_, parent_class)) = self.closing_tags.last() &&
+            can_merge(current_class, Some(*parent_class), "")
+        {
+            for (text, class) in self.pending_elems.iter() {
+                string(self.out, Escape(text), *class, &self.href_context, false);
+            }
+        } else {
+            // We only want to "open" the tag ourselves if we have more than one pending and if the
+            // current parent tag is not the same as our pending content.
+            let close_tag = if self.pending_elems.len() > 1 && current_class.is_some() {
+                Some(enter_span(self.out, current_class.unwrap(), &self.href_context))
+            } else {
+                None
+            };
+            for (text, class) in self.pending_elems.iter() {
+                string(self.out, Escape(text), *class, &self.href_context, close_tag.is_none());
+            }
+            if let Some(close_tag) = close_tag {
+                exit_span(self.out, close_tag);
+            }
+        }
+        self.pending_elems.clear();
+        true
+    }
+}
+
+impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    /// When leaving, we need to flush all pending data to not have missing content.
+    fn drop(&mut self) {
+        if self.pending_exit_span.is_some() {
+            self.handle_exit_span();
+        } else {
+            self.write_pending_elems(self.current_class);
+        }
     }
 }
 
@@ -194,64 +228,72 @@ fn write_code(
 ) {
     // This replace allows to fix how the code source with DOS backline characters is displayed.
     let src = src.replace("\r\n", "\n");
-    // It contains the closing tag and the associated `Class`.
-    let mut closing_tags: Vec<(&'static str, Class)> = Vec::new();
-    // The following two variables are used to group HTML elements with same `class` attributes
-    // to reduce the DOM size.
-    let mut current_class: Option<Class> = None;
-    // We need to keep the `Class` for each element because it could contain a `Span` which is
-    // used to generate links.
-    let mut pending_elems: Vec<(&str, Option<Class>)> = Vec::new();
+    let mut token_handler = TokenHandler {
+        out,
+        closing_tags: Vec::new(),
+        pending_exit_span: None,
+        current_class: None,
+        pending_elems: Vec::new(),
+        href_context,
+    };
 
     Classifier::new(
         &src,
-        href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
+        token_handler.href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
         decoration_info,
     )
     .highlight(&mut |highlight| {
         match highlight {
             Highlight::Token { text, class } => {
+                // If we received a `ExitSpan` event and then have a non-compatible `Class`, we
+                // need to close the `<span>`.
+                let need_current_class_update = if let Some(pending) = token_handler.pending_exit_span &&
+                    !can_merge(Some(pending), class, text) {
+                        token_handler.handle_exit_span();
+                        true
                 // If the two `Class` are different, time to flush the current content and start
                 // a new one.
-                if !can_merge(current_class, class, text) {
-                    write_pending_elems(
-                        out,
-                        &href_context,
-                        &mut pending_elems,
-                        &mut current_class,
-                        &closing_tags,
-                    );
-                    current_class = class.map(Class::dummy);
-                } else if current_class.is_none() {
-                    current_class = class.map(Class::dummy);
+                } else if !can_merge(token_handler.current_class, class, text) {
+                    token_handler.write_pending_elems(token_handler.current_class);
+                    true
+                } else {
+                    token_handler.current_class.is_none()
+                };
+
+                if need_current_class_update {
+                    token_handler.current_class = class.map(Class::dummy);
                 }
-                pending_elems.push((text, class));
+                token_handler.pending_elems.push((text, class));
             }
             Highlight::EnterSpan { class } => {
-                // We flush everything just in case...
-                write_pending_elems(
-                    out,
-                    &href_context,
-                    &mut pending_elems,
-                    &mut current_class,
-                    &closing_tags,
-                );
-                closing_tags.push((enter_span(out, class, &href_context), class))
+                let mut should_add = true;
+                if let Some(pending_exit_span) = token_handler.pending_exit_span {
+                    if class.is_equal_to(pending_exit_span) {
+                        should_add = false;
+                    } else {
+                        token_handler.handle_exit_span();
+                    }
+                } else {
+                    // We flush everything just in case...
+                    if token_handler.write_pending_elems(token_handler.current_class) {
+                        token_handler.current_class = None;
+                    }
+                }
+                if should_add {
+                    let closing_tag = enter_span(token_handler.out, class, &token_handler.href_context);
+                    token_handler.closing_tags.push((closing_tag, class));
+                }
+
+                token_handler.current_class = None;
+                token_handler.pending_exit_span = None;
             }
             Highlight::ExitSpan => {
-                // We flush everything just in case...
-                write_pending_elems(
-                    out,
-                    &href_context,
-                    &mut pending_elems,
-                    &mut current_class,
-                    &closing_tags,
-                );
-                exit_span(out, closing_tags.pop().expect("ExitSpan without EnterSpan").0)
+                token_handler.current_class = None;
+                token_handler.pending_exit_span =
+                    Some(token_handler.closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1);
             }
         };
     });
-    write_pending_elems(out, &href_context, &mut pending_elems, &mut current_class, &closing_tags);
 }
 
 fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
@@ -291,8 +333,8 @@ fn is_equal_to(self, other: Self) -> bool {
         match (self, other) {
             (Self::Self_(_), Self::Self_(_))
             | (Self::Macro(_), Self::Macro(_))
-            | (Self::Ident(_), Self::Ident(_))
-            | (Self::Decoration(_), Self::Decoration(_)) => true,
+            | (Self::Ident(_), Self::Ident(_)) => true,
+            (Self::Decoration(c1), Self::Decoration(c2)) => c1 == c2,
             (x, y) => x == y,
         }
     }
@@ -761,7 +803,7 @@ fn advance(
             TokenKind::CloseBracket => {
                 if self.in_attribute {
                     self.in_attribute = false;
-                    sink(Highlight::Token { text: "]", class: Some(Class::Attribute) });
+                    sink(Highlight::Token { text: "]", class: None });
                     sink(Highlight::ExitSpan);
                     return;
                 }
index 2184897872153b6fb7573a0292ffb3c6973738d8..ebf29f9cb3a91616f151baa53722095c9e7b8f42 100644 (file)
@@ -1,2 +1,4 @@
-<span class="example"><span class="kw">let </span>x = <span class="number">1</span>;</span>
-<span class="kw">let </span>y = <span class="number">2</span>;
\ No newline at end of file
+<span class="example"><span class="kw">let </span>x = <span class="number">1</span>;
+<span class="kw">let </span>y = <span class="number">2</span>;
+</span><span class="example2"><span class="kw">let </span>z = <span class="number">3</span>;
+</span><span class="kw">let </span>a = <span class="number">4</span>;
\ No newline at end of file
index ae2650528eb723c742f598f3e5cd77ff0128fb23..4a5a3cf609cd405956270d3f6c8465e250d73750 100644 (file)
@@ -8,12 +8,13 @@
 .lifetime { color: #B76514; }
 .question-mark { color: #ff9011; }
 </style>
-<pre><code><span class="attribute">#![crate_type = <span class="string">&quot;lib&quot;</span>]</span>
+<pre><code><span class="attribute">#![crate_type = <span class="string">&quot;lib&quot;</span>]
 
-<span class="kw">use </span>std::path::{Path, PathBuf};
+</span><span class="kw">use </span>std::path::{Path, PathBuf};
 
-<span class="attribute">#[cfg(target_os = <span class="string">&quot;linux&quot;</span>)]</span>
-<span class="kw">fn </span>main() -&gt; () {
+<span class="attribute">#[cfg(target_os = <span class="string">&quot;linux&quot;</span>)]
+#[cfg(target_os = <span class="string">&quot;windows&quot;</span>)]
+</span><span class="kw">fn </span>main() -&gt; () {
     <span class="kw">let </span>foo = <span class="bool-val">true </span>&amp;&amp; <span class="bool-val">false </span>|| <span class="bool-val">true</span>;
     <span class="kw">let _</span>: <span class="kw-2">*const </span>() = <span class="number">0</span>;
     <span class="kw">let _ </span>= <span class="kw-2">&amp;</span>foo;
@@ -22,8 +23,8 @@
     <span class="macro">mac!</span>(foo, <span class="kw-2">&amp;mut </span>bar);
     <span class="macro">assert!</span>(<span class="self">self</span>.length &lt; N &amp;&amp; index &lt;= <span class="self">self</span>.length);
     ::std::env::var(<span class="string">&quot;gateau&quot;</span>).is_ok();
-    <span class="attribute">#[rustfmt::skip]</span>
-    <span class="kw">let </span>s:std::path::PathBuf = std::path::PathBuf::new();
+    <span class="attribute">#[rustfmt::skip]
+    </span><span class="kw">let </span>s:std::path::PathBuf = std::path::PathBuf::new();
     <span class="kw">let </span><span class="kw-2">mut </span>s = String::new();
 
     <span class="kw">match </span><span class="kw-2">&amp;</span>s {
@@ -31,7 +32,7 @@
     }
 }
 
-<span class="macro">macro_rules!</span> bar {
+<span class="macro">macro_rules! </span>bar {
     (<span class="macro-nonterminal">$foo</span>:tt) =&gt; {};
 }
 </code></pre>
index fbfdc6767337ccbff158e57265a3409ca53dc847..ef85b566cb3c487bf756d212f4a8b5b9d68f6eb1 100644 (file)
@@ -3,6 +3,7 @@
 use std::path::{Path, PathBuf};
 
 #[cfg(target_os = "linux")]
+#[cfg(target_os = "windows")]
 fn main() -> () {
     let foo = true && false || true;
     let _: *const () = 0;
index 4861a8ad32da6fa34b63478a637536c841fa792f..a5e633df4344820f4b140d3f6d5714ad9df8e7a7 100644 (file)
@@ -69,9 +69,12 @@ fn test_union_highlighting() {
 fn test_decorations() {
     create_default_session_globals_then(|| {
         let src = "let x = 1;
-let y = 2;";
+let y = 2;
+let z = 3;
+let a = 4;";
         let mut decorations = FxHashMap::default();
-        decorations.insert("example", vec![(0, 10)]);
+        decorations.insert("example", vec![(0, 10), (11, 21)]);
+        decorations.insert("example2", vec![(22, 32)]);
 
         let mut html = Buffer::new();
         write_code(&mut html, src, None, Some(DecorationInfo(decorations)));
index 2b66ab22475d4595c51712d9afa5573f8f20e29d..f9d6b4619cc77999e44c7151aa410464cf6ff2c3 100644 (file)
@@ -2632,8 +2632,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
             clean::Type::BorrowedRef { type_, .. } => {
                 work.push_back(*type_);
             }
-            clean::Type::QPath { self_type, trait_, .. } => {
-                work.push_back(*self_type);
+            clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
+                work.push_back(self_type);
                 process_path(trait_.def_id());
             }
             _ => {}
index 1fedb0144d1d088b6645305a8c71b2c3668c903d..c4e8b6f5f8449d103513ac647a2ba0aae06883df 100644 (file)
@@ -248,7 +248,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
         FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
         ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
-        TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
+        TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)),
         TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
         MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
         TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
@@ -480,10 +480,10 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
                 mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
-            QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath {
+            QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
                 name: assoc.name.to_string(),
                 args: Box::new(assoc.args.clone().into_tcx(tcx)),
-                self_type: Box::new((*self_type).into_tcx(tcx)),
+                self_type: Box::new(self_type.into_tcx(tcx)),
                 trait_: trait_.into_tcx(tcx),
             },
         }
diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs
new file mode 100644 (file)
index 0000000..0f3b465
--- /dev/null
@@ -0,0 +1,25 @@
+// Floating-point clamp is designed to be implementable as max+min,
+// so check to make sure that's what it's actually emitting.
+
+// assembly-output: emit-asm
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+
+// CHECK-LABEL: clamp_demo:
+#[no_mangle]
+pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 {
+    // CHECK: maxss
+    // CHECK: minss
+    a.clamp(x, y)
+}
+
+// CHECK-LABEL: clamp12_demo:
+#[no_mangle]
+pub fn clamp12_demo(a: f32) -> f32 {
+    // CHECK: movss   xmm1
+    // CHECK-NEXT: maxss   xmm1, xmm0
+    // CHECK-NEXT: movss   xmm0
+    // CHECK-NEXT: minss   xmm0, xmm1
+    // CHECK: ret
+    a.clamp(1.0, 2.0)
+}
index 6e1d5a6c3f2712f22fca6991cd44ca62ea8f8fce..bcfe2f9af50bdeab63b71f70a655935165490c65 100644 (file)
@@ -13,4 +13,4 @@ pub fn call_foreign_fn() -> u8 {
 // CHECK: declare zeroext i8 @foreign_fn()
 extern "C" {fn foreign_fn() -> u8;}
 
-// CHECK: !{i32 7, !"PIC Level", i32 2}
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
index a843202a94f82c0bf73b34fbf48201bd4e307566..ec44edc0667741ad863b968aa99141a040f77963 100644 (file)
@@ -18,5 +18,5 @@ pub fn call_foreign_fn() -> u8 {
 // CHECK: declare zeroext i8 @foreign_fn()
 extern "C" {fn foreign_fn() -> u8;}
 
-// CHECK: !{i32 7, !"PIC Level", i32 2}
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
 // CHECK: !{i32 7, !"PIE Level", i32 2}
index 836443bf4d2933995b8f9a67754208709519a705..04378dbf374d9d74e312363997242227ebbc1dbc 100644 (file)
@@ -24,7 +24,7 @@
 +         _1 = const 1_i32;                // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
           StorageDead(_2);                 // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
           StorageDead(_3);                 // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
-          nop;                             // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
       }
index 7a3b26a731727305e00a50ff49e12776bfb597f4..493d0508a046ddfd220f36f17f2fb9879b7ab44b 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 
 // EMIT_MIR aggregate.main.ConstProp.diff
index bb9abdd10200dddc3e2796c021603162c1ce8ddf..439b2a3e16b458fde72d7328c8436f8e48f9fdc9 100644 (file)
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
           StorageLive(_3);                 // scope 0 at $DIR/array_index.rs:+1:31: +1:32
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:+1:31: +1:32
-          _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
+-         _4 = Len(_2);                    // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
       }
   
       bb1: {
@@ -30,7 +31,7 @@
 +         _1 = const 2_u32;                // scope 0 at $DIR/array_index.rs:+1:18: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
           StorageDead(_2);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
-          nop;                             // scope 0 at $DIR/array_index.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/array_index.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/array_index.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/array_index.rs:+2:2: +2:2
       }
index bb9abdd10200dddc3e2796c021603162c1ce8ddf..439b2a3e16b458fde72d7328c8436f8e48f9fdc9 100644 (file)
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
           StorageLive(_3);                 // scope 0 at $DIR/array_index.rs:+1:31: +1:32
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:+1:31: +1:32
-          _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
+-         _4 = Len(_2);                    // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
       }
   
       bb1: {
@@ -30,7 +31,7 @@
 +         _1 = const 2_u32;                // scope 0 at $DIR/array_index.rs:+1:18: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
           StorageDead(_2);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
-          nop;                             // scope 0 at $DIR/array_index.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/array_index.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/array_index.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/array_index.rs:+2:2: +2:2
       }
index 2c5254b5deba064fbb183a3a38b8480f30a3f955..d31c2827b4e0ac94daede6bdfac232dfc1a66204 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR array_index.main.ConstProp.diff
index 45134a3fdff3cfe6785fb76189c2eaa91eb8380c..bea32a67ef4a031b87d257845dfe6be9f105e9d3 100644 (file)
           StorageLive(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 -         _3 = _1;                         // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 -         _4 = Eq(_3, const 0_i32);        // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
--         assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _3 = const 0_i32;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+          assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
       }
   
       bb1: {
 +         _5 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _6 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _7 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
++         assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
       }
   
       bb2: {
--         _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+          _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
           StorageDead(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
-          nop;                             // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
+          _0 = const ();                   // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
           StorageDead(_2);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2
index 6f39209b970d23aa4ebbe1a373fbac8b419df134..a6fd325ece035d14f2b9924911ace9a31aa44de7 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
index 57164e3e794d20822e5760786eb7603de9b1f789..c7b609949cd15a58a146013fcd4a79f82483b30f 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O -Zmir-opt-level=4
 
 // EMIT_MIR boolean_identities.test.ConstProp.diff
index 73fdf14049896a8f6d7c522b78a3c92271e4fc7f..cb82a7bea149381b42e68f9cc0be10961b0a0c2e 100644 (file)
           StorageLive(_3);                 // scope 0 at $DIR/boxes.rs:+1:14: +1:22
 -         _4 = SizeOf(i32);                // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 -         _5 = AlignOf(i32);               // scope 2 at $DIR/boxes.rs:+1:14: +1:22
--         _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 +         _4 = const 4_usize;              // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 +         _5 = const 4_usize;              // scope 2 at $DIR/boxes.rs:+1:14: +1:22
-+         _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
+          _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/boxes.rs:12:14: 12:22
+                                           // + span: $DIR/boxes.rs:13:14: 13:22
                                            // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) }
       }
   
@@ -53,7 +52,7 @@
   
       bb2: {
           StorageDead(_3);                 // scope 0 at $DIR/boxes.rs:+1:26: +1:27
-          nop;                             // scope 0 at $DIR/boxes.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/boxes.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/boxes.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/boxes.rs:+2:2: +2:2
       }
index fea666a4455eda1d3a566e807913f5eac43380df..d287830db5a56ed86aa83c6ca6a440e9e590ee99 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 // ignore-emscripten compiled with panic=abort by default
 // ignore-wasm32
index 5698a612fe2d2e78e139d485c0db56f63ca7c9ca..e040a4b3a53e92b4c3ca489e3c81b5e6d0e996ae 100644 (file)
@@ -19,7 +19,7 @@
           StorageLive(_2);                 // scope 1 at $DIR/cast.rs:+3:9: +3:10
 -         _2 = const 42_u32 as u8 (Misc);  // scope 1 at $DIR/cast.rs:+3:13: +3:24
 +         _2 = const 42_u8;                // scope 1 at $DIR/cast.rs:+3:13: +3:24
-          nop;                             // scope 0 at $DIR/cast.rs:+0:11: +4:2
+          _0 = const ();                   // scope 0 at $DIR/cast.rs:+0:11: +4:2
           StorageDead(_2);                 // scope 1 at $DIR/cast.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/cast.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/cast.rs:+4:2: +4:2
index 680cab007408295d39f13ce5886e8e8987aa3b06..984086eda48b0a0225ca5f8b4d51cf56a60dae91 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR cast.main.ConstProp.diff
 
 fn main() {
index 5e33d054207b0036fbb9c2f33f508af276337da8..96d0d25664a41d15d7aa54c8a942626c08b476fe 100644 (file)
@@ -20,7 +20,7 @@
       bb1: {
 -         _1 = move (_2.0: u32);           // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
 +         _1 = const 2_u32;                // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
-          nop;                             // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/checked_add.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/checked_add.rs:+2:2: +2:2
       }
index 08d59b6fbc36f195058666ce5305a43d74ea720a..b9860da4c82204777d579a06a4f024fdbaca2037 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR checked_add.main.ConstProp.diff
index c21b24591d88e8b388949e3942461b843b508897..2cb071deab13fc0ac87f4b9989ce36978cb0c618 100644 (file)
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _3 = const FOO;                  // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39
           _5 = _1;                         // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11
           _4 = read(move _5) -> bb1;       // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:5: 8:9
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9
                                            // + literal: Const { ty: fn(usize) {read}, val: Value(<ZST>) }
       }
   
       bb1: {
           StorageDead(_5);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12
           StorageDead(_4);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13
-          nop;                             // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
+          _0 = const ();                   // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2
       }
index 8bd68527f37033bf1f0de2dd52d9dd622318ffa3..0a3dcbd380fa823b44acb921e7bab8b9ee1a64cb 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 #[inline(never)]
 fn read(_: usize) { }
 
index aa4ce19f620fe18a69ce5c20e0e30b8212e79573..7dbe8e7344b1227bb4cbf6389efb961301a4e5bc 100644 (file)
@@ -1,10 +1,11 @@
+// unit-test: ConstProp
 // compile-flags: -Zmir-opt-level=1
 
-trait NeedsDrop:Sized{
-    const NEEDS:bool=std::mem::needs_drop::<Self>();
+trait NeedsDrop: Sized {
+    const NEEDS: bool = std::mem::needs_drop::<Self>();
 }
 
-impl<This> NeedsDrop for This{}
+impl<This> NeedsDrop for This {}
 
 // EMIT_MIR control_flow_simplification.hello.ConstProp.diff
 // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir
index 5b4ecaa80f1f10f5e89cb70402ba249b91b16e02..6b29bb59c40dacc56c3161cb4bdfe71a6e0d6098 100644 (file)
@@ -44,7 +44,7 @@
           _1 = Add(move _2, const 0_i32);  // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
           StorageDead(_2);                 // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
           StorageDead(_3);                 // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
-          nop;                             // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
       }
index 5b4ecaa80f1f10f5e89cb70402ba249b91b16e02..6b29bb59c40dacc56c3161cb4bdfe71a6e0d6098 100644 (file)
@@ -44,7 +44,7 @@
           _1 = Add(move _2, const 0_i32);  // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
           StorageDead(_2);                 // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
           StorageDead(_3);                 // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
-          nop;                             // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
       }
index 67538b3c7a563fea9fd36338402157bf1de3b2d2..fdd67ca8ac44f847634106a98ad31329f457e5b5 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 
 // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with
index 2e1e32545a28629aa300b7a407348551b4021688..948bb7f56fe8589b14acdb9c48d671b4f6aeadb0 100644 (file)
 -         assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
 +         _2 = const 2_u8;                 // scope 0 at $DIR/indirect.rs:+1:13: +1:25
 +         _3 = const (3_u8, false);        // scope 0 at $DIR/indirect.rs:+1:13: +1:29
-+         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
       }
   
       bb1: {
 -         _1 = move (_3.0: u8);            // scope 0 at $DIR/indirect.rs:+1:13: +1:29
 +         _1 = const 3_u8;                 // scope 0 at $DIR/indirect.rs:+1:13: +1:29
           StorageDead(_2);                 // scope 0 at $DIR/indirect.rs:+1:28: +1:29
-          nop;                             // scope 0 at $DIR/indirect.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/indirect.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/indirect.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/indirect.rs:+2:2: +2:2
       }
index 37217ca8134076d92b42b40147bbef4eedfb18cf..44916cbfe743a8781e22e8d35bca33639719ba9a 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR indirect.main.ConstProp.diff
index 81eccae46b97e2673d2ccf6a31200946e7f64fbc..6ca03438ef3965239bb0c18b0ee68129627fe066 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
 // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected
index c78b8b971783f0393981be5802721aa111a94829..ffc6fa1f290f3e06210bfd90fe4eb63bc0b70972 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
 // This used to ICE in const-prop
index b3d5980aa73367006d4ef9ac0c24f49fe272c0cd..9d541dcabbb2c24c19109d2351f79d1497feaa37 100644 (file)
@@ -19,7 +19,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22
           _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/issue-66971.rs:16:5: 16:11
+                                           // + span: $DIR/issue-66971.rs:17:5: 17:11
                                            // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) }
       }
   
index 8330b50529f73f1916c81f75806d7c7a1bda1fe2..b79d814760d9eda1ec1d7eab095f28128b7df2bd 100644 (file)
@@ -20,7 +20,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19
           _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20
                                            // mir::Constant
-                                           // + span: $DIR/issue-67019.rs:11:5: 11:9
+                                           // + span: $DIR/issue-67019.rs:12:5: 12:9
                                            // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) }
       }
   
index b0ecdf1818e4d365f13ed10fab76895fe2b746b8..c839f92f2ceb180f9a1aeb9c08987b73f494b988 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O -Zmir-opt-level=4
 
 // EMIT_MIR mult_by_zero.test.ConstProp.diff
index 801e7a9fcbb7b48fbf3c5d0b9bc0f5437ea4b176..cb01719dd77a9e97885bbc9395950f26b967384a 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable.main.ConstProp.diff
index e0b4b77bac476a1d19de9c58d3e879d121bb45c6..d4ff8d89073427e24217112dbfea577fce6cab6f 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff
index 79ac497c783fb20d6cbba96753cde2e014faf041..9060f7e9bd3e6a8759f3f03e1c030599d1756cb8 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff
index c678f7b0327633d6ffad6e1f68c61e2dc26ea294..6eda503c1eec4c615afcb8e467988fc186447935 100644 (file)
@@ -16,7 +16,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32
+                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32
                                            // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(<ZST>) }
       }
   
index 9bb62b8973cbd14b974126d17303cc6261c9c8b9..cb59509ff1061ae1245ab0306c6c00c3a82b8735 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff
index 4c2ba9a099815fe038663afeb4736c8f8d7f2d61..eb3a7bc96d8822cdf959be5ac9ca55daecc246d0 100644 (file)
@@ -25,7 +25,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
           _4 = const {alloc1: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19
+                                           // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19
                                            // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) }
           _3 = (*_4);                      // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
           _1 = move _3;                    // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19
index 4126fb3c68c4ff41799e174e8fcd69315089e5c3..8c23c5fcf0f88948a0952e751394e693bd26ca30 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 static mut STATIC: u32 = 42;
index 5328792b323888dda92979c9fe6eb0c38442489e..4f205667be0e2821a76f724caa84733ed84e2304 100644 (file)
@@ -25,7 +25,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16
+                                           // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16
                                            // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
       }
   
index 13f1b3f47f2419132c577ff21e7a5b26968c97a9..b077cfd3e0ae71a9cb29b0d0099f09858cfdfaf3 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff
index 17265b7eb858e3c6423b1c81b1a74982e010109e..c0fbd2558cd98fd1bc12b3621c654a68887d2840 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -C overflow-checks=on
 
 struct Point {
index 89f43d751381565cd5137dbf572285b872f041c0..b9c283a54821b7576aa1edb8717ad2daf9d64501 100644 (file)
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
           _3 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
                                            // mir::Constant
-                                           // + span: $DIR/read_immutable_static.rs:7:13: 7:16
+                                           // + span: $DIR/read_immutable_static.rs:8:13: 8:16
                                            // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _2 = (*_3);                      // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
 +         _2 = const 2_u8;                 // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
@@ -26,7 +26,7 @@
           StorageLive(_5);                 // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
           _5 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/read_immutable_static.rs:7:19: 7:22
+                                           // + span: $DIR/read_immutable_static.rs:8:19: 8:22
                                            // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _4 = (*_5);                      // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
 -         _1 = Add(move _2, move _4);      // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22
index 8a5f12c6f3da9b799b52c25d19d8e7273b6c0b1a..4f7afe6cad4a19d5e08ad465ddce6ee0ea57f52c 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 static FOO: u8 = 2;
index f0c89caeac6454aea872587c7593aa88e59d0efa..84ec5c8bb1db1ac1035aaf7813b6539278b52fc3 100644 (file)
@@ -13,7 +13,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
                                            // mir::Constant
-                                           // + span: $DIR/ref_deref_project.rs:5:6: 5:17
+                                           // + span: $DIR/ref_deref_project.rs:6:6: 6:17
                                            // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
index d2554028792c133b793e6e24bcf97b9373b4b828..6f3a060a1260a87281f8b73dbed98d1c80ffdb99 100644 (file)
@@ -16,7 +16,7 @@
 -         _2 = &(_3.1: i32);               // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
 +         _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
 +                                          // mir::Constant
-+                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
++                                          // + span: $DIR/ref_deref_project.rs:6:6: 6:17
 +                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
index c7cc73651f6349b2a725a401da4a06c6d6fe7f87..659c11d9b0c29f4afae77f07b26913976bce623e 100644 (file)
@@ -1,3 +1,4 @@
+// unit-test
 // EMIT_MIR ref_deref_project.main.PromoteTemps.diff
 // EMIT_MIR ref_deref_project.main.ConstProp.diff
 
index b919935e4b47a3b73ed5fb82b5db4932720a200d..89987491d1b46cbcc47fd36d1977d84202e65387 100644 (file)
@@ -1,5 +1,5 @@
 <code># single
 ## double
 ### triple
-<span class="attribute">#[outer]</span>
-<span class="attribute">#![inner]</span></code>
\ No newline at end of file
+<span class="attribute">#[outer]
+#![inner]</span></code>
index d67716028799b6e8f5785ebe1b5582d13689830f..87267a750c6151b1079e4d75948168b0a2cb1059 100644 (file)
@@ -1,8 +1,10 @@
 // @has issue_41783/struct.Foo.html
 // @!hasraw - 'space'
 // @!hasraw - 'comment'
-// @hasraw - '<span class="attribute">#[outer]</span>'
-// @hasraw - '<span class="attribute">#![inner]</span>'
+// @hasraw - '<span class="attribute">#[outer]'
+// @!hasraw - '<span class="attribute">#[outer]</span>'
+// @hasraw - '#![inner]</span>'
+// @!hasraw - '<span class="attribute">#![inner]</span>'
 // @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code'
 
 /// ```no_run
index 0d9c9350efca4a0bbf7cb7bd93328e9bf509be9f..117b798710cf00570fee91785d61787f65d091e8 100644 (file)
@@ -30,7 +30,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_parse::new_parser_from_source_str;
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::FilePathMapping;
@@ -47,7 +46,7 @@ fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
 
 // Helper functions for building exprs
 fn expr(kind: ExprKind) -> P<Expr> {
-    P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: ThinVec::new(), tokens: None })
+    P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })
 }
 
 fn make_x() -> P<Expr> {
@@ -196,7 +195,7 @@ fn visit_expr(&mut self, e: &mut P<Expr>) {
                 id: DUMMY_NODE_ID,
                 kind: ExprKind::Paren(e),
                 span: DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
                 tokens: None,
             })
         });
index 19750fe1f333f74cc0d4cd89dfc0f5a478d95907..fbe1a1ee8bcd7a1b7950ee4f8b64b4129660c1bd 100644 (file)
@@ -36,9 +36,7 @@ error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
   --> $DIR/associated-types-eq-3.rs:40:9
    |
 LL |     baz(&a);
-   |     --- ^^ type mismatch resolving `<isize as Foo>::A == Bar`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^ type mismatch resolving `<isize as Foo>::A == Bar`
    |
 note: expected this to be `Bar`
   --> $DIR/associated-types-eq-3.rs:12:14
index 6552c8be7808926e1b4acb7cd25536ed2c708795..389cc7beddd83a5ccfce4cc1dbd079ed970fd82b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index b2ee1b5e6d04527fb56eb6eddb0b65ce4e8d8381..1feaa612ee688714a363c578f9900edca268067f 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:21
+  --> $DIR/associated-types-no-suitable-bound.rs:11:5
    |
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 2e40dbd065d3ef5579d5495b95590646d5e086a0..cc3ed556115bc472b0b22e887e0ce8a040b051c1 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index bd3ee2abd2c7604da8473500748cdb10eea74504..18f2830d8b21504515f21599a3f13dc9e9328639 100644 (file)
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 66f1ab726922df37cef4c10b0653d4f3fe08d849..5edd5c864e1357b44b0c6407bef4d309bc3139ec 100644 (file)
@@ -17,10 +17,12 @@ LL |     f1(2i32, 4u32);
    |               ~~~
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
+  --> $DIR/associated-types-path-2.rs:29:8
    |
 LL |     f1(2u32, 4u32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     -- ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `f1`
@@ -33,9 +35,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:14
    |
 LL |     f1(2u32, 4u32);
-   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
-   |     |
-   |     required by a bound introduced by this call
+   |              ^^^^ the trait `Foo` is not implemented for `u32`
    |
    = help: the trait `Foo` is implemented for `i32`
 
index 2e67c21940fc712c05aebfd3170128e287c54434..66d59bccdbb68861f6c356e4b0c11569b5e09bb4 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
    |
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
index 22daaf329102a5a7624c5b71634cfb7c6bdab1d9..a14a273b3ece97456f40a49e88eadb9493ca96bd 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-27675-unchecked-bounds.rs:15:31
+  --> $DIR/issue-27675-unchecked-bounds.rs:15:12
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |     ------------------------- ^ the trait `Copy` is not implemented for `T`
-   |     |
-   |     required by a bound introduced by this call
+   |            ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required by a bound in `copy`
   --> $DIR/issue-27675-unchecked-bounds.rs:10:12
index dd5ec7175b5f1aa47ac07db08a3786875027cf4b..62cf1f37a77139e3ce71dab1e8587d329bcba70f 100644 (file)
@@ -45,16 +45,20 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:23:1
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
-   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:16:8
+  --> $DIR/issue-59324.rs:16:5
    |
-LL |     fn get_service(
-   |        ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
    |
 help: consider further restricting this bound
    |
index 01c0d3225ba0bb260c3a7397ec33ed56ad561727..af99b608ca14d0f4388d25de27db4fab08f6c27f 100644 (file)
@@ -1,8 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-67252-unnamed-future.rs:18:5
+  --> $DIR/issue-67252-unnamed-future.rs:18:11
    |
-LL |     spawn(async {
-   |     ^^^^^ future created by async block is not `Send`
+LL |       spawn(async {
+   |  ___________^
+LL | |         let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+LL | |         AFuture.await;
+LL | |     });
+   | |_____^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
index 9c85eb876849749f393e84fde681b69de25fdcdb..c3553e3e0c1c2b9524ee08623c9c4d7fa50aab68 100644 (file)
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:34:5
+  --> $DIR/issue-68112.rs:34:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ future created by async block is not `Send`
+   |                  ^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: future is not `Send` as it awaits another future which is not `Send`
@@ -17,10 +17,10 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:43:5
+  --> $DIR/issue-68112.rs:43:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ future created by async block is not `Send`
+   |                  ^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: future is not `Send` as it awaits another future which is not `Send`
@@ -35,10 +35,12 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/issue-68112.rs:60:5
+  --> $DIR/issue-68112.rs:60:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
index b230930012914fed15ecfe2facd5901a2168484c..99e960f5d0f26f98694a4bed5ff9c3b4c4128134 100644 (file)
@@ -1,8 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:5
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:17
    |
-LL |     assert_send(async {
-   |     ^^^^^^^^^^^ future created by async block is not `Send`
+LL |       assert_send(async {
+   |  _________________^
+LL | |
+LL | |         bar(Foo(std::ptr::null())).await;
+LL | |     })
+   | |_____^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8`
 note: future is not `Send` as this value is used across an await
index 7d6bf58f51696a6915645b6b8da9dd697fcb64b7..0c4970a72591f727b699e433230e364155db29fb 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)`
-  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5
+  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18
    |
 LL |     is_mytrait::<(MyS2, MyS)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
+   |                  ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
    |
    = note: required because it appears within the type `(MyS2, MyS)`
 note: required by a bound in `is_mytrait`
index 5645e15850274cbc7ed55ab4ce485835ae998a36..ce7095664c11a3798fcae9f8bccfd967562f5ad8 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `u32: Signed` is not satisfied
-  --> $DIR/typeck-default-trait-impl-precedence.rs:19:5
+  --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
    |
 LL |     is_defaulted::<&'static u32>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
+   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
    = help: the trait `Signed` is implemented for `i32`
 note: required for `&'static u32` to implement `Defaulted`
index dd83a03fdf691cbcc9b7c623ba4864636848a6fa..eeeefcfb7dd15cd846411f5dd6c8307174cd42ae 100644 (file)
@@ -15,8 +15,8 @@ fn main() {
        x: 5,
     };
 
-    let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied
-        x: 5.0,
+    let s = S {
+        x: 5.0, //~ ERROR the trait bound `{float}: Foo` is not satisfied
     };
 
     let s = S {
index 7f8566082cd262a4afa3510c67e6997cc64f9832..6e8daf635175fbf62fe080c81445cc5b73245a92 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `{float}: Foo` is not satisfied
-  --> $DIR/type_wf.rs:18:13
+  --> $DIR/type_wf.rs:19:12
    |
-LL |     let s = S {
-   |             ^ the trait `Foo` is not implemented for `{float}`
+LL |         x: 5.0,
+   |            ^^^ the trait `Foo` is not implemented for `{float}`
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `S`
index 74d3c4977ee65d40c6945d47ec71e59e94993b71..f744b71c284b0d68c8c965e48c2c515368011c3f 100644 (file)
@@ -8,6 +8,8 @@ LL |         num += 1;
 ...
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
+   |
+   = note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()`
 
 error: aborting due to previous error
 
index 473e8e8417e6e09966d6771e2b9d1f0ecc2e17b4..34f94f9dca6d34de487fe29fbb94781a2bf93e00 100644 (file)
@@ -8,6 +8,8 @@ LL |         vec
 ...
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
+   |
+   = note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec<u8>`
 
 error: aborting due to previous error
 
index bcde35983fc4c3f6484c38b8052c1cb6a9d33724..309c63e52932baa970fcba0d9ed3c60a952becb7 100644 (file)
@@ -7,7 +7,15 @@ LL |         let [_, _s] = s;
    |                       - closure is `FnOnce` because it moves the variable `s` out of its environment
 LL |     };
 LL |     expect_fn(c);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `expect_fn`
+  --> $DIR/closure-origin-array-diagnostics.rs:5:17
+   |
+LL | fn expect_fn<F: Fn()>(_f: F) {}
+   |                 ^^^^ required by this bound in `expect_fn`
 
 error: aborting due to previous error
 
index df33c4f1fd6d4836c1db1ac0995aa9843601631a..3e77635f9e0c82c7736d07d565fe206e40268cc3 100644 (file)
@@ -7,7 +7,15 @@ LL |         let s = s.1;
    |                 --- closure is `FnOnce` because it moves the variable `s.1` out of its environment
 LL |     };
 LL |     expect_fn(c);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `expect_fn`
+  --> $DIR/closure-origin-tuple-diagnostics.rs:5:17
+   |
+LL | fn expect_fn<F: Fn()>(_f: F) {}
+   |                 ^^^^ required by this bound in `expect_fn`
 
 error: aborting due to previous error
 
index 3e9b1c292dc1865b6109784eef1dc91d7dd6583e..a2ca06b4e6e1aa7917d8a5a1864ea51d6238a08b 100644 (file)
@@ -1,8 +1,14 @@
 error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
-  --> $DIR/closure-move-sync.rs:6:13
+  --> $DIR/closure-move-sync.rs:6:27
    |
-LL |     let t = thread::spawn(|| {
-   |             ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
+LL |       let t = thread::spawn(|| {
+   |  _____________-------------_^
+   | |             |
+   | |             required by a bound introduced by this call
+LL | |         recv.recv().unwrap();
+LL | |
+LL | |     });
+   | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
    = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send`
@@ -18,10 +24,12 @@ LL |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`
 
 error[E0277]: `Sender<()>` cannot be shared between threads safely
-  --> $DIR/closure-move-sync.rs:18:5
+  --> $DIR/closure-move-sync.rs:18:19
    |
 LL |     thread::spawn(|| tx.send(()).unwrap());
-   |     ^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely
+   |     ------------- ^^^^^^^^^^^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Sender<()>`
    = note: required for `&Sender<()>` to implement `Send`
index 35caf71a5e8c78446b58da82bc2db3dc91d7569b..9ea55d764f345b6d77c74fc1056835c09a00b9a7 100644 (file)
@@ -6,7 +6,15 @@ LL |     let closure = |_| foo(x);
    |                   |
    |                   this closure implements `FnOnce`, not `Fn`
 LL |     bar(closure);
-   |     --- the requirement to implement `Fn` derives from here
+   |     --- ------- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `bar`
+  --> $DIR/closure-wrong-kind.rs:6:11
+   |
+LL | fn bar<T: Fn(u32)>(_: T) {}
+   |           ^^^^^^^ required by this bound in `bar`
 
 error: aborting due to previous error
 
index a9c185e5fcbd15577036eeaf1bc4068331c9c626..0e8334d033820b3d8465adc8d46d7a8ff02d6c0f 100644 (file)
@@ -2,9 +2,7 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied
   --> $DIR/trait_objects_fail.rs:26:9
    |
 LL |     foo(&10_u32);
-   |     --- ^^^^^^^ the trait `Trait` is not implemented for `u32`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^^^ the trait `Trait` is not implemented for `u32`
    |
    = help: the trait `Trait<2>` is implemented for `u32`
    = note: required for the cast from `u32` to the object type `dyn Trait`
@@ -13,9 +11,7 @@ error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
   --> $DIR/trait_objects_fail.rs:28:9
    |
 LL |     bar(&true);
-   |     --- ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
    |
    = help: the trait `Traitor<2, 3>` is implemented for `bool`
    = note: required for the cast from `bool` to the object type `dyn Traitor<_>`
index a5f7bc0b26cbd0d4b2d4f439acae5408079ec614..615dc875f67a34b6bf6aeba2121309b722455155 100644 (file)
@@ -1,8 +1,8 @@
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:17:5
+  --> $DIR/abstract-const-as-cast-3.rs:17:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
 note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
@@ -26,10 +26,10 @@ LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
               found type `{ O as u128 }`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:20:5
+  --> $DIR/abstract-const-as-cast-3.rs:20:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
 note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
@@ -71,10 +71,10 @@ LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
               found type `14`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:35:5
+  --> $DIR/abstract-const-as-cast-3.rs:35:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
 note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
@@ -98,10 +98,10 @@ LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
               found type `{ O as u128 }`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:38:5
+  --> $DIR/abstract-const-as-cast-3.rs:38:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
 note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
index 87ca771e54ed41904a1496076a3a2e80d0ad7146..b9c4d8866bf9deeabbb1c025521bd0eb78508895 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: can't drop `UnconstDrop` in const contexts
   --> $DIR/const-block-const-bound.rs:20:11
    |
 LL |         f(UnconstDrop);
-   |         - ^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |         - ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
    |         |
    |         required by a bound introduced by this call
    |
@@ -23,7 +23,7 @@ error[E0277]: can't drop `NonDrop` in const contexts
   --> $DIR/const-block-const-bound.rs:22:11
    |
 LL |         f(NonDrop);
-   |         - ^^^^^^^ expected an implementor of trait `~const Destruct`
+   |         - ^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
    |         |
    |         required by a bound introduced by this call
    |
index da895098e4b8e9a6b724799555386b4b8bf2b72a..80e2dd7fedefd196d52cf0218a42a1ddcb3e7f34 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `B<C>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:13
    |
 LL |     is_copy(B { a: 1, b: C });
-   |     ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
+   |     ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<C>`
    |     |
    |     required by a bound introduced by this call
    |
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `B<C>: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
    |
 LL |     is_clone(B { a: 1, b: C });
-   |     -------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
+   |     -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B<C>`
    |     |
    |     required by a bound introduced by this call
    |
@@ -50,7 +50,7 @@ error[E0277]: the trait bound `B<D>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
    |
 LL |     is_copy(B { a: 1, b: D });
-   |     ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
+   |     ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<D>`
    |     |
    |     required by a bound introduced by this call
    |
index 26764bc0ee5cca431355fc6856b5780d298de731..b69fcd5d32a60da122e535111cd6acc07404211b 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
-  --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:8
+  --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:12
    |
 LL |     f1.foo(1usize);
-   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        --- ^^^^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        |
+   |        required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<A>`:
              <Bar as Foo<i32>>
index bb175367e1f9e0772ad8d07bfe4520285a1a3733..5e0e4a0115a0e29e5bbdd8ab36df224997611e9a 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
-  --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:8
+  --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:12
    |
 LL |     f1.foo(1usize);
-   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        --- ^^^^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        |
+   |        required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<A>`:
              <Bar as Foo<i16>>
index ca2cb884240763abb5af0ea9d8f7a6a381742b5d..a2abf37931a4fb488a6e60666fa93e315afdd841 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
-  --> $DIR/E0277-2.rs:16:5
+  --> $DIR/E0277-2.rs:16:15
    |
 LL |     is_send::<Foo>();
-   |     ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
+   |               ^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `Foo`, the trait `Send` is not implemented for `*const u8`
 note: required because it appears within the type `Baz`
index 8d6713261d5ecb6b3232cc1a6d0ca7261f3a7cb7..a79caced111bbfc6316643e49350b1428f3c7961 100644 (file)
@@ -16,10 +16,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:25:5
+  --> $DIR/extern-types-unsized.rs:25:20
    |
 LL |     assert_sized::<Foo>();
-   |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^ doesn't have a size known at compile-time
    |
    = help: within `Foo`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Foo`
@@ -38,10 +38,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:28:5
+  --> $DIR/extern-types-unsized.rs:28:20
    |
 LL |     assert_sized::<Bar<A>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Bar<A>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
@@ -60,10 +60,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:31:5
+  --> $DIR/extern-types-unsized.rs:31:20
    |
 LL |     assert_sized::<Bar<Bar<A>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
index 0557340f792fd21292d8fb7aae82683ce9ab4dbc..b7757740d9e34de53ca83755350cb841b114ea17 100644 (file)
@@ -15,9 +15,7 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known
   --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |     --- ^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = help: unsized fn params are gated as an unstable feature
index 726d3e35b10e967776c704d95b8b891d7cc2e465..3ed040c3ab35926e91d4d0731b008da25cd2f0e1 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
-  --> $DIR/send-sync.rs:8:5
+  --> $DIR/send-sync.rs:8:10
    |
 LL |     send(format_args!("{:?}", c));
-   |     ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
    = note: required because it appears within the type `&core::fmt::Opaque`
@@ -17,10 +19,12 @@ LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
-  --> $DIR/send-sync.rs:9:5
+  --> $DIR/send-sync.rs:9:10
    |
 LL |     sync(format_args!("{:?}", c));
-   |     ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::Opaque`
    = note: required because it appears within the type `&core::fmt::Opaque`
index 522a300b3ed79afd49b744057ae3337734b15c58..fbf5d6e07256b27fab6289e3eacd0cbb7c1d1093 100644 (file)
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -41,10 +41,10 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -83,10 +83,10 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
index 5bc6ea5600fc58769414aded57d688f22a1261c0..0808a2c85ee1dd477b68b36511b02c476fa8fdb2 100644 (file)
@@ -1,8 +1,14 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-yield-twice.rs:7:5
+  --> $DIR/drop-yield-twice.rs:7:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |         let guard = Foo(42);
+LL | |         yield;
+LL | |         drop(guard);
+LL | |         yield;
+LL | |     })
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 7:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
index 2a39a08ee39b26ff7e2d358508da7bd51c5b18e8..8f5d2429a2892734ad64c69bac083a7a0d9ab6c8 100644 (file)
@@ -1,8 +1,15 @@
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
+  --> $DIR/generator-yielding-or-returning-itself.rs:15:34
    |
-LL |     want_cyclic_generator_return(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+LL |       want_cyclic_generator_return(|| {
+   |  _____----------------------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         if false { yield None.unwrap(); }
+LL | |         None.unwrap()
+LL | |     })
+   | |_____^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
@@ -17,10 +24,17 @@ LL |     where T: Generator<Yield = (), Return = T>
    |                                    ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return`
 
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:28:5
+  --> $DIR/generator-yielding-or-returning-itself.rs:28:33
    |
-LL |     want_cyclic_generator_yield(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+LL |       want_cyclic_generator_yield(|| {
+   |  _____---------------------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         if false { yield None.unwrap(); }
+LL | |         None.unwrap()
+LL | |     })
+   | |_____^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
index 03b21c5ebd3ee48ae59551029a4f1a023d575c96..21026f45cb823375f9cc94400a0aed20da7ef085 100644 (file)
@@ -64,6 +64,7 @@ fn test2() {
     //~^ ERROR `RefCell<i32>` cannot be shared between threads safely
     //~| NOTE `RefCell<i32>` cannot be shared between threads safely
     //~| NOTE required for
+    //~| NOTE required by a bound introduced by this call
     //~| NOTE captures the following types
 }
 
index b56f445872bc4b9efe0215a6b72c28776b739da2..eb99d42c9206805a90800898f75eb5ffd8ab5ed5 100644 (file)
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:40:5
+  --> $DIR/issue-68112.rs:40:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |                  ^^^^^^^^ generator is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: generator is not `Send` as this value is used across a yield
@@ -23,10 +23,12 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/issue-68112.rs:63:5
+  --> $DIR/issue-68112.rs:63:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
index b54b0f570c9628834cd3210de0c50217769ecc14..a821c57b923a097bdb4770b167e6c568a6acbd51 100644 (file)
@@ -1,8 +1,15 @@
 error[E0277]: `Cell<i32>` cannot be shared between threads safely
-  --> $DIR/not-send-sync.rs:16:5
+  --> $DIR/not-send-sync.rs:16:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
+LL |       assert_send(|| {
+   |  _____-----------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^ `Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required for `&Cell<i32>` to implement `Send`
@@ -18,10 +25,15 @@ LL |     fn assert_send<T: Send>(_: T) {}
    |                       ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be shared between threads safely
-  --> $DIR/not-send-sync.rs:9:5
-   |
-LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+  --> $DIR/not-send-sync.rs:9:17
+   |
+LL |       assert_sync(|| {
+   |  _________________^
+LL | |
+LL | |         let a = Cell::new(2);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Sync`
    |
    = help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell<i32>`
 note: generator is not `Sync` as this value is used across a yield
index 1004fc64da93ad980d8e957b8054862c3342a414..9baafe54e84d41002fea3d207770365b7b57698b 100644 (file)
@@ -1,8 +1,15 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:14:5
+  --> $DIR/partial-drop.rs:14:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+LL | |         drop(guard.foo);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:14:17: 14:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
@@ -22,10 +29,17 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:22:5
+  --> $DIR/partial-drop.rs:22:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+...  |
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:22:17: 22:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
@@ -45,10 +59,17 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:32:5
+  --> $DIR/partial-drop.rs:32:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+...  |
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:32:17: 32:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
index bbde8ea7892cc232250f95179ac03b7a5ba28777..3a83021dd99508fef77cffcfca1091d098c15089 100644 (file)
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/generator-print-verbose-1.rs:37:5
+  --> $DIR/generator-print-verbose-1.rs:37:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |                  ^^^^^^^^ generator is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: generator is not `Send` as this value is used across a yield
@@ -21,10 +21,12 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-1.rs:56:5
+  --> $DIR/generator-print-verbose-1.rs:56:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required for `Arc<RefCell<i32>>` to implement `Send`
index 92ca51b4e7267c140d0bc875897a87722bbdcbaa..909e49c38b8d18e42e7ba3f56f5e242788b6aa10 100644 (file)
@@ -1,8 +1,15 @@
 error[E0277]: `Cell<i32>` cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-2.rs:19:5
+  --> $DIR/generator-print-verbose-2.rs:19:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
+LL |       assert_send(|| {
+   |  _____-----------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^ `Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required for `&'_#4r Cell<i32>` to implement `Send`
@@ -18,10 +25,15 @@ LL |     fn assert_send<T: Send>(_: T) {}
    |                       ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-2.rs:12:5
-   |
-LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+  --> $DIR/generator-print-verbose-2.rs:12:17
+   |
+LL |       assert_sync(|| {
+   |  _________________^
+LL | |
+LL | |         let a = Cell::new(2);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Sync`
    |
    = help: within `[main::{closure#0} upvar_tys=() {Cell<i32>, ()}]`, the trait `Sync` is not implemented for `Cell<i32>`
 note: generator is not `Sync` as this value is used across a yield
index 98c304cc90b53a02554e57c8c7591000d6784739..8193f491e69edbb7e775179a4e0c4b16a951ee23 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
-  --> $DIR/issue-88460.rs:30:5
+  --> $DIR/issue-88460.rs:30:10
    |
 LL |     test(Foo);
-   |     ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
+   |     ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Marker` is implemented for `()`
 note: required by a bound in `test`
index 066bf431a83d78e4ae21581ee887296f120b6eab..b30dd36d2ad6aebf092f513c11180771d7eaed2e 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
-  --> $DIR/issue-62529-3.rs:25:9
+  --> $DIR/issue-62529-3.rs:25:14
    |
 LL |         call(f, ());
-   |         ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+   |         ---- ^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+   |         |
+   |         required by a bound introduced by this call
    |
    = note: expected a closure with arguments `((),)`
               found a closure with arguments `(<_ as ATC<'a>>::Type,)`
index 04673a375cf0176f780abe3d45b33bfe8a97c407..79bee33280d2e45769cbc0e8a49e28e4d426b034 100644 (file)
@@ -2,7 +2,9 @@ error[E0283]: type annotations needed
   --> $DIR/issue-71732.rs:18:10
    |
 LL |         .get(&"key".into())
-   |          ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get`
+   |          ^^^ ------------- type must be known at this point
+   |          |
+   |          cannot infer type of the type parameter `Q` declared on the associated function `get`
    |
    = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl Borrow<str> for String;
@@ -13,7 +15,7 @@ note: required by a bound in `HashMap::<K, V, S>::get`
    |
 LL |         K: Borrow<Q>,
    |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |         .get::<Q>(&"key".into())
    |             +++++
index e395e65fad066acc6142cbea61b08523aca2414f..4f621b82dc579eb341abb6bf6c6d4d4b7f366695 100644 (file)
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
 LL |     foo(gen()); //<- Do not suggest `foo::<impl Clone>()`!
    |     --- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
    |     |
-   |     type must be known at this point
+   |     required by a bound introduced by this call
    |
    = note: cannot satisfy `_: Clone`
 note: required by a bound in `foo`
index 30e6e10eaa2fd07a09fba9e3c544a89e6e3d6d19..9aff2cec160f2bcce6f800297fde81056f38656c 100644 (file)
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
 LL |     Foo::bar(gen()); //<- Do not suggest `Foo::bar::<impl Clone>()`!
    |     -------- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
    |     |
-   |     type must be known at this point
+   |     required by a bound introduced by this call
    |
    = note: cannot satisfy `_: Clone`
 note: required by a bound in `Foo::bar`
index 7955fecda0670d3e23f8604ef113f0029da23b4b..94f41c92598866d4aaef7e8a1162a7de304aa3c9 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/interior-mutability.rs:5:5
+  --> $DIR/interior-mutability.rs:5:18
    |
 LL |     catch_unwind(|| { x.set(23); });
-   |     ^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |     ------------ ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `Cell<i32>`
index bd18d46223e69162ae8cdd869df402f0d84b35d7..22c3470b61edeb955e8cb92b46c1d837c4c241aa 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:18
+  --> $DIR/issue-18611.rs:1:1
    |
-LL | fn add_state(op: <isize as HasState>::State) {
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+LL | / fn add_state(op: <isize as HasState>::State) {
+LL | |
+LL | | }
+   | |_^ the trait `HasState` is not implemented for `isize`
 
 error: aborting due to previous error
 
index d70bf6e1d921c3618744544c4763648cd8057d27..3f9b3be98517946f728235e3e34d2956ce678b6c 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:7
+  --> $DIR/issue-20162.rs:5:5
    |
 LL |     b.sort();
-   |       ^^^^ the trait `Ord` is not implemented for `X`
+   |     ^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
index b41b602a55b5c35ab4d66dee34d676e643ccd91b..e1858b63989326593855ab1a44d9062af4ce7681 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cann
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |                 ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
    |
    = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
    = note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
index 57f9575bdbd2937b1faa72f4b3e559c0cbb429dc..ef62dece8364002a54f8cb4b760740c426bf57d7 100644 (file)
@@ -1,8 +1,14 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/issue-20831-debruijn.rs:28:8
+  --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |        ^^^^^^^^^
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |         //
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime defined here...
   --> $DIR/issue-20831-debruijn.rs:28:58
@@ -15,10 +21,16 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | impl<'a> Publisher<'a> for MyStruct<'a> {
    |      ^^
 note: ...so that the types are compatible
-  --> $DIR/issue-20831-debruijn.rs:28:8
+  --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |        ^^^^^^^^^
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |         //
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
    = note: expected `<MyStruct<'a> as Publisher<'_>>`
               found `<MyStruct<'_> as Publisher<'_>>`
 
index 790681589248afe48fae46ac4a4a3bfee22e6928..72c65029746adb83a8aaa15d71eca77667e8860c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `Rc<()>` cannot be sent between threads safely
-  --> $DIR/issue-21763.rs:9:5
+  --> $DIR/issue-21763.rs:9:11
    |
 LL |     foo::<HashMap<Rc<()>, Rc<()>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
    |
    = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`
    = note: required because it appears within the type `(Rc<()>, Rc<()>)`
index 3d8e7b969184e6ad70bb4d1e773e41f6a831c671..f6cda3de5c763138558a318195c6bbdc462bdfda 100644 (file)
@@ -1,15 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
+error[E0275]: overflow evaluating the requirement `<T as Next>::Next`
   --> $DIR/issue-23122-2.rs:10:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
-  --> $DIR/issue-23122-2.rs:9:15
-   |
-LL | impl<T: Next> Next for GetNext<T> {
-   |               ^^^^     ^^^^^^^^^^
 
 error: aborting due to previous error
 
index 472a95d4636bc16e39b756a08df4aacb00a29782..04efa27189b746e533439c6548818dc7d1e4b17d 100644 (file)
@@ -4,12 +4,12 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
+        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
         .cloned()
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
index 0b8222088b879509e60c7fae29ce3091728fd441..e3334eef3ad7f6c5e9bfd11af0f66495fc54a059 100644 (file)
@@ -1,8 +1,16 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:11:10
-   |
-LL |         .cloned()
-   |          ^^^^^^ expected reference, found `u8`
+error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:6:25
+   |
+LL |       let temp: Vec<u8> = it
+   |  _________________________^
+LL | |
+LL | |         .take_while(|&x| {
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+   | |__________^ expected reference, found `u8`
+LL |           .cloned()
+   |            ------ required by a bound introduced by this call
    |
    = note: expected reference `&_`
                    found type `u8`
@@ -12,11 +20,11 @@ note: required by a bound in `cloned`
 LL |         Self: Sized + Iterator<Item = &'a T>,
    |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
   --> $DIR/issue-31173.rs:13:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds
+   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
    |
   ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
@@ -29,10 +37,10 @@ LL | pub struct Cloned<I> {
    | -------------------- doesn't satisfy `_: Iterator`
    |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
index caba0ad52689e10f1b33936409e8bfb919a5ea4f..691b8f88f4ed54c87d6e65b5f9c1614d81e73a34 100644 (file)
@@ -1,8 +1,10 @@
 error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:36
+  --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |                                    ^^^^^^ expected reference, found tuple
+   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
+   |              |
+   |              expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
index 48ae2df691c3d66ef17bafb381ba1e72b6b0ba15..72082f0cd17287650dbb42d4a341c419ab782df0 100644 (file)
@@ -13,10 +13,12 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:87
+  --> $DIR/issue-34334.rs:5:33
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |                                 |
+   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
index d0b51961b44a72037f90f7c58be6d148038dce59..8e9a16619f3b13cf537040461d15a5abcc614e3a 100644 (file)
@@ -7,7 +7,15 @@ LL |         farewell.push_str("!!!");
    |         -------- closure is `FnMut` because it mutates the variable `farewell` here
 ...
 LL |     apply(diary);
-   |     ----- the requirement to implement `Fn` derives from here
+   |     ----- ----- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `apply`
+  --> $DIR/issue-34349.rs:11:32
+   |
+LL |     fn apply<F>(f: F) where F: Fn() {
+   |                                ^^^^ required by this bound in `apply`
 
 error: aborting due to previous error
 
index 42cef9a47f2792deebb6fa59daf887b4f09589ea..a2b0222d4f395466a8b7e9e4e903f34724f30883 100644 (file)
@@ -6,7 +6,8 @@ trait Trait2<'a> {
 }
 
 fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
-//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+    //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
     let _e: (usize, usize) = unsafe{mem::transmute(param)};
 }
 
index 2697d46bdb2f42a510b6d12f7bf9c1a19abec2f0..ebc40f6786fd0a403bfe52554028f0cce3299195 100644 (file)
@@ -1,9 +1,19 @@
+error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+  --> $DIR/issue-35570.rs:8:1
+   |
+LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+LL | |
+LL | |
+LL | |     let _e: (usize, usize) = unsafe{mem::transmute(param)};
+LL | | }
+   | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
+
 error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
   --> $DIR/issue-35570.rs:8:40
    |
 LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 922b593935aa8341aeb1aff0bc03ec25b76c095e..384501e3e5dfdb77768412c8f6ce2a5eed782d2b 100644 (file)
@@ -30,4 +30,5 @@ fn main() {
     assert_eq!(Foo::Bar, i);
     //~^ ERROR binary operation `==` cannot be applied to type `fn(usize) -> Foo {Foo::Bar}` [E0369]
     //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277]
+    //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277]
 }
index 7ce3dedaa887bf7f6a777d0444967c2f1412eff8..bb6843a19586e8643c3a13d17f480b93ffe1b95f 100644 (file)
@@ -106,7 +106,26 @@ LL |     assert_eq!(Foo::Bar, i);
            and 68 others
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 9 previous errors
+error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
+  --> $DIR/issue-59488.rs:30:5
+   |
+LL |     assert_eq!(Foo::Bar, i);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the following other types implement trait `Debug`:
+             extern "C" fn() -> Ret
+             extern "C" fn(A, B) -> Ret
+             extern "C" fn(A, B, ...) -> Ret
+             extern "C" fn(A, B, C) -> Ret
+             extern "C" fn(A, B, C, ...) -> Ret
+             extern "C" fn(A, B, C, D) -> Ret
+             extern "C" fn(A, B, C, D, ...) -> Ret
+             extern "C" fn(A, B, C, D, E) -> Ret
+           and 68 others
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0369.
 For more information about an error, try `rustc --explain E0277`.
index 870b25014471d9402ef178545ca6d29e8747281d..dd72b6515ddca41d5241bfda07632328a14015cb 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `&u32: Foo` is not satisfied
-  --> $DIR/issue-60218.rs:18:27
+  --> $DIR/issue-60218.rs:18:19
    |
 LL |     trigger_error(vec![], |x: &u32| x)
-   |     -------------         ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     ------------- ^^^^^^ the trait `Foo` is not implemented for `&u32`
    |     |
    |     required by a bound introduced by this call
    |
index d6e39251632ba70c00a626d13bbe99db5660061d..2de15037650825da8c9abd1ba74b69f1ae523fc7 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |                        |
+   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
@@ -13,10 +15,12 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |              |
+   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
index b732df764e57f05289e59850a6dac6654c982729..9d11cf19ea77c41a2f65c2c1f18e5aea41ed7f66 100644 (file)
@@ -16,7 +16,7 @@ error[E0283]: type annotations needed
 LL |     println!("{}", 23u64.test(xs.iter().sum()));
    |                          ----           ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
    |                          |
-   |                          type must be known at this point
+   |                          required by a bound introduced by this call
    |
 note: multiple `impl`s satisfying `u64: Test<_>` found
   --> $DIR/issue-69455.rs:11:1
index a1144c8cb8c6ae72eef12533c75420e038c4eb51..7d35da825328e29577a5bb8e6ec3177ee8ff6c38 100644 (file)
@@ -4,4 +4,5 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
+    //~| NOTE required by a bound introduced by this call
 }
index 7be53a4873bccd45d12eb78e47a3e390988d7f37..7fe9707e6d232b4e4323f95320c591f18755f90c 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:3:39
+  --> $DIR/collect-into-array.rs:3:31
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                               ^^^^^^^ ------- required by a bound introduced by this call
+   |                               |
+   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
index aafa6bc8b951476245a47f487237e96baa4dc2e8..5eade075613fe6ce94d16c94256a60bcec2ee670 100644 (file)
@@ -1,15 +1,20 @@
 fn process_slice(data: &[i32]) {
     //~^ NOTE required by a bound in this
+    //~| NOTE required by a bound in this
     todo!()
 }
 
 fn main() {
     let some_generated_vec = (0..10).collect();
     //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time
+    //~| ERROR the size for values of type `[i32]` cannot be known at compilation time
     //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size
     //~| NOTE try explicitly collecting into a `Vec<{integer}>`
     //~| NOTE required by a bound in `collect`
+    //~| NOTE required by a bound in `collect`
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
+    //~| NOTE doesn't have a size known at compile-time
+    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
index 4842e65fe976b205f05726c4ea876f55e273f460..bce40118bdfa0ad5b50fb7442e131469a71ac60f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:7:9
+  --> $DIR/collect-into-slice.rs:8:9
    |
 LL |     let some_generated_vec = (0..10).collect();
    |         ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,11 +8,26 @@ LL |     let some_generated_vec = (0..10).collect();
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/collect-into-slice.rs:8:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                ^ required by this bound in `collect`
+
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:7:38
+  --> $DIR/collect-into-slice.rs:8:30
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |                              ^^^^^^^ ------- required by a bound introduced by this call
+   |                              |
+   |                              try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
@@ -21,6 +36,6 @@ note: required by a bound in `collect`
 LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 8b0771985dc3fe53cc50dadb2911156ff65cc307..8950fc51e643c67993dd28cf442211d89b588202 100644 (file)
@@ -11,5 +11,5 @@ fn take_param<T:Foo>(foo: &T) { }
 fn main() {
     let x: Box<_> = Box::new(3);
     take_param(&x);
-    //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
+    //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied
 }
index 06d48ff1f0f2796d604d07f4924b26b48675130c..930d96375bff48b07d741e135aec26ca3156fbc2 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
index 09661289a9b77cfa9d914f4c3dec0976b9cdfa55..e81d2441e6ef8de972a004e10657efb52ce35b18 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
index 299600eb6bf30e1363e3db784a562596274c4111..2380533b9c3ef4bba5357c434bfd11da99ad0b67 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
index eab003a1107829b4dc8ea4626805d109b59fce7d..cc6e1f59c7789e212bb64fd82ddaa75b142df34e 100644 (file)
@@ -1,10 +1,12 @@
 error[E0277]: `Rc<usize>` cannot be sent between threads safely
-  --> $DIR/kindck-nonsendable-1.rs:9:5
+  --> $DIR/kindck-nonsendable-1.rs:9:9
    |
 LL |     bar(move|| foo(x));
-   |     ^^^ ------ within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`
-   |     |
-   |     `Rc<usize>` cannot be sent between threads safely
+   |     --- ------^^^^^^^
+   |     |   |
+   |     |   `Rc<usize>` cannot be sent between threads safely
+   |     |   within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`
+   |     required by a bound introduced by this call
    |
    = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`, the trait `Send` is not implemented for `Rc<usize>`
 note: required because it's used within this closure
index 47b7462a6a104fdc481e047eb872dc6e6b4290ef..e9bbeeacd7013ea21c61c068028c80142bcfb962 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object.rs:12:5
+  --> $DIR/kindck-send-object.rs:12:19
    |
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
@@ -13,10 +13,10 @@ LL | fn assert_send<T:Send>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
-  --> $DIR/kindck-send-object.rs:17:5
+  --> $DIR/kindck-send-object.rs:17:19
    |
 LL |     assert_send::<Box<dyn Dummy>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `dyn Dummy`
    = note: required for `Unique<dyn Dummy>` to implement `Send`
index 24428266cc717d2e7681a74a19b61f8f51797ec4..11f597fee91be00435affb7d22fd99905ded27f7 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object1.rs:10:5
+  --> $DIR/kindck-send-object1.rs:10:19
    |
 LL |     assert_send::<&'a dyn Dummy>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`
    = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
@@ -13,10 +13,10 @@ LL | fn assert_send<T:Send+'static>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
-  --> $DIR/kindck-send-object1.rs:28:5
+  --> $DIR/kindck-send-object1.rs:28:19
    |
 LL |     assert_send::<Box<dyn Dummy + 'a>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
    = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
index 81ec65950d8757ecb56aacbe9e72340ca03d1bb0..b8af33d0dc120313c435d246754f1798af0fac8c 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object2.rs:7:5
+  --> $DIR/kindck-send-object2.rs:7:19
    |
 LL |     assert_send::<&'static dyn Dummy>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
    = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
@@ -13,10 +13,10 @@ LL | fn assert_send<T:Send>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
-  --> $DIR/kindck-send-object2.rs:12:5
+  --> $DIR/kindck-send-object2.rs:12:19
    |
 LL |     assert_send::<Box<dyn Dummy>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `dyn Dummy`
    = note: required for `Unique<dyn Dummy>` to implement `Send`
index 076c42959826d81e64a7e8297eabf8a1b0929525..b03f56465cea0d270aeeccba2e04c35ff655f5bd 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `*mut u8` cannot be sent between threads safely
-  --> $DIR/kindck-send-owned.rs:12:5
+  --> $DIR/kindck-send-owned.rs:12:19
    |
 LL |     assert_send::<Box<*mut u8>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `*mut u8`
    = note: required for `Unique<*mut u8>` to implement `Send`
index 6b87da0c040d5ccacec4f3b544eb8af09cc48fab..33f82448dd2acd87fd701c178ba088ceede166d0 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:28
+  --> $DIR/branches.rs:19:9
    |
 LL |         std::iter::empty().collect()
-   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
index 42a1f782d299d651e0e5a720a84ef4f1bfbbb8e9..57978edf2bf0505fc9397326d8f8a3149abd874b 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:28
+  --> $DIR/recursion4.rs:10:9
    |
 LL |     x = std::iter::empty().collect();
-   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
@@ -12,10 +14,12 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:28
+  --> $DIR/recursion4.rs:19:9
    |
 LL |     x = std::iter::empty().collect();
-   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
index c2515c40b1d778373235367e02fdfaefb501fb0b..36748fae13c9413fae09d3b016b6ed0776b460fa 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:7
+  --> $DIR/method-help-unsatisfied-bound.rs:5:5
    |
 LL |     a.unwrap();
-   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
+   |     ^ ------ required by a bound introduced by this call
+   |     |
+   |     `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
index 4c8b492247352ef5d690c79d29e3913696d93b61..283aca1b084effd3c779cb508abd58b6578b6f40 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
-  --> $DIR/defaulted-never-note.rs:30:5
+  --> $DIR/defaulted-never-note.rs:30:9
    |
 LL |     foo(_x);
-   |     ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+   |     --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `ImplementedForUnitButNotNever` is implemented for `()`
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
index aefc739a0a0b0a41d8233e8cf6adcc4452d4db34..d30ffcd3846e7f74d7b18dbddc6be52c75c0bfe3 100644 (file)
@@ -32,6 +32,7 @@ fn smeg() {
     //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
     //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()`
     //[fallback]~| NOTE this error might have been caused
+    //[fallback]~| NOTE required by a bound introduced by this call
     //[fallback]~| HELP did you intend
 }
 
index dee2b1d704b8663c8bd37f1c3a694c948c7145bb..3215c4669d5e3ba9df2959556e94a099d5effe6b 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `!: Test` is not satisfied
-  --> $DIR/diverging-fallback-no-leak.rs:17:5
+  --> $DIR/diverging-fallback-no-leak.rs:17:23
    |
 LL |     unconstrained_arg(return);
-   |     ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!`
+   |     ----------------- ^^^^^^ the trait `Test` is not implemented for `!`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Test`:
              ()
index 54abed383000dc8134137db45fa06923d8cfe74e..6dc039fc35db7c3294c82b065ec17706d83dfc81 100644 (file)
@@ -1,8 +1,12 @@
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/feature-gate-never_type_fallback.rs:10:5
+  --> $DIR/feature-gate-never_type_fallback.rs:10:9
    |
 LL |     foo(panic!())
-   |     ^^^ the trait `T` is not implemented for `()`
+   |     --- ^^^^^^^^
+   |     |   |
+   |     |   the trait `T` is not implemented for `()`
+   |     |   this tail expression is of type `_`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/feature-gate-never_type_fallback.rs:13:16
index e2045591390e1717ef21c0a9c923282048375fa9..06e902bca70fe4cd694c0fbaa404d73fe2cd4626 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `E: From<()>` is not satisfied
-  --> $DIR/never-value-fallback-issue-66757.rs:28:5
+  --> $DIR/never-value-fallback-issue-66757.rs:28:26
    |
 LL |     <E as From<_>>::from(never);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E`
+   |     -------------------- ^^^^^ the trait `From<()>` is not implemented for `E`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `From<!>` is implemented for `E`
 
index 6da3d5d96925df2666995ce535955690634d232a..6abe53127c3fb080cc64083a53995d62ff289312 100644 (file)
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
-  --> $DIR/normalization-bounds-error.rs:12:4
+  --> $DIR/normalization-bounds-error.rs:12:1
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   |    ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'d` as defined here...
   --> $DIR/normalization-bounds-error.rs:12:14
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    |                  ^^
 note: ...so that the types are compatible
-  --> $DIR/normalization-bounds-error.rs:12:4
+  --> $DIR/normalization-bounds-error.rs:12:1
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   |    ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `Visitor<'d>`
               found `Visitor<'_>`
 
index 249c2fe2fa74efe3aee0f1cce2ea6165293b3beb..c864b93dbbbe17aef49193dbc69acc3f43930b30 100644 (file)
@@ -1,10 +1,17 @@
 error[E0277]: `Rc<()>` cannot be sent between threads safely
-  --> $DIR/no-send-res-ports.rs:25:5
+  --> $DIR/no-send-res-ports.rs:25:19
    |
-LL |     thread::spawn(move|| {
-   |     ^^^^^^^^^^^^^ ------ within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`
-   |     |
-   |     `Rc<()>` cannot be sent between threads safely
+LL |       thread::spawn(move|| {
+   |       ------------- ^-----
+   |       |             |
+   |  _____|_____________within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         let y = x;
+LL | |         println!("{:?}", y);
+LL | |     });
+   | |_____^ `Rc<()>` cannot be sent between threads safely
    |
    = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`, the trait `Send` is not implemented for `Rc<()>`
 note: required because it appears within the type `Port<()>`
index 37d94cf0ebd8c515e7c1d1db7fb7a01ad1276c34..f61ee661bb7edbe205b97b68bcb99383eca8ae8c 100644 (file)
@@ -1,11 +1,13 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:23
+  --> $DIR/not-clone-closure.rs:11:17
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                 ^^^^^ ----- required by a bound introduced by this call
+   |                 |
+   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
index 43bb31afa6f54c5aec637144615596300a80254b..3b0f83b3b9a47154711b8099a2c73c02c5d6f854 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-2.rs:10:5
+  --> $DIR/not-panic-safe-2.rs:10:14
    |
 LL |     assert::<Rc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
@@ -14,10 +14,10 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-2.rs:10:5
+  --> $DIR/not-panic-safe-2.rs:10:14
    |
 LL |     assert::<Rc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
index ef1d1baf58bfc85ca1af3e25e9a0989d693cff52..9e9a12764a4b6f9e966a0c61d870b65630a82671 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-3.rs:10:5
+  --> $DIR/not-panic-safe-3.rs:10:14
    |
 LL |     assert::<Arc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
@@ -14,10 +14,10 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-3.rs:10:5
+  --> $DIR/not-panic-safe-3.rs:10:14
    |
 LL |     assert::<Arc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
index a398b44d339e79fd2e527b935bc71b5aecca42af..fc1c594d0d422041ec99e62e30ca70c5c28600ee 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-4.rs:9:5
+  --> $DIR/not-panic-safe-4.rs:9:14
    |
 LL |     assert::<&RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
@@ -14,10 +14,10 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-4.rs:9:5
+  --> $DIR/not-panic-safe-4.rs:9:14
    |
 LL |     assert::<&RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
index 9617d5dfde40df5a23f63d5d09b35de6b46252f9..cb78370b48a6cc149b97bb11cd9a05ec7b9d982e 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-5.rs:9:5
+  --> $DIR/not-panic-safe-5.rs:9:14
    |
 LL |     assert::<*const UnsafeCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required for `*const UnsafeCell<i32>` to implement `UnwindSafe`
index 09204d942d2351ca4121c13cbc0efd4ae6bfa912..7986e341eb01f602ef615fb3fa11b70e41c736d1 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-6.rs:9:5
+  --> $DIR/not-panic-safe-6.rs:9:14
    |
 LL |     assert::<*mut RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
@@ -14,10 +14,10 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-6.rs:9:5
+  --> $DIR/not-panic-safe-6.rs:9:14
    |
 LL |     assert::<*mut RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
index 6e3601d7bf4b53463496cca851371bd0b073e8ba..d47a398412fe4e7b37ffe5db36e74818506f83ea 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/multiple-impls.rs:33:18
+  --> $DIR/multiple-impls.rs:33:33
    |
 LL |     Index::index(&[] as &[i32], 2u32);
-   |     ------------ ^^^^^^^^^^^^^ trait message
+   |     ------------                ^^^^ trait message
    |     |
    |     required by a bound introduced by this call
    |
@@ -12,10 +12,10 @@ LL |     Index::index(&[] as &[i32], 2u32);
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:35:18
+  --> $DIR/multiple-impls.rs:35:33
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
-   |     ------------ ^^^^^^^^^^^^^ on impl for Foo
+   |     ------------                ^^^^^^^^^ on impl for Foo
    |     |
    |     required by a bound introduced by this call
    |
@@ -25,10 +25,10 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:37:18
+  --> $DIR/multiple-impls.rs:37:33
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
-   |     ------------ ^^^^^^^^^^^^^ on impl for Bar
+   |     ------------                ^^^^^^^^^ on impl for Bar
    |     |
    |     required by a bound introduced by this call
    |
index 396c062cfe2acfe26cc67ba8c1246802b16ee562..01315b854098ee4dee9d1c06703ce4cc3477dfac 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/on-impl.rs:22:25
+  --> $DIR/on-impl.rs:22:47
    |
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
-   |     ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     -------------------                       ^^^^ a usize is required to index into a slice
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/or-patterns/inner-or-pat.or3.stderr b/src/test/ui/or-patterns/inner-or-pat.or3.stderr
new file mode 100644 (file)
index 0000000..2236a38
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/inner-or-pat.rs:38:54
+   |
+LL |     match x {
+   |           - this expression has type `&str`
+LL |         x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
+   |                                                      ^^ expected `str`, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/inner-or-pat.or4.stderr b/src/test/ui/or-patterns/inner-or-pat.or4.stderr
new file mode 100644 (file)
index 0000000..058873f
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0408]: variable `x` is not bound in all patterns
+  --> $DIR/inner-or-pat.rs:53:37
+   |
+LL |         (x @ "red" | (x @ "blue" |  "red")) => {
+   |                       -             ^^^^^ pattern doesn't bind `x`
+   |                       |
+   |                       variable not in all patterns
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/or-patterns/inner-or-pat.rs b/src/test/ui/or-patterns/inner-or-pat.rs
new file mode 100644 (file)
index 0000000..f4cf4b0
--- /dev/null
@@ -0,0 +1,73 @@
+// revisions: or1 or2 or3 or4 or5
+// [or1] run-pass
+// [or2] run-pass
+// [or5] run-pass
+
+#![allow(unreachable_patterns)]
+#![allow(unused_variables)]
+#![allow(unused_parens)]
+#![allow(dead_code)]
+
+
+
+fn foo() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}
+
+fn bar() {
+    let x = "foo";
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" | x @ "red")) => {
+        }
+        _ => (),
+    }
+}
+
+#[cfg(or3)]
+fn zot() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
+        //[or3]~^ ERROR mismatched types
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}
+
+
+#[cfg(or4)]
+fn hey() {
+    let x = "foo";
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" |  "red")) => {
+        //[or4]~^ variable `x` is not bound in all patterns
+        }
+        _ => (),
+    }
+}
+
+fn don() {
+    enum Foo {
+        A,
+        B,
+        C,
+    }
+
+    match Foo::A {
+        | _foo @ (Foo::A | Foo::B) => {}
+        Foo::C => {}
+    };
+}
+
+fn main(){}
index 85c9fe409dbe9f68181902acc62d50267c5c24dd..a00f37ed6069c1ecc7beece0ce84427bdf26b273 100644 (file)
@@ -107,10 +107,10 @@ LL |         V = [Vec::new; { [0].len() ].len() as isize,
    |             closing delimiter possibly meant for this
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:29
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:26
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |                             ^^^ cannot infer type for type parameter `T`
+   |                          ^^ cannot infer type for type parameter `T`
 
 error[E0282]: type annotations needed
   --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14
diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs
new file mode 100644 (file)
index 0000000..fa037e5
--- /dev/null
@@ -0,0 +1,47 @@
+// edition:2018
+
+fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+//~^ ERROR expected identifier, found keyword `fn`
+//~| ERROR expected identifier, found keyword `fn`
+//~| ERROR expected identifier, found keyword `fn`
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  escape `fn` to use it as an identifier
+//~| HELP  escape `fn` to use it as an identifier
+//~| HELP  escape `fn` to use it as an identifier
+where
+G: fn(),
+    //~^ ERROR expected identifier, found keyword `fn`
+    //~| ERROR cannot find trait `r#fn` in this scope
+    //~| HELP  a trait with a similar name exists
+    //~| HELP  escape `fn` to use it as an identifier
+{}
+
+fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+//~^ ERROR expected identifier, found keyword `struct`
+//~| ERROR expected identifier, found keyword `struct`
+//~| ERROR expected identifier, found keyword `struct`
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  escape `struct` to use it as an identifier
+//~| HELP  escape `struct` to use it as an identifier
+//~| HELP  escape `struct` to use it as an identifier
+where
+    B: struct,
+    //~^ ERROR expected identifier, found keyword `struct`
+    //~| ERROR cannot find trait `r#struct` in this scope
+    //~| HELP  a trait with a similar name exists
+    //~| HELP  escape `struct` to use it as an identifier
+{}
+
+trait Struct {}
+
+fn main() {}
diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr
new file mode 100644 (file)
index 0000000..28196c7
--- /dev/null
@@ -0,0 +1,171 @@
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:10
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:27
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                           ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn())
+   |                           ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:41
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                                         ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn())
+   |                                         ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:17:4
+   |
+LL | G: fn(),
+   |    ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | G: r#fn(),
+   |    ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:10
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |          ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct)
+   |          ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:29
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                             ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct)
+   |                             ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:45
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                                             ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct)
+   |                                             ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:38:8
+   |
+LL |     B: struct,
+   |        ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL |     B: r#struct,
+   |        ++
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:10
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:17:4
+   |
+LL | G: fn(),
+   |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:27
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:41
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:10
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |          ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:38:8
+   |
+LL |     B: struct,
+   |        ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:29
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:45
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
index d96e863939c0229589ba938d3fbd0c1a1c09cb67..eba65a61803d0c9e37a43e15d7dd8684390a1a57 100644 (file)
@@ -8,7 +8,15 @@ LL |         drop::<U>(_x1);
    |                   --- closure is `FnOnce` because it moves the variable `_x1` out of its environment
 ...
 LL |     accept_fn_mut(&c1);
-   |     ------------- the requirement to implement `FnMut` derives from here
+   |     ------------- --- the requirement to implement `FnMut` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn_mut`
+  --> $DIR/move-ref-patterns-closure-captures.rs:4:31
+   |
+LL |     fn accept_fn_mut(_: &impl FnMut()) {}
+   |                               ^^^^^^^ required by this bound in `accept_fn_mut`
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
   --> $DIR/move-ref-patterns-closure-captures.rs:9:14
@@ -20,7 +28,15 @@ LL |         drop::<U>(_x1);
    |                   --- closure is `FnOnce` because it moves the variable `_x1` out of its environment
 ...
 LL |     accept_fn(&c1);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- --- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn`
+  --> $DIR/move-ref-patterns-closure-captures.rs:5:27
+   |
+LL |     fn accept_fn(_: &impl Fn()) {}
+   |                           ^^^^ required by this bound in `accept_fn`
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
   --> $DIR/move-ref-patterns-closure-captures.rs:20:14
@@ -32,7 +48,15 @@ LL |         drop::<&mut U>(_x2);
    |                        --- closure is `FnMut` because it mutates the variable `_x2` here
 ...
 LL |     accept_fn(&c2);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- --- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn`
+  --> $DIR/move-ref-patterns-closure-captures.rs:5:27
+   |
+LL |     fn accept_fn(_: &impl Fn()) {}
+   |                           ^^^^ required by this bound in `accept_fn`
 
 error: aborting due to 3 previous errors
 
index a6bd98ddb1977881ceb3a7d5d6ca5476e6a0258a..78b0beff0da39d6aae0af07deafac0e05ce2b58f 100644 (file)
@@ -5,7 +5,10 @@ LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
 LL | |
 LL | |     loop {}
 LL | | }
-   | |_^ call the function in a closure: `|| unsafe { /* code */ }`
+   | | ^
+   | | |
+   | |_call the function in a closure: `|| unsafe { /* code */ }`
+   |   required by a bound introduced by this call
    |
    = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
    = note: unsafe function cannot be called generically without an unsafe block
index 0e3bb66ab61e9d7eb2902ab7d1717a1322fa748b..aaea91ce0cbae15aac806d8e64ab459fbd531233 100644 (file)
@@ -27,7 +27,7 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi
   --> $DIR/range-1.rs:14:17
    |
 LL |     let range = *arr..;
-   |                 ^^^^^^ doesn't have a size known at compile-time
+   |                 ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `RangeFrom`
index 07f828475680fe072678147b0f0dd361880a990e..32f25faf3e8baaff1a721cae42784dc089a667d4 100644 (file)
@@ -9,9 +9,11 @@ LL |     func(&mut iter.map(|x| x + 1))
    = note: `#[warn(unconditional_recursion)]` on by default
    = help: a `loop` may express intention better if this is on purpose
 
-error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>: Iterator`
+error[E0275]: overflow evaluating the requirement `<std::ops::Range<u8> as Iterator>::Item`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
+   = note: required for `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
+   = note: 64 redundant requirements hidden
    = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/recursion/issue-95134.rs b/src/test/ui/recursion/issue-95134.rs
new file mode 100644 (file)
index 0000000..adc9c6e
--- /dev/null
@@ -0,0 +1,28 @@
+// build-fail
+// compile-flags: -Copt-level=0
+//~^^ ERROR overflow evaluating the requirement
+
+pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> {
+    if n > 15 {
+        encode_num(n / 16, &mut writer)?;
+    }
+    Ok(())
+}
+
+pub trait ExampleWriter {
+    type Error;
+}
+
+impl<'a, T: ExampleWriter> ExampleWriter for &'a mut T {
+    type Error = T::Error;
+}
+
+struct EmptyWriter;
+
+impl ExampleWriter for EmptyWriter {
+    type Error = ();
+}
+
+fn main() {
+    encode_num(69, &mut EmptyWriter).unwrap();
+}
diff --git a/src/test/ui/recursion/issue-95134.stderr b/src/test/ui/recursion/issue-95134.stderr
new file mode 100644 (file)
index 0000000..57a4986
--- /dev/null
@@ -0,0 +1,7 @@
+error[E0275]: overflow evaluating the requirement `<EmptyWriter as ExampleWriter>::Error`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95134`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
index c1dab6086ef3a97c2c35c26ce40df9d25aadc6eb..1106352037a080a43e02905ddd3ebe207d13b03e 100644 (file)
@@ -19,7 +19,8 @@ trait Trait2<'a, 'b> {
 // since for it to be WF, we would need to know that `'y: 'x`, but we
 // do not infer that.
 fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-    //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+    //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+    //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
 {
 }
 
index 6844e86653299c00810f2b600408e18710338e72..66f592c34dd070ada24e0e826d4dd25c017eac99 100644 (file)
@@ -1,3 +1,18 @@
+error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
+   |
+LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | |
+LL | |
+LL | | {
+LL | | }
+   | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |                    ++++++++++++++++++++++++
+
 error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
   --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
    |
@@ -9,6 +24,6 @@ help: consider restricting type parameter `T`
 LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
    |                    ++++++++++++++++++++++++
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index ec724cc9675f134dc8d422b7209ec448ed4c6cbe..fddc8d37f2ff7ddcc54ff02b6037af009293e144 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:18
+  --> $DIR/const-default-method-bodies.rs:24:5
    |
 LL |     NonConstImpl.a();
-   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
+   |     |
+   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
-  --> $DIR/const-default-method-bodies.rs:24:18
+  --> $DIR/const-default-method-bodies.rs:24:5
    |
 LL |     NonConstImpl.a();
-   |                  ^
+   |     ^^^^^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
index ac61c3279217b2184290258a3218a1500966ca4f..2295a822fa48b7be4b4680ba1ae38dc576f687f1 100644 (file)
@@ -5,7 +5,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     NonTrivialDrop,
-   |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
@@ -52,7 +52,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
 note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
   --> $DIR/const-drop-fail.rs:28:25
index ac61c3279217b2184290258a3218a1500966ca4f..2295a822fa48b7be4b4680ba1ae38dc576f687f1 100644 (file)
@@ -5,7 +5,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     NonTrivialDrop,
-   |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
@@ -52,7 +52,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
 note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
   --> $DIR/const-drop-fail.rs:28:25
index 174c62912fcee84aa56454dcd909d7d19d8eee90..d4fa44b4bfcb572a0650e335dcb0f98fc4b1651b 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |     ^^^^^^^^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^
+   |     ^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
index 4619dd1138e1ff2f44539ad71ab69e05167bf792..71ecd9b06945fb4150f2172f8c29b2d6804ab133 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |     ^^^^^^^^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^
+   |     ^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
index b229053eb50cfa5e3aaa1bcd6a2aaa10e6bd5499..85285ba8497779ff9e3ec17603fd894c7df2c150 100644 (file)
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
    |
 LL |         ().a()
-   |            ^ the trait `~const Tr` is not implemented for `()`
+   |         ^^ - required by a bound introduced by this call
+   |         |
+   |         the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
    |
 LL |         ().a()
-   |            ^
+   |         ^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | pub trait Tr where (): ~const Tr {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
new file mode 100644 (file)
index 0000000..1004bb2
--- /dev/null
@@ -0,0 +1,29 @@
+// revisions: nn ny yn yy
+// check-pass
+#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)]
+
+#[cfg_attr(any(yn, yy), const_trait)]
+pub trait Index {
+    type Output;
+}
+
+#[cfg_attr(any(ny, yy), const_trait)]
+pub trait IndexMut where Self: Index {
+    const C: <Self as Index>::Output;
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
+}
+
+impl Index for () { type Output = (); }
+
+impl const IndexMut for <() as Index>::Output {
+    const C: <Self as Index>::Output = ();
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+        where <Self as Index>::Output:,
+    {}
+}
+
+const C: <() as Index>::Output = ();
+
+fn main() {}
index d5b2d269730967bdbcef68fce42a968058c8508e..fd5fe25ddcfb450c477db16f0c11f4b2b049e5b4 100644 (file)
@@ -20,16 +20,16 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
    |                                    ++++++++++++
 
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:15:5
+  --> $DIR/trait-where-clause.rs:15:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
+   |            ^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause.rs:15:5
+  --> $DIR/trait-where-clause.rs:15:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^
+   |            ^
 note: required by a bound in `Foo::c`
   --> $DIR/trait-where-clause.rs:8:13
    |
@@ -57,10 +57,10 @@ LL | fn test3<T: Foo + Bar>() {
    |                 +++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:29:5
+  --> $DIR/trait-where-clause.rs:29:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^ the trait `Bar` is not implemented for `T`
+   |            ^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::c`
   --> $DIR/trait-where-clause.rs:8:13
index e8b261545499f1b3189dac58e35e341b158f1955..d63381b5f2cc9a8b92121c8ad7af9b9a205b943f 100644 (file)
@@ -3,4 +3,4 @@
 #![feature(const_trait_impl)]
 
 struct S<T: const Tr>;
-//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path
+//~^ ERROR const bounds must start with `~`
index b6b77ac4a2fb67ada81e1ff0c4c37988304074ff..31300354a573791ff479ab8421229be97734e27d 100644 (file)
@@ -1,8 +1,10 @@
-error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const`
+error: const bounds must start with `~`
   --> $DIR/without-tilde.rs:5:13
    |
 LL | struct S<T: const Tr>;
-   |             ^^^^^ expected one of 10 possible tokens
+   |             -^^^^
+   |             |
+   |             help: add `~`: `~`
 
 error: aborting due to previous error
 
index 34da1dd12df6f6debd91728e95a5572568f29ea2..fd34a59d2bd6df2252a7a238d155f7d6499b2e19 100644 (file)
@@ -1,8 +1,12 @@
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:18:17
+  --> $DIR/issue-79224.rs:18:1
    |
-LL | impl<B: ?Sized> Display for Cow<'_, B> {
-   |                 ^^^^^^^ the trait `Clone` is not implemented for `B`
+LL | / impl<B: ?Sized> Display for Cow<'_, B> {
+LL | |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+LL | |         write!(f, "foo")
+LL | |     }
+LL | | }
+   | |_^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
@@ -11,10 +15,12 @@ LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
 
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:19:12
+  --> $DIR/issue-79224.rs:19:5
    |
-LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |            ^^^^^ the trait `Clone` is not implemented for `B`
+LL | /     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+LL | |         write!(f, "foo")
+LL | |     }
+   | |_____^ the trait `Clone` is not implemented for `B`
    |
    = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
index 61cb7b25e4981eb4691c60b100cd3d34af0ba6ee..eb828bb9a2c179352d4e46b65dc26df8ef57fd68 100644 (file)
@@ -4,58 +4,58 @@ PRE EXPANSION AST STATS
 Name                Accumulated Size         Count     Item Size
 ----------------------------------------------------------------
 ExprField                 48 ( 0.6%)             1            48
-Attribute                 64 ( 0.7%)             2            32
+Crate                     56 ( 0.7%)             1            56
+Attribute                 64 ( 0.8%)             2            32
 - Normal                    32 ( 0.4%)             1
 - DocComment                32 ( 0.4%)             1
-GenericArgs               64 ( 0.7%)             1            64
-- AngleBracketed            64 ( 0.7%)             1
-Local                     72 ( 0.8%)             1            72
-WherePredicate            72 ( 0.8%)             1            72
-- BoundPredicate            72 ( 0.8%)             1
-Crate                     72 ( 0.8%)             1            72
+GenericArgs               64 ( 0.8%)             1            64
+- AngleBracketed            64 ( 0.8%)             1
+Local                     72 ( 0.9%)             1            72
+WherePredicate            72 ( 0.9%)             1            72
+- BoundPredicate            72 ( 0.9%)             1
 Arm                       96 ( 1.1%)             2            48
-ForeignItem              112 ( 1.3%)             1           112
-- Fn                       112 ( 1.3%)             1
-FieldDef                 160 ( 1.8%)             2            80
-Stmt                     160 ( 1.8%)             5            32
+ForeignItem               96 ( 1.1%)             1            96
+- Fn                        96 ( 1.1%)             1
+FieldDef                 160 ( 1.9%)             2            80
+Stmt                     160 ( 1.9%)             5            32
 - Local                     32 ( 0.4%)             1
 - MacCall                   32 ( 0.4%)             1
 - Expr                      96 ( 1.1%)             3
-Param                    160 ( 1.8%)             4            40
-FnDecl                   200 ( 2.3%)             5            40
+Param                    160 ( 1.9%)             4            40
+FnDecl                   200 ( 2.4%)             5            40
 Variant                  240 ( 2.8%)             2           120
-Block                    288 ( 3.3%)             6            48
-GenericBound             352 ( 4.0%)             4            88
-- Trait                    352 ( 4.0%)             4
-AssocItem                480 ( 5.5%)             4           120
-- TyAlias                  240 ( 2.8%)             2
-- Fn                       240 ( 2.8%)             2
-GenericParam             520 ( 6.0%)             5           104
-PathSegment              720 ( 8.3%)            30            24
-Expr                     832 ( 9.6%)             8           104
+Block                    288 ( 3.4%)             6            48
+GenericBound             352 ( 4.2%)             4            88
+- Trait                    352 ( 4.2%)             4
+AssocItem                416 ( 4.9%)             4           104
+- TyAlias                  208 ( 2.5%)             2
+- Fn                       208 ( 2.5%)             2
+GenericParam             520 ( 6.1%)             5           104
+PathSegment              720 ( 8.5%)            30            24
+Expr                     832 ( 9.8%)             8           104
 - Path                     104 ( 1.2%)             1
 - Match                    104 ( 1.2%)             1
 - Struct                   104 ( 1.2%)             1
-- Lit                      208 ( 2.4%)             2
-- Block                    312 ( 3.6%)             3
-Pat                      840 ( 9.7%)             7           120
+- Lit                      208 ( 2.5%)             2
+- Block                    312 ( 3.7%)             3
+Pat                      840 ( 9.9%)             7           120
 - Struct                   120 ( 1.4%)             1
 - Wild                     120 ( 1.4%)             1
-- Ident                    600 ( 6.9%)             5
-Ty                     1_344 (15.5%)            14            96
+- Ident                    600 ( 7.1%)             5
+Ty                     1_344 (15.9%)            14            96
 - Rptr                      96 ( 1.1%)             1
 - Ptr                       96 ( 1.1%)             1
-- ImplicitSelf             192 ( 2.2%)             2
-- Path                     960 (11.0%)            10
-Item                   1_800 (20.7%)             9           200
-- Trait                    200 ( 2.3%)             1
-- Enum                     200 ( 2.3%)             1
-- ForeignMod               200 ( 2.3%)             1
-- Impl                     200 ( 2.3%)             1
-- Fn                       400 ( 4.6%)             2
-- Use                      600 ( 6.9%)             3
+- ImplicitSelf             192 ( 2.3%)             2
+- Path                     960 (11.4%)            10
+Item                   1_656 (19.6%)             9           184
+- Trait                    184 ( 2.2%)             1
+- Enum                     184 ( 2.2%)             1
+- ForeignMod               184 ( 2.2%)             1
+- Impl                     184 ( 2.2%)             1
+- Fn                       368 ( 4.4%)             2
+- Use                      552 ( 6.5%)             3
 ----------------------------------------------------------------
-Total                  8_696
+Total                  8_456
 
 
 POST EXPANSION AST STATS
@@ -63,15 +63,15 @@ POST EXPANSION AST STATS
 Name                Accumulated Size         Count     Item Size
 ----------------------------------------------------------------
 ExprField                 48 ( 0.5%)             1            48
+Crate                     56 ( 0.6%)             1            56
 GenericArgs               64 ( 0.7%)             1            64
 - AngleBracketed            64 ( 0.7%)             1
 Local                     72 ( 0.8%)             1            72
 WherePredicate            72 ( 0.8%)             1            72
 - BoundPredicate            72 ( 0.8%)             1
-Crate                     72 ( 0.8%)             1            72
 Arm                       96 ( 1.0%)             2            48
-ForeignItem              112 ( 1.2%)             1           112
-- Fn                       112 ( 1.2%)             1
+ForeignItem               96 ( 1.0%)             1            96
+- Fn                        96 ( 1.0%)             1
 InlineAsm                120 ( 1.3%)             1           120
 Attribute                128 ( 1.4%)             4            32
 - DocComment                32 ( 0.3%)             1
@@ -82,42 +82,42 @@ Stmt                     160 ( 1.7%)             5            32
 - Semi                      32 ( 0.3%)             1
 - Expr                      96 ( 1.0%)             3
 Param                    160 ( 1.7%)             4            40
-FnDecl                   200 ( 2.1%)             5            40
-Variant                  240 ( 2.5%)             2           120
-Block                    288 ( 3.0%)             6            48
-GenericBound             352 ( 3.7%)             4            88
-- Trait                    352 ( 3.7%)             4
-AssocItem                480 ( 5.1%)             4           120
-- TyAlias                  240 ( 2.5%)             2
-- Fn                       240 ( 2.5%)             2
-GenericParam             520 ( 5.5%)             5           104
-PathSegment              792 ( 8.4%)            33            24
-Pat                      840 ( 8.9%)             7           120
+FnDecl                   200 ( 2.2%)             5            40
+Variant                  240 ( 2.6%)             2           120
+Block                    288 ( 3.1%)             6            48
+GenericBound             352 ( 3.8%)             4            88
+- Trait                    352 ( 3.8%)             4
+AssocItem                416 ( 4.5%)             4           104
+- TyAlias                  208 ( 2.3%)             2
+- Fn                       208 ( 2.3%)             2
+GenericParam             520 ( 5.7%)             5           104
+PathSegment              792 ( 8.6%)            33            24
+Pat                      840 ( 9.1%)             7           120
 - Struct                   120 ( 1.3%)             1
 - Wild                     120 ( 1.3%)             1
-- Ident                    600 ( 6.3%)             5
-Expr                     936 ( 9.9%)             9           104
+- Ident                    600 ( 6.5%)             5
+Expr                     936 (10.2%)             9           104
 - Path                     104 ( 1.1%)             1
 - Match                    104 ( 1.1%)             1
 - Struct                   104 ( 1.1%)             1
 - InlineAsm                104 ( 1.1%)             1
-- Lit                      208 ( 2.2%)             2
-- Block                    312 ( 3.3%)             3
-Ty                     1_344 (14.2%)            14            96
+- Lit                      208 ( 2.3%)             2
+- Block                    312 ( 3.4%)             3
+Ty                     1_344 (14.6%)            14            96
 - Rptr                      96 ( 1.0%)             1
 - Ptr                       96 ( 1.0%)             1
-- ImplicitSelf             192 ( 2.0%)             2
-- Path                     960 (10.2%)            10
-Item                   2_200 (23.3%)            11           200
-- Trait                    200 ( 2.1%)             1
-- Enum                     200 ( 2.1%)             1
-- ExternCrate              200 ( 2.1%)             1
-- ForeignMod               200 ( 2.1%)             1
-- Impl                     200 ( 2.1%)             1
-- Fn                       400 ( 4.2%)             2
-- Use                      800 ( 8.5%)             4
+- ImplicitSelf             192 ( 2.1%)             2
+- Path                     960 (10.5%)            10
+Item                   2_024 (22.0%)            11           184
+- Trait                    184 ( 2.0%)             1
+- Enum                     184 ( 2.0%)             1
+- ExternCrate              184 ( 2.0%)             1
+- ForeignMod               184 ( 2.0%)             1
+- Impl                     184 ( 2.0%)             1
+- Fn                       368 ( 4.0%)             2
+- Use                      736 ( 8.0%)             4
 ----------------------------------------------------------------
-Total                  9_456
+Total                  9_184
 
 
 HIR STATS
index 71facf57e8d659122dda5452473f0e0231d90021..e43a4e79bfe8c54c1e433d7ef0ddf184fe7567ce 100644 (file)
@@ -46,10 +46,12 @@ LL |     pub const fn new(pointer: P) -> Pin<P> {
    |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
-  --> $DIR/expected-boxed-future-isnt-pinned.rs:19:5
+  --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
    |
 LL |     Pin::new(x)
-   |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     -------- ^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
@@ -59,10 +61,12 @@ LL | impl<P: Deref<Target: Unpin>> Pin<P> {
    |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
-  --> $DIR/expected-boxed-future-isnt-pinned.rs:24:5
+  --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
    |
 LL |     Pin::new(Box::new(x))
-   |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     -------- ^^^^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
index ba6af8f15fa89658915f1ddad572cbfd4c52fe3f..864ab053520db2f738f08652b16d6283ff997cd5 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied
-  --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:5
+  --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:14
    |
 LL |     foo::<S>(s);
-   |     ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S`
+   |     -------- ^ the trait `for<'b> Trait` is not implemented for `&'b S`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Trait` is implemented for `&'a mut S`
    = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S`
index 5f3f62a7b7570b4107e5c7ce7569ca5d2d036468..e01102e3864ea4a6182f8fa19eaeca57ca2bd7fe 100644 (file)
@@ -21,7 +21,7 @@ error[E0277]: the trait bound `S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:13:7
    |
 LL |   foo(s);
-   |   --- ^ expected an implementor of trait `Trait`
+   |   --- ^ the trait `Trait` is not implemented for `S`
    |   |
    |   required by a bound introduced by this call
    |
index 607e7992b9f0606649baf2d8087174afa5fb98a1..62f0943d4c9d99f1466df7eab512747d0eaed232 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
   --> $DIR/issue-62843.rs:4:32
    |
 LL |     println!("{:?}", line.find(pattern));
-   |                           ---- ^^^^^^^ expected an implementor of trait `Pattern<'_>`
+   |                           ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
    |                           |
    |                           required by a bound introduced by this call
    |
index a5e6f5b5ffcb0a40fa7a4041ea1baff58bdd7042..684db23e1355f3ff31f596d73198298221964bd2 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:25
+  --> $DIR/issue-71394-no-from-impl.rs:3:20
    |
 LL |     let _: &[i8] = data.into();
-   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                    ^^^^ ---- required by a bound introduced by this call
+   |                    |
+   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
index 2c54ea6724505f9217ec07e9aebe5423c8c5b826..513bf28fb5878f34e9a4e67606f29345c17335cc 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-2.rs:11:9
    |
 LL |     foo(a);
-   |     --- ^ expected an implementor of trait `Tr`
+   |     --- ^ the trait `Tr` is not implemented for `i32`
    |     |
    |     required by a bound introduced by this call
    |
index ae0d3efca4727330c16bfc121288e8605d5ed3be..c20cc816484b4652f8caca83a3611f7e9f7b9aa3 100644 (file)
@@ -31,10 +31,12 @@ LL | #[derive(Clone)]
    |
 
 error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned
-  --> $DIR/issue-84973-blacklist.rs:17:5
+  --> $DIR/issue-84973-blacklist.rs:17:13
    |
 LL |     f_unpin(static || { yield; });
-   |     ^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]`
+   |     ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `f_unpin`
index 15559d4ae2c2f68893e928acc390ece02510ab6d..ce838bce09e7b94af11ce989a9c22a083aac8158 100644 (file)
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:11:9
    |
 LL |     bar(b);
-   |     --- ^ expected an implementor of trait `Tr`
+   |     --- ^ the trait `Tr` is not implemented for `f32`
    |     |
    |     required by a bound introduced by this call
    |
index 24c989ec3e86d51f2168e8f87988bdbda7353b4b..ae2bf5aac40b01e1715d9114f8f064198d847692 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
   --> $DIR/issue-84973.rs:6:24
    |
 LL |     let o = Other::new(f);
-   |             ---------- ^ expected an implementor of trait `SomeTrait`
+   |             ---------- ^ the trait `SomeTrait` is not implemented for `Fancy`
    |             |
    |             required by a bound introduced by this call
    |
index 44f0da27f13602f7b3bb96e914c955a8736fde07..84ecd749b0dda8af53422429fa48f93c4af8032f 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
-   |            ^^^^^^ expected an implementor of trait `IntoIterator`
+   |            ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
    |
    = note: the trait bound `[i32]: IntoIterator` is not satisfied
    = note: required for `[i32]` to implement `IntoIterator`
@@ -17,7 +17,7 @@ error[E0277]: `[i32]` is not an iterator
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
-   |            ^^^^^^ expected an implementor of trait `IntoIterator`
+   |            ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
    |
    = note: the trait bound `[i32]: IntoIterator` is not satisfied
    = note: required for `[i32]` to implement `IntoIterator`
@@ -32,7 +32,7 @@ error[E0277]: the size for values of type `[K]` cannot be known at compilation t
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
-   |             ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |             ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
    |
    = note: the trait bound `[K]: IntoIterator` is not satisfied
    = note: required for `[K]` to implement `IntoIterator`
@@ -47,7 +47,7 @@ error[E0277]: `[K]` is not an iterator
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
-   |             ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |             ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
    |
    = note: the trait bound `[K]: IntoIterator` is not satisfied
    = note: required for `[K]` to implement `IntoIterator`
index b930d22a3915eb39298983424be06de67f585d4a..125a8b44f2f0a257ee7173c41d6f075fbd43aede 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `&mut usize: Default` is not satisfied
   --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
    |
 LL |     foo(Default::default());
-   |         ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
+   |         ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize`
    |
 help: consider mutably borrowing here
    |
@@ -13,7 +13,7 @@ error[E0277]: the trait bound `&usize: Default` is not satisfied
   --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
    |
 LL |     bar(Default::default());
-   |         ^^^^^^^^^^^^^^^^ expected an implementor of trait `Default`
+   |         ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize`
    |
 help: consider borrowing here
    |
index 6b6e406130ec2934120b565060f719dca06aa87f..6ce9bfd9dcaa2b385cbaf8bf85a998e7492aecbc 100644 (file)
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
    |
 LL |     check(s);
-   |     ----- ^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^ doesn't have a size known at compile-time
    |
    = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `OsStr`
index 6583cabe18489b698f7103773edf31d33d32cf4f..f2eb651eaa426af11e62ec8bf2933e725b1a5737 100644 (file)
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `A: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9
    |
 LL |     foo(a);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `A`
    |     |
    |     required by a bound introduced by this call
    |
@@ -22,7 +22,7 @@ error[E0277]: the trait bound `B: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9
    |
 LL |     foo(b);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `B`
    |     |
    |     required by a bound introduced by this call
    |
@@ -40,7 +40,7 @@ error[E0277]: the trait bound `C: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9
    |
 LL |     foo(c);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `C`
    |     |
    |     required by a bound introduced by this call
    |
index bfbbe7fd25702b137c24df2c62af1f7998f793ef..fa7a8a2a093358aedfa136e480000cc29c23d9ce 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/check-trait-object-bounds-1.rs:12:5
+  --> $DIR/check-trait-object-bounds-1.rs:12:9
    |
 LL |     f::<dyn X<Y = str>>();
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+   |         ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `f`
index 46e8ce78874934ca3ad1344e7618cec9637d91b8..4084f69a6f04b736b2e62f42556ac082b3f2b9a9 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
-  --> $DIR/check-trait-object-bounds-2.rs:13:5
+  --> $DIR/check-trait-object-bounds-2.rs:13:9
    |
 LL |     f::<dyn for<'x> X<'x, F = i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
    |
    = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32`
 note: required by a bound in `f`
index 3ca36d5d2ff197e0439b37dc92e558b16809939a..4891ee9c29f7e28cf106f9db49bae2b214ca49e8 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/check-trait-object-bounds-4.rs:15:5
+  --> $DIR/check-trait-object-bounds-4.rs:15:9
    |
 LL |     f::<dyn X<Y = str>>();
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+   |         ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `f`
index 8befa4c5f738ba4c507111f57ea7e4d806ad21df..56acfbe80d03f6c76a646727388774c49d9b8914 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/bad-method-typaram-kind.rs:2:7
+  --> $DIR/bad-method-typaram-kind.rs:2:13
    |
 LL |     1.bar::<T>();
-   |       ^^^ `T` cannot be sent between threads safely
+   |             ^ `T` cannot be sent between threads safely
    |
 note: required by a bound in `Bar::bar`
   --> $DIR/bad-method-typaram-kind.rs:6:14
index 5ba189aa82a41233abac79fddcd172eb970c680d..f9a9347641143f891ad74b8421914c9e83781058 100644 (file)
@@ -2,7 +2,6 @@ fn strip_lf(s: &str) -> &str {
     s.strip_suffix(b'\n').unwrap_or(s)
     //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8`
     //~| NOTE expected an `FnMut<(char,)>` closure, found `u8`
-    //~| NOTE required by a bound introduced by this call
     //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8`
     //~| HELP the following other types implement trait `Pattern<'a>`:
     //~| NOTE required for `u8` to implement `Pattern<'_>`
index 41120c09fb1640e2d26a36a15bc3d8801f768081..ce9ab2d811ae112d22c7959e17374755b6e90463 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: expected a `FnMut<(char,)>` closure, found `u8`
-  --> $DIR/assoc-fn-bound-root-obligation.rs:2:20
+  --> $DIR/assoc-fn-bound-root-obligation.rs:2:7
    |
 LL |     s.strip_suffix(b'\n').unwrap_or(s)
-   |       ------------ ^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
-   |       |
-   |       required by a bound introduced by this call
+   |       ^^^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
    |
    = help: the trait `FnMut<(char,)>` is not implemented for `u8`
    = help: the following other types implement trait `Pattern<'a>`:
index 21c0ce80f8a8d5fca47da519a3e9ea30be7cec16..60ba343bb0a5c272216fd7fded1024239e86918d 100644 (file)
@@ -8,8 +8,8 @@ struct Foo<T:Trait> {
 
 fn main() {
     let foo = Foo {
-    //~^ ERROR E0277
         x: 3
+    //~^ ERROR E0277
     };
 
     let baz: Foo<usize> = loop { };
index c9068a270020d323dade48baed4b3725aa63be0e..20bbe69c059f84e1e42341aeffe3c14495edebe0 100644 (file)
@@ -11,10 +11,10 @@ LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-locals.rs:10:15
+  --> $DIR/on-structs-and-enums-locals.rs:11:12
    |
-LL |     let foo = Foo {
-   |               ^^^ the trait `Trait` is not implemented for `{integer}`
+LL |         x: 3
+   |            ^ the trait `Trait` is not implemented for `{integer}`
    |
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-locals.rs:5:14
index 8156868e048d94285523bcf81e65df25e04db978..5ef35b513e0fb532e160ca65aab7b7e349573021 100644 (file)
@@ -6,8 +6,8 @@
 
 fn main() {
     let foo = Foo {
-    //~^ ERROR E0277
         x: 3
+    //~^ ERROR E0277
     };
     let bar: Bar<f64> = return;
     //~^ ERROR E0277
index f4cc64af94f371f5d2fb1b8d7a84827a3b89e19d..3fb5decb723ea5838c776b55a98f7aa7aae056e7 100644 (file)
@@ -11,10 +11,10 @@ LL | pub enum Bar<T:Trait> {
    |                ^^^^^ required by this bound in `Bar`
 
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-xc1.rs:8:15
+  --> $DIR/on-structs-and-enums-xc1.rs:9:12
    |
-LL |     let foo = Foo {
-   |               ^^^ the trait `Trait` is not implemented for `{integer}`
+LL |         x: 3
+   |            ^ the trait `Trait` is not implemented for `{integer}`
    |
 note: required by a bound in `Foo`
   --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18
index cab0ccdf710da0c6af89c23b9d5ba1f08a0c36f7..656e0d0bf26627cb14d48f75e3017731730bb728 100644 (file)
@@ -1,18 +1,22 @@
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:26:7
+  --> $DIR/repeated-supertrait-ambig.rs:26:15
    |
 LL |     c.same_as(22)
-   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |       ------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
              <i64 as CompareTo<u64>>
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:30:7
+  --> $DIR/repeated-supertrait-ambig.rs:30:15
    |
 LL |     c.same_as(22)
-   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |       ------- ^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |       |
+   |       required by a bound introduced by this call
    |
 help: consider further restricting this bound
    |
@@ -20,20 +24,24 @@ LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
 
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:34:5
+  --> $DIR/repeated-supertrait-ambig.rs:34:37
    |
 LL |     <dyn CompareToInts>::same_as(c, 22)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |     ----------------------------    ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
              <i64 as CompareTo<u64>>
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:38:5
+  --> $DIR/repeated-supertrait-ambig.rs:38:27
    |
 LL |     CompareTo::same_as(c, 22)
-   |     ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |     ------------------    ^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |     |
+   |     required by a bound introduced by this call
    |
 help: consider further restricting this bound
    |
@@ -41,10 +49,12 @@ LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
 
 error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:42:23
+  --> $DIR/repeated-supertrait-ambig.rs:42:31
    |
 LL |     assert_eq!(22_i64.same_as(22), true);
-   |                       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `i64`
+   |                       ------- ^^ the trait `CompareTo<i32>` is not implemented for `i64`
+   |                       |
+   |                       required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
index 2b832e27c5224ac26a388ed73810dc9a4f6a77b7..e210f11b3e0c12a49439fc5f7144d2c7453802c4 100644 (file)
@@ -2,7 +2,9 @@ error[E0283]: type annotations needed
   --> $DIR/issue-77982.rs:8:10
    |
 LL |     opts.get(opt.as_ref());
-   |          ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get`
+   |          ^^^ ------------ type must be known at this point
+   |          |
+   |          cannot infer type of the type parameter `Q` declared on the associated function `get`
    |
    = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl Borrow<str> for String;
@@ -13,7 +15,7 @@ note: required by a bound in `HashMap::<K, V, S>::get`
    |
 LL |         K: Borrow<Q>,
    |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |     opts.get::<Q>(opt.as_ref());
    |             +++++
@@ -42,7 +44,7 @@ error[E0283]: type annotations needed
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
    |                                            ---------      ^^^^
    |                                            |
-   |                                            type must be known at this point
+   |                                            required by a bound introduced by this call
    |
    = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
            - impl From<Ipv4Addr> for u32;
index 9f9acf851135f4d0a3282cede8249af04ad6f6fa..5fcd090a8349fe181c5e4e252c83f8a479bee39b 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
-  --> $DIR/issue-91594.rs:10:6
+  --> $DIR/issue-91594.rs:10:1
    |
 LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
    |
    = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
 note: required for `Foo` to implement `Component<Foo>`
index 9062a0fab630a3103d5e8ac839e5b1a54dd90b40..146d38d076a3ccb1e7696c60c940fdf82cab8773 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:22
+  --> $DIR/issue-97576.rs:8:18
    |
 LL |             bar: bar.into(),
-   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
+   |                  ^^^ ---- required by a bound introduced by this call
+   |                  |
+   |                  the trait `From<impl ToString>` is not implemented for `String`
    |
    = note: required for `impl ToString` to implement `Into<String>`
 
index cbec35934214886d693b3d5a6625b1ec0ca16033..6e6172eea474660f78edbb631b50bf94ea6b948e 100644 (file)
@@ -13,7 +13,9 @@ error[E0283]: type annotations needed
   --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
    |
 LL |     test(22, std::default::Default::default());
-   |     ^^^^ cannot infer type of the type parameter `U` declared on the function `test`
+   |     ^^^^     -------------------------------- type must be known at this point
+   |     |
+   |     cannot infer type of the type parameter `U` declared on the function `test`
    |
 note: multiple `impl`s satisfying `i32: Convert<_>` found
   --> $DIR/multidispatch-convert-ambig-dest.rs:8:1
@@ -30,10 +32,10 @@ LL | fn test<T,U>(_: T, _: U)
    |    ---- required by a bound in this
 LL | where T : Convert<U>
    |           ^^^^^^^^^^ required by this bound in `test`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
    |
-LL |     test::<T, U>(22, std::default::Default::default());
-   |         ++++++++
+LL |     test::<i32, U>(22, std::default::Default::default());
+   |         ++++++++++
 
 error: aborting due to 2 previous errors
 
index bf7c3bcc6aa9b46c1e22bed723b2200027108a12..41fc3600fcd54e295148bce95c0602fa20068f81 100644 (file)
@@ -61,7 +61,7 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:48:13
    |
 LL |     is_send(Box::new(TestType));
-   |     ------- ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Send`
+   |     ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique<dummy2::TestType>`
    |     |
    |     required by a bound introduced by this call
    |
index d4d9b4967478ada0cedd6115bc14d1a5638b3b4b..747e2477b9cf14193c2c806ec2d87c09136e8f32 100644 (file)
@@ -19,13 +19,13 @@ LL + fn check<T: Iterator, U>() {
    |
 
 error[E0277]: the size for values of type `U` cannot be known at compilation time
-  --> $DIR/suggest-where-clause.rs:10:5
+  --> $DIR/suggest-where-clause.rs:10:20
    |
 LL | fn check<T: Iterator, U: ?Sized>() {
    |                       - this type parameter needs to be `std::marker::Sized`
 ...
 LL |     mem::size_of::<Misc<U>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `Misc<U>`
   --> $DIR/suggest-where-clause.rs:3:8
index b1359ea586583be07c55190e2a5efb0a2c946cfe..17ffcf64177e3fa13e7311aeb08058a5d47a2c2d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
-  --> $DIR/references.rs:19:37
+  --> $DIR/references.rs:19:52
    |
 LL |     assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
-   |                                     ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
+   |                                                    ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, true, true, true, true>` is not implemented for `&'static Unit`
 note: required by a bound in `is_maybe_transmutable`
index 53610985f31da73e6da9d56cf90e31bc596c1a95..220b3929c88574e338bd7266cafdb08ffa84abca 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
-  --> $DIR/type-params-in-different-spaces-2.rs:10:9
+  --> $DIR/type-params-in-different-spaces-2.rs:10:16
    |
 LL |         Tr::op(u)
-   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |         ------ ^ the trait `Tr<U>` is not implemented for `Self`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: consider further restricting `Self`
    |
@@ -10,10 +12,12 @@ LL |     fn test<U>(u: U) -> Self where Self: Tr<U> {
    |                              +++++++++++++++++
 
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
-  --> $DIR/type-params-in-different-spaces-2.rs:16:9
+  --> $DIR/type-params-in-different-spaces-2.rs:16:16
    |
 LL |         Tr::op(u)
-   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |         ------ ^ the trait `Tr<U>` is not implemented for `Self`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: consider further restricting `Self`
    |
index 6bb5e1f54272b6257604508bacd675a51d3bb558..b9fca1a1b54b81b6e3013fc669cf786a3d635aaf 100644 (file)
@@ -12,10 +12,10 @@ LL | fn is_sync<T: Sync>() {}
    |               ^^^^ required by this bound in `is_sync`
 
 error[E0277]: `UnsafeCell<u8>` cannot be shared between threads safely
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:5
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:15
    |
 LL |     is_sync::<MyTypeWUnsafe>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely
    |
    = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell<u8>`
 note: required because it appears within the type `MyTypeWUnsafe`
@@ -30,10 +30,10 @@ LL | fn is_sync<T: Sync>() {}
    |               ^^^^ required by this bound in `is_sync`
 
 error[E0277]: `Managed` cannot be shared between threads safely
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:15
    |
 LL |     is_sync::<MyTypeManaged>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
    |
    = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`
 note: required because it appears within the type `MyTypeManaged`
index c6f9b3661a232a84efb7c90365134c266866aa3c..f08c81bc1e937f7bada03d02c80886a7d277c649 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: cannot add `u32` to `i32`
-  --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+  --> $DIR/ufcs-qpath-self-mismatch.rs:4:31
    |
 LL |     <i32 as Add<u32>>::add(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+   |     ----------------------    ^ no implementation for `i32 + u32`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
index 85ff49d61a3fff949b9c8b77f7e9e30baeb1eea4..635ebbb71d0701bc2e4bc439e4d43dfb29d0785d 100644 (file)
@@ -6,7 +6,17 @@ LL |     let c = || drop(y.0);
    |             |
    |             this closure implements `FnOnce`, not `Fn`
 LL |     foo(c);
-   |     --- the requirement to implement `Fn` derives from here
+   |     --- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14
+   |
+LL | fn foo<F>(f: F)
+   |    --- required by a bound in this
+LL |     where F: Fn()
+   |              ^^^^ required by this bound in `foo`
 
 error: aborting due to previous error
 
index a4f0c400d7310979668bc3f433d6599dc1ad8363..037022a91fcd07053546f6c35ba907eccc728ed1 100644 (file)
@@ -11,10 +11,10 @@ LL | union U<T: Copy> {
    |            ^^^^ required by this bound in `U`
 
 error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:13:13
+  --> $DIR/union-generic.rs:13:17
    |
 LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |                 ^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
    |
 note: required by a bound in `U`
   --> $DIR/union-generic.rs:6:12
index a4f0c400d7310979668bc3f433d6599dc1ad8363..037022a91fcd07053546f6c35ba907eccc728ed1 100644 (file)
@@ -11,10 +11,10 @@ LL | union U<T: Copy> {
    |            ^^^^ required by this bound in `U`
 
 error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:13:13
+  --> $DIR/union-generic.rs:13:17
    |
 LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |                 ^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
    |
 note: required by a bound in `U`
   --> $DIR/union-generic.rs:6:12
index 6960255d98797492815899c0bebc915e1feedd59..a7f57e3fd15667d81396d6c40e1293565bde5a18 100644 (file)
@@ -12,9 +12,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/unsized-exprs.rs:24:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
-   |     ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
index d7af558eef42aa45ecd9469b3b6a71016935ba90..f5491552a45d2ed89134cab0d3b53c6adbde58f7 100644 (file)
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |      - ^^ doesn't have a size known at compile-time
-   |      |
-   |      required by a bound introduced by this call
+   |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = help: unsized fn params are gated as an unstable feature
index d7b95f55769fdc600f7b37ff9ec22b43e9844215..50060e53a49d64fe15b62716e0de51e8545baa98 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:15
+  --> $DIR/issue-71659.rs:30:13
    |
 LL |     let x = x.cast::<[i32]>();
-   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |             ^ ---- required by a bound introduced by this call
+   |             |
+   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15
index 7d0a2cb85b6120b65f8d5d6b57f403c86476ecc4..97618ed05ed38148ebeedc74007b5d15d4240caf 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `MyCall: Callback` is not satisfied
-  --> $DIR/issue-75707.rs:15:5
+  --> $DIR/issue-75707.rs:15:9
    |
 LL |     f::<dyn Processing<Call = MyCall>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
    |
 note: required by a bound in `f`
   --> $DIR/issue-75707.rs:9:9
index 0221ef16b4965f30eb121b81b0b3843c40e6f42e..b4772605432584914fb79fa5a6ec9f6a8fdeeca6 100644 (file)
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:11:11
    |
 LL |     foo11("bar", &"baz");
-   |     ----- ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
@@ -17,9 +15,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:13:19
    |
 LL |     foo12(&"bar", "baz");
-   |     -----         ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
@@ -32,9 +28,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:16:11
    |
 LL |     foo21("bar", &"baz");
-   |     ----- ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<str>`
@@ -47,9 +41,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:18:19
    |
 LL |     foo22(&"bar", "baz");
-   |     -----         ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<str>`
index c9510e92fecb42bb1e1d32cfb3d747c8bf4c2a27..dff1b0a5112a486afbe414923b2089082b90780f 100644 (file)
@@ -25,10 +25,10 @@ LL + fn foo2<T>() { not_sized::<Foo<T>>() }
    |
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/unsized-struct.rs:13:24
+  --> $DIR/unsized-struct.rs:13:35
    |
 LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
-   |         -              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         -                         ^^^^^^ doesn't have a size known at compile-time
    |         |
    |         this type parameter needs to be `std::marker::Sized`
    |
index d64091b15eb1fc2c747980353ca77551e9d41dea..9ad1ac6b4df61c29ee7a57f10ee6284cc4c4c99d 100644 (file)
@@ -79,14 +79,12 @@ LL | fn f5<Y: ?Sized>(x: &Y) {}
    |        ++++++++
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized3.rs:40:8
+  --> $DIR/unsized3.rs:40:5
    |
 LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(*x1, 34));
-   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -106,9 +104,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
    |        - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(32, *x1));
-   |     --  ^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^^^^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
index b03023b5fd14f707d69bdeb7c927305ae6a36cac..78312a0910594105190791d871ecc48b7a1a1814 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
    |
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
index f431deee73f9adc9cd05a56161788d931e6d32ca..8c47ed6d4317a7ad4c80db1beba2ea2541c91525 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `X: Foo<X>` is not satisfied
-  --> $DIR/where-clause-method-substituion.rs:20:7
+  --> $DIR/where-clause-method-substituion.rs:20:16
    |
 LL |     1.method::<X>();
-   |       ^^^^^^ the trait `Foo<X>` is not implemented for `X`
+   |                ^ the trait `Foo<X>` is not implemented for `X`
    |
 note: required by a bound in `Bar::method`
   --> $DIR/where-clause-method-substituion.rs:6:34
index c13552bc26eee730aba31adce9137ebcfc8bc9b6..e90502977ff6a3ebdbe4ab7ca0dca87d738b3b4a 100644 (file)
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `Bar: Eq` is not satisfied
-  --> $DIR/where-clauses-method-unsatisfied.rs:18:14
+  --> $DIR/where-clauses-method-unsatisfied.rs:18:7
    |
 LL |     x.equals(&x);
-   |       ------ ^^ the trait `Eq` is not implemented for `Bar`
-   |       |
-   |       required by a bound introduced by this call
+   |       ^^^^^^ the trait `Eq` is not implemented for `Bar`
    |
 note: required by a bound in `Foo::<T>::equals`
   --> $DIR/where-clauses-method-unsatisfied.rs:11:52
index b8f617897a66953b9026c02f7a8f93a2e9611f63..ab88e64b152d3704c35db96dbbc6efaaed67773f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b8f617897a66953b9026c02f7a8f93a2e9611f63
+Subproject commit ab88e64b152d3704c35db96dbbc6efaaed67773f
index 41ba9a847e67a0bc2bf4167aac630782e8e3be2a..f5c1ee5fdd12130d28e470299c246d0846de8ef5 100644 (file)
@@ -49,10 +49,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span {
 }
 
 /// Returns attributes that are within `outer_span`.
-pub(crate) fn filter_inline_attrs(
-    attrs: &[ast::Attribute],
-    outer_span: Span,
-) -> Vec<ast::Attribute> {
+pub(crate) fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> ast::AttrVec {
     attrs
         .iter()
         .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi())
index 8d41c881589e5564c97fd3220a4c72b1ff0b63d0..b6530c69243ed1c16c056cffdc358763fb7b8e15 100644 (file)
@@ -116,7 +116,7 @@ pub(crate) struct UseTree {
     // Additional fields for top level use items.
     // Should we have another struct for top-level use items rather than reusing this?
     visibility: Option<ast::Visibility>,
-    attrs: Option<Vec<ast::Attribute>>,
+    attrs: Option<ast::AttrVec>,
 }
 
 impl PartialEq for UseTree {
@@ -417,7 +417,7 @@ fn from_ast(
         list_item: Option<ListItem>,
         visibility: Option<ast::Visibility>,
         opt_lo: Option<BytePos>,
-        attrs: Option<Vec<ast::Attribute>>,
+        attrs: Option<ast::AttrVec>,
     ) -> UseTree {
         let span = if let Some(lo) = opt_lo {
             mk_sp(lo, a.span.hi())
index 81da724329f02edc918bc6eaf5b91e76238dc011..7a0d1736c59a66ae729b9305bb049c71921d925c 100644 (file)
@@ -26,7 +26,7 @@
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
     pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-    inner_attr: Vec<ast::Attribute>,
+    inner_attr: ast::AttrVec,
     pub(crate) span: Span,
 }
 
@@ -35,7 +35,7 @@ pub(crate) fn new(
         mod_span: Span,
         ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
         mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-        mod_attrs: Cow<'a, Vec<ast::Attribute>>,
+        mod_attrs: Cow<'a, ast::AttrVec>,
     ) -> Self {
         let inner_attr = mod_attrs
             .iter()
@@ -158,7 +158,7 @@ fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResol
                         module_item.item.span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
                         Cow::Owned(vec![]),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
             }
@@ -185,7 +185,7 @@ fn visit_mod_outside_ast(
                         span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
                         Cow::Owned(vec![]),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
             }
index 268c72649a65a9c93155429dd76e71facc761f2c..e0bd065518b3db5f7e9016ba428e755086c8a923 100644 (file)
@@ -109,7 +109,7 @@ pub(crate) fn parse_file_as_module(
         sess: &'a ParseSess,
         path: &Path,
         span: Span,
-    ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
+    ) -> Result<(ast::AttrVec, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
             let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
index 3cf44a2d7d1efffaf74c8ae9c223876042d109ef..dee58ff2fb510718c4161ec6e649db3a1bbdde98 100644 (file)
@@ -125,16 +125,13 @@ fn should_ignore(line: &str) -> bool {
 
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
 fn long_line_is_ok(extension: &str, is_error_code: bool, max_columns: usize, line: &str) -> bool {
-    if extension != "md" || is_error_code {
-        if line_is_url(is_error_code, max_columns, line) || should_ignore(line) {
-            return true;
-        }
-    } else if extension == "md" {
+    match extension {
+        // fluent files are allowed to be any length
+        "ftl" => true,
         // non-error code markdown is allowed to be any length
-        return true;
+        "md" if !is_error_code => true,
+        _ => line_is_url(is_error_code, max_columns, line) || should_ignore(line),
     }
-
-    false
 }
 
 enum Directive {
@@ -230,7 +227,7 @@ fn skip(path: &Path) -> bool {
     super::walk(path, &mut skip, &mut |entry, contents| {
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
-        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css"];
+        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"];
         if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") {
             return;
         }