]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #85989 - jyn514:gitignore-cleanup, r=ehuss
authorYuki Okushi <jtitor@2k36.org>
Tue, 8 Jun 2021 04:26:30 +0000 (13:26 +0900)
committerGitHub <noreply@github.com>
Tue, 8 Jun 2021 04:26:30 +0000 (13:26 +0900)
Remove rustfmt tests from top-level .gitattributes

These are tracked in src/tools/rustfmt/.gitattributes already, they
don't need to be listed twice.

r? `@ehuss` since you suggested adding them in https://github.com/rust-lang/rust/pull/82208/#issuecomment-841440199; I think it should be ok now that bors isn't trying to merge the `subtree add` changes.

cc `@calebcartwright`

422 files changed:
Cargo.lock
compiler/rustc_ast/src/ast_like.rs
compiler/rustc_ast/src/tokenstream.rs
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_builtin_macros/src/test.rs
compiler/rustc_codegen_cranelift/src/archive.rs
compiler/rustc_codegen_cranelift/src/driver/aot.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_cranelift/src/toolchain.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/back/archive.rs
compiler/rustc_codegen_llvm/src/lib.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm/mod.rs
compiler/rustc_codegen_ssa/Cargo.toml
compiler/rustc_codegen_ssa/src/back/archive.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/linker.rs
compiler/rustc_codegen_ssa/src/back/metadata.rs
compiler/rustc_codegen_ssa/src/back/rpath.rs
compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
compiler/rustc_codegen_ssa/src/back/symbol_export.rs
compiler/rustc_codegen_ssa/src/back/write.rs
compiler/rustc_codegen_ssa/src/base.rs
compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
compiler/rustc_codegen_ssa/src/lib.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_codegen_ssa/src/target_features.rs
compiler/rustc_codegen_ssa/src/traits/backend.rs
compiler/rustc_data_structures/src/obligation_forest/mod.rs
compiler/rustc_data_structures/src/sync.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes/E0759.md
compiler/rustc_errors/src/json.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/tests.rs
compiler/rustc_incremental/src/persist/fs.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/equate.rs
compiler/rustc_infer/src/infer/glb.rs
compiler/rustc_infer/src/infer/lub.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/sub.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/queries.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/build.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_llvm/src/lib.rs
compiler/rustc_macros/src/serialize.rs
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/cstore.rs
compiler/rustc_middle/src/middle/exported_symbols.rs
compiler/rustc_middle/src/mir/mono.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/_match.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/query/mod.rs
compiler/rustc_middle/src/ty/query/on_disk_cache.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_mir/src/borrow_check/constraints/graph.rs
compiler/rustc_mir/src/borrow_check/constraints/mod.rs
compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs
compiler/rustc_mir/src/borrow_check/type_check/mod.rs
compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs
compiler/rustc_mir/src/lib.rs
compiler/rustc_mir/src/transform/check_consts/validation.rs
compiler/rustc_mir/src/transform/const_goto.rs
compiler/rustc_mir/src/transform/deduplicate_blocks.rs
compiler/rustc_mir/src/transform/early_otherwise_branch.rs
compiler/rustc_mir/src/transform/generator.rs
compiler/rustc_mir/src/transform/inline.rs
compiler/rustc_mir/src/transform/match_branches.rs
compiler/rustc_mir/src/transform/multiple_return_terminators.rs
compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
compiler/rustc_mir/src/transform/remove_zsts.rs
compiler/rustc_mir/src/transform/simplify.rs
compiler/rustc_mir/src/transform/simplify_try.rs
compiler/rustc_mir/src/transform/unreachable_prop.rs
compiler/rustc_parse/src/parser/attr_wrapper.rs
compiler/rustc_parse/src/parser/expr.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_parse/src/parser/nonterminal.rs
compiler/rustc_parse/src/parser/path.rs
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_query_system/src/dep_graph/serialized.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_serialize/src/collection_impls.rs
compiler/rustc_serialize/src/json.rs
compiler/rustc_serialize/src/serialize.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/crate_disambiguator.rs [new file with mode: 0644]
compiler/rustc_span/src/def_id.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/lib.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/abi/call/bpf.rs [new file with mode: 0644]
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_target/src/asm/bpf.rs [new file with mode: 0644]
compiler/rustc_target/src/asm/mod.rs
compiler/rustc_target/src/spec/bpf_base.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/bpfeb_unknown_none.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/bpfel_unknown_none.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/msp430_none_elf.rs
compiler/rustc_target/src/spec/wasm_base.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/demand.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
config.toml.example
library/alloc/benches/vec.rs
library/alloc/src/collections/vec_deque/pair_slices.rs
library/alloc/src/lib.rs
library/alloc/src/string.rs
library/alloc/src/vec/mod.rs
library/alloc/src/vec/splice.rs
library/alloc/tests/vec.rs
library/core/src/array/mod.rs
library/core/src/char/methods.rs
library/core/src/lib.rs
library/core/src/ops/range.rs
library/core/src/slice/mod.rs
library/core/tests/array.rs
library/core/tests/iter/adapters/zip.rs
library/panic_abort/src/lib.rs
library/panic_unwind/src/lib.rs
library/proc_macro/src/lib.rs
library/std/Cargo.toml
library/std/src/lib.rs
library/std/src/path.rs
library/std/src/sys/unix/mod.rs
library/std/src/time.rs
library/term/src/lib.rs
library/test/src/formatters/pretty.rs
library/test/src/formatters/terse.rs
library/test/src/lib.rs
library/test/src/tests.rs
library/test/src/types.rs
library/unwind/build.rs
src/bootstrap/bin/rustc.rs
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/bootstrap/util.rs
src/doc/rustc/src/codegen-options/index.md
src/doc/rustc/src/platform-support.md
src/doc/rustdoc/src/documentation-tests.md
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/force-warns.md [new file with mode: 0644]
src/doc/unstable-book/src/language-features/external-doc.md [deleted file]
src/doc/unstable-book/src/library-features/asm.md
src/etc/htmldocck.py
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/llvm-project
src/test/assembly/asm/bpf-types.rs [new file with mode: 0644]
src/test/codegen/bpf-alu32.rs [new file with mode: 0644]
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
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/slice_len.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt [new file with mode: 0644]
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt
src/test/run-make-fulldeps/coverage/conditions.rs
src/test/run-make-fulldeps/coverage/generator.rs [new file with mode: 0644]
src/test/run-make-fulldeps/coverage/generics.rs
src/test/run-make-fulldeps/coverage/loops_branches.rs
src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
src/test/run-make-fulldeps/include_bytes_deps/main.rs
src/test/run-make-fulldeps/save-analysis/foo.rs
src/test/run-make/raw-dylib/Makefile [new file with mode: 0644]
src/test/run-make/raw-dylib/driver.rs [new file with mode: 0644]
src/test/run-make/raw-dylib/extern_1.c [new file with mode: 0644]
src/test/run-make/raw-dylib/extern_2.c [new file with mode: 0644]
src/test/run-make/raw-dylib/lib.rs [new file with mode: 0644]
src/test/run-make/raw-dylib/output.txt [new file with mode: 0644]
src/test/run-make/unstable-flag-required/Makefile
src/test/run-make/unstable-flag-required/force-warns.stderr [new file with mode: 0644]
src/test/rustdoc-ui/check.rs
src/test/rustdoc-ui/check.stderr
src/test/rustdoc-ui/doc-include-suggestion.rs [new file with mode: 0644]
src/test/rustdoc-ui/doc-include-suggestion.stderr [new file with mode: 0644]
src/test/rustdoc-ui/doc-spotlight.fixed
src/test/rustdoc-ui/doc-spotlight.rs
src/test/rustdoc-ui/doc-spotlight.stderr
src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
src/test/rustdoc-ui/issue-80992.stdout
src/test/rustdoc-ui/no-crate-level-doc-lint.rs
src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
src/test/rustdoc-ui/no-run-flag.stdout
src/test/rustdoc-ui/test-type.rs [new file with mode: 0644]
src/test/rustdoc-ui/test-type.stdout [new file with mode: 0644]
src/test/rustdoc/auxiliary/external-cross-doc.md
src/test/rustdoc/auxiliary/external-cross.rs
src/test/rustdoc/auxiliary/external-doc.md
src/test/rustdoc/external-doc.rs
src/test/rustdoc/intra-doc/associated-items.rs
src/test/rustdoc/intra-doc/builtin-macros.rs
src/test/rustdoc/intra-doc/field.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/generic-params.rs
src/test/rustdoc/intra-doc/non-path-primitives.rs
src/test/rustdoc/intra-doc/prim-assoc.rs
src/test/rustdoc/intra-doc/prim-methods-external-core.rs
src/test/rustdoc/intra-doc/prim-methods-local.rs
src/test/rustdoc/intra-doc/prim-methods.rs
src/test/rustdoc/intra-doc/prim-precedence.rs
src/test/rustdoc/intra-doc/primitive-disambiguators.rs
src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
src/test/rustdoc/intra-doc/pub-use.rs
src/test/rustdoc/intra-doc/trait-item.rs
src/test/rustdoc/intra-doc/true-false.rs
src/test/rustdoc/intra-link-prim-self.rs
src/test/rustdoc/primitive-link.rs
src/test/rustdoc/primitive-reexport.rs
src/test/rustdoc/unindent.rs
src/test/ui/c-variadic/variadic-ffi-4.stderr
src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs
src/test/ui/consts/miri_unleashed/tls.stderr
src/test/ui/deprecation/deprecation-lint.rs
src/test/ui/deprecation/deprecation-lint.stderr
src/test/ui/deprecation/suggestion.fixed
src/test/ui/deprecation/suggestion.rs
src/test/ui/deprecation/suggestion.stderr
src/test/ui/error-codes/E0121.stderr
src/test/ui/extern/external-doc-error.rs [deleted file]
src/test/ui/extern/external-doc-error.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-external_doc.rs [deleted file]
src/test/ui/feature-gates/feature-gate-external_doc.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr [new file with mode: 0644]
src/test/ui/generator/print/generator-print-verbose-1.stderr
src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
src/test/ui/layout/issue-84108.rs [new file with mode: 0644]
src/test/ui/layout/issue-84108.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-warning.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-allowed-warning.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-deny-by-default-lint.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-group.rs [new file with mode: 0644]
src/test/ui/lint/force-warn/force-warn-group.stderr [new file with mode: 0644]
src/test/ui/lint/lint-ctypes-fn.rs
src/test/ui/lint/lint-ctypes-fn.stderr
src/test/ui/lint/lint-stability-deprecated.stderr
src/test/ui/lto-duplicate-symbols.stderr
src/test/ui/manual/manual-link-unsupported-kind.rs [new file with mode: 0644]
src/test/ui/manual/manual-link-unsupported-kind.stderr [new file with mode: 0644]
src/test/ui/match/match-ref-mut-invariance.nll.stderr
src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
src/test/ui/nll/type-check-pointer-coercions.stderr
src/test/ui/nll/type-check-pointer-comparisons.stderr
src/test/ui/parser/issue-84104.rs [new file with mode: 0644]
src/test/ui/parser/issue-84104.stderr [new file with mode: 0644]
src/test/ui/parser/issue-84148-1.rs [new file with mode: 0644]
src/test/ui/parser/issue-84148-1.stderr [new file with mode: 0644]
src/test/ui/parser/issue-84148-2.rs [new file with mode: 0644]
src/test/ui/parser/issue-84148-2.stderr [new file with mode: 0644]
src/test/ui/parser/unmatched-langle-1.rs [new file with mode: 0644]
src/test/ui/parser/unmatched-langle-1.stderr [new file with mode: 0644]
src/test/ui/parser/unmatched-langle-2.rs [new file with mode: 0644]
src/test/ui/parser/unmatched-langle-2.stderr [new file with mode: 0644]
src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs [new file with mode: 0644]
src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout [new file with mode: 0644]
src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs [deleted file]
src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr [deleted file]
src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs [deleted file]
src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr [deleted file]
src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs [new file with mode: 0644]
src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr [new file with mode: 0644]
src/test/ui/rustdoc/deny-invalid-doc-attrs.rs [new file with mode: 0644]
src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr [new file with mode: 0644]
src/test/ui/rustdoc/doc-inline-extern-crate.rs [new file with mode: 0644]
src/test/ui/rustdoc/doc-inline-extern-crate.stderr [new file with mode: 0644]
src/test/ui/simd/issue-85915-simd-ptrs.rs [new file with mode: 0644]
src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs [new file with mode: 0644]
src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs [new file with mode: 0644]
src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr [new file with mode: 0644]
src/test/ui/simd/simd-type-wide-ptr.rs [new file with mode: 0644]
src/test/ui/simd/simd-type-wide-ptr.stderr [new file with mode: 0644]
src/test/ui/simd/wasm-simd-indirect.rs [new file with mode: 0644]
src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
src/test/ui/stability-attribute/generics-default-stability.stderr
src/test/ui/suggestions/format-borrow.rs
src/test/ui/suggestions/format-borrow.stderr
src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs [new file with mode: 0644]
src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr [new file with mode: 0644]
src/test/ui/symbol-names/basic.legacy.stderr
src/test/ui/symbol-names/basic.rs
src/test/ui/symbol-names/basic.v0.stderr
src/test/ui/symbol-names/const-generics-demangling.rs
src/test/ui/symbol-names/const-generics-demangling.stderr
src/test/ui/symbol-names/impl1.rs
src/test/ui/symbol-names/impl1.v0.stderr
src/test/ui/symbol-names/issue-60925.legacy.stderr
src/test/ui/symbol-names/issue-60925.rs
src/test/ui/symbol-names/issue-60925.v0.stderr
src/test/ui/symbol-names/issue-75326.rs
src/test/ui/symbol-names/issue-75326.v0.stderr
src/test/ui/symbol-names/trait-objects.v0.stderr
src/test/ui/target-feature/gate.rs
src/test/ui/target-feature/gate.stderr
src/test/ui/test-attrs/test-type.rs [new file with mode: 0644]
src/test/ui/test-attrs/test-type.run.stdout [new file with mode: 0644]
src/test/ui/test-panic-abort-nocapture.run.stdout
src/test/ui/test-panic-abort.run.stdout
src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr
src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
src/tools/build-manifest/src/main.rs
src/tools/clippy/clippy_lints/src/missing_doc.rs
src/tools/clippy/tests/ui/missing-doc-crate.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs

index 4150285b4619f0638df5e5c5899257485da9316d..270297f73b63e94f6bd08411d56d1e9a916249df 100644 (file)
@@ -294,7 +294,7 @@ dependencies = [
  "rand 0.8.3",
  "rustc-workspace-hack",
  "rustfix",
- "semver 1.0.1",
+ "semver 1.0.3",
  "serde",
  "serde_ignored",
  "serde_json",
@@ -652,9 +652,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.43"
+version = "0.1.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65af2dcae4779003dfa91aedc6ade7bdc7ba685944e50a8b4f9380df376a4466"
+checksum = "787187ae221adfcda34b03006f1617099e4ae26b50e5a4db282496014ab75837"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -2154,9 +2154,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.3.3"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
 
 [[package]]
 name = "memmap2"
@@ -2359,6 +2359,17 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
+[[package]]
+name = "object"
+version = "0.25.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e"
+dependencies = [
+ "crc32fast",
+ "indexmap",
+ "memchr",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.7.2"
@@ -3701,7 +3712,7 @@ dependencies = [
  "itertools 0.9.0",
  "jobserver",
  "libc",
- "object",
+ "object 0.25.2",
  "pathdiff",
  "rustc_apfloat",
  "rustc_ast",
@@ -4681,9 +4692,9 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.1"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d023dabf011d5dcb5ac64e3685d97d3b0ef412911077a2851455c6098524a723"
+checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe"
 dependencies = [
  "serde",
 ]
@@ -4912,7 +4923,7 @@ dependencies = [
  "hermit-abi",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.22.0",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
index 945a44ab66371ccbae0b8e3cec39975ae5168396..d586426d70ef053c4825ee567eb7289b2e48c18e 100644 (file)
@@ -82,7 +82,8 @@ fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
             Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtVis(vis) => vis.tokens_mut(),
-            _ => panic!("Called tokens_mut on {:?}", self),
+            Nonterminal::NtBlock(block) => block.tokens_mut(),
+            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None,
         }
     }
 }
index 2d463a4588c561ecd8e1df5da5eca65000a10b5e..5d994dbad4d1fcf128851668679a54ced7f92e41 100644 (file)
@@ -218,8 +218,7 @@ pub fn to_tokenstream(&self) -> TokenStream {
                 AttrAnnotatedTokenTree::Attributes(data) => {
                     let mut outer_attrs = Vec::new();
                     let mut inner_attrs = Vec::new();
-                    let attrs: Vec<_> = data.attrs.clone().into();
-                    for attr in attrs {
+                    for attr in &data.attrs {
                         match attr.style {
                             crate::AttrStyle::Outer => {
                                 assert!(
@@ -264,7 +263,7 @@ pub fn to_tokenstream(&self) -> TokenStream {
                                 // so we never reach this code.
 
                                 let mut builder = TokenStreamBuilder::new();
-                                for inner_attr in &inner_attrs {
+                                for inner_attr in inner_attrs {
                                     builder.push(inner_attr.tokens().to_tokenstream());
                                 }
                                 builder.push(delim_tokens.clone());
index 4996c2195efdf2402f8cd32c816671c31623f553..664e138b39dc81bfc53af267177e0eec27462ea3 100644 (file)
@@ -318,7 +318,6 @@ macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
                 }}
 
                 gate_doc!(
-                    include => external_doc
                     cfg => doc_cfg
                     masked => doc_masked
                     notable_trait => doc_notable_trait
index e845f9ec55ad58ea20191f90de89c81ed11554bd..99544ddb66e66f4445d7fec260b46aa435055017 100644 (file)
@@ -254,6 +254,10 @@ pub fn expand_test_or_bench(
                                         "allow_fail",
                                         cx.expr_bool(sp, should_fail(&cx.sess, &item)),
                                     ),
+                                    // compile_fail: true | false
+                                    field("compile_fail", cx.expr_bool(sp, false)),
+                                    // no_run: true | false
+                                    field("no_run", cx.expr_bool(sp, false)),
                                     // should_panic: ...
                                     field(
                                         "should_panic",
index bd54adc53ee2a58eba807aa045dd51bcf098b9d4..22897c43e7ef917cdc456010c9129d35aca97c1e 100644 (file)
@@ -254,6 +254,15 @@ enum BuilderKind {
             }
         }
     }
+
+    fn inject_dll_import_lib(
+        &mut self,
+        _lib_name: &str,
+        _dll_imports: &[rustc_middle::middle::cstore::DllImport],
+        _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
+    ) {
+        bug!("injecting dll imports is not supported");
+    }
 }
 
 impl<'a> ArArchiveBuilder<'a> {
index 9cf51d15c8ca0a8e99595398d76580bad62d7067..6676d88602c45d9e34991e80ce25e6cf158077e5 100644 (file)
@@ -177,21 +177,6 @@ pub(crate) fn run_aot(
     metadata: EncodedMetadata,
     need_metadata_module: bool,
 ) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
-    use rustc_span::symbol::sym;
-
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
-    let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
-    let windows_subsystem = subsystem.map(|subsystem| {
-        if subsystem != sym::windows && subsystem != sym::console {
-            tcx.sess.fatal(&format!(
-                "invalid windows subsystem `{}`, only \
-                                    `windows` and `console` are allowed",
-                subsystem
-            ));
-        }
-        subsystem.to_string()
-    });
-
     let mut work_products = FxHashMap::default();
 
     let cgus = if tcx.sess.opts.output_types.should_codegen() {
@@ -307,12 +292,10 @@ pub(crate) fn run_aot(
 
     Box::new((
         CodegenResults {
-            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules,
             allocator_module,
             metadata_module,
             metadata,
-            windows_subsystem,
             linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
             crate_info: CrateInfo::new(tcx),
         },
index 4ee887cd5afaef819a65ed333e6bbbed3e8e8b16..904efed5bd98c6e45800273a60a59da92529968a 100644 (file)
@@ -28,8 +28,7 @@
 use rustc_codegen_ssa::CodegenResults;
 use rustc_errors::ErrorReported;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_session::config::OutputFilenames;
 use rustc_session::Session;
 
@@ -164,17 +163,14 @@ fn init(&self, sess: &Session) {
         }
     }
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, _providers: &mut Providers) {}
-    fn provide_extern(&self, _providers: &mut Providers) {}
-
     fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
         vec![]
     }
 
+    fn print_version(&self) {
+        println!("Cranelift version: {}", cranelift_codegen::VERSION);
+    }
+
     fn codegen_crate(
         &self,
         tcx: TyCtxt<'_>,
@@ -222,7 +218,7 @@ fn link(
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_name.as_str(),
+            &codegen_results.crate_info.local_crate_name.as_str(),
         );
 
         Ok(())
index 484a9b699a0aa41aa73c412610bae16e2155d456..f86236ef3eafc6eee6c6a476bb19d2fed1f13ce4 100644 (file)
@@ -2,9 +2,8 @@
 
 use std::path::PathBuf;
 
-use rustc_middle::bug;
+use rustc_codegen_ssa::back::link::linker_and_flavor;
 use rustc_session::Session;
-use rustc_target::spec::LinkerFlavor;
 
 /// Tries to infer the path of a binary for the target toolchain from the linker name.
 pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
@@ -30,89 +29,3 @@ pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
 
     linker
 }
-
-// Adapted from https://github.com/rust-lang/rust/blob/5db778affee7c6600c8e7a177c48282dab3f6292/src/librustc_codegen_ssa/back/link.rs#L848-L931
-fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
-    fn infer_from(
-        sess: &Session,
-        linker: Option<PathBuf>,
-        flavor: Option<LinkerFlavor>,
-    ) -> Option<(PathBuf, LinkerFlavor)> {
-        match (linker, flavor) {
-            (Some(linker), Some(flavor)) => Some((linker, flavor)),
-            // only the linker flavor is known; use the default linker for the selected flavor
-            (None, Some(flavor)) => Some((
-                PathBuf::from(match flavor {
-                    LinkerFlavor::Em => {
-                        if cfg!(windows) {
-                            "emcc.bat"
-                        } else {
-                            "emcc"
-                        }
-                    }
-                    LinkerFlavor::Gcc => {
-                        if cfg!(any(target_os = "solaris", target_os = "illumos")) {
-                            // On historical Solaris systems, "cc" may have
-                            // been Sun Studio, which is not flag-compatible
-                            // with "gcc".  This history casts a long shadow,
-                            // and many modern illumos distributions today
-                            // ship GCC as "gcc" without also making it
-                            // available as "cc".
-                            "gcc"
-                        } else {
-                            "cc"
-                        }
-                    }
-                    LinkerFlavor::Ld => "ld",
-                    LinkerFlavor::Msvc => "link.exe",
-                    LinkerFlavor::Lld(_) => "lld",
-                    LinkerFlavor::PtxLinker => "rust-ptx-linker",
-                }),
-                flavor,
-            )),
-            (Some(linker), None) => {
-                let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
-                    sess.fatal("couldn't extract file stem from specified linker")
-                });
-
-                let flavor = if stem == "emcc" {
-                    LinkerFlavor::Em
-                } else if stem == "gcc"
-                    || stem.ends_with("-gcc")
-                    || stem == "clang"
-                    || stem.ends_with("-clang")
-                {
-                    LinkerFlavor::Gcc
-                } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
-                    LinkerFlavor::Ld
-                } else if stem == "link" || stem == "lld-link" {
-                    LinkerFlavor::Msvc
-                } else if stem == "lld" || stem == "rust-lld" {
-                    LinkerFlavor::Lld(sess.target.lld_flavor)
-                } else {
-                    // fall back to the value in the target spec
-                    sess.target.linker_flavor
-                };
-
-                Some((linker, flavor))
-            }
-            (None, None) => None,
-        }
-    }
-
-    // linker and linker flavor specified via command line have precedence over what the target
-    // specification specifies
-    if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
-        return ret;
-    }
-
-    if let Some(ret) = infer_from(
-        sess,
-        sess.target.linker.clone().map(PathBuf::from),
-        Some(sess.target.linker_flavor),
-    ) {
-        return ret;
-    }
-
-    bug!("Not enough information provided to determine how to invoke the linker");
-}
index 0aef77129d8c6c818f269e39ff1d0fd2ed999bf3..ecf62ed213df82aec1daaf5b5b1cf958d0f9054c 100644 (file)
@@ -288,6 +288,7 @@ fn codegen_inline_asm(
                 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
                 InlineAsmArch::SpirV => {}
                 InlineAsmArch::Wasm32 => {}
+                InlineAsmArch::Bpf => {}
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
@@ -593,6 +594,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
+            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
             InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
                 bug!("LLVM backend does not support SPIR-V")
             }
@@ -661,6 +664,7 @@ fn modifier_to_llvm(
         },
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
+        InlineAsmRegClass::Bpf(_) => None,
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
@@ -708,6 +712,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
+        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
+        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
index 261affe2c427e1f01aa63dfe57cad8d5a7a4e9f3..64416bced31d024dcd8819dbeaa6f35e0f2cf8ad 100644 (file)
@@ -8,9 +8,11 @@
 use std::str;
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
-use crate::llvm::{self, ArchiveKind};
+use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
+use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_middle::middle::cstore::DllImport;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -61,6 +63,17 @@ fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) ->
     }
 }
 
+/// Map machine type strings to values of LLVM's MachineTypes enum.
+fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
+    match cpu {
+        "x86_64" => LLVMMachineType::AMD64,
+        "x86" => LLVMMachineType::I386,
+        "aarch64" => LLVMMachineType::ARM64,
+        "arm" => LLVMMachineType::ARM,
+        _ => panic!("unsupported cpu type {}", cpu),
+    }
+}
+
 impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
     /// Creates a new static archive, ready for modifying the archive specified
     /// by `config`.
@@ -175,6 +188,74 @@ fn build(mut self) {
             self.config.sess.fatal(&format!("failed to build archive: {}", e));
         }
     }
+
+    fn inject_dll_import_lib(
+        &mut self,
+        lib_name: &str,
+        dll_imports: &[DllImport],
+        tmpdir: &MaybeTempDir,
+    ) {
+        let output_path = {
+            let mut output_path: PathBuf = tmpdir.as_ref().to_path_buf();
+            output_path.push(format!("{}_imports", lib_name));
+            output_path.with_extension("lib")
+        };
+
+        // we've checked for \0 characters in the library name already
+        let dll_name_z = CString::new(lib_name).unwrap();
+        // All import names are Rust identifiers and therefore cannot contain \0 characters.
+        // FIXME: when support for #[link_name] implemented, ensure that import.name values don't
+        // have any \0 characters
+        let import_name_vector: Vec<CString> = dll_imports
+            .iter()
+            .map(if self.config.sess.target.arch == "x86" {
+                |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap()
+            } else {
+                |import: &DllImport| CString::new(import.name.to_string()).unwrap()
+            })
+            .collect();
+
+        let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
+
+        tracing::trace!("invoking LLVMRustWriteImportLibrary");
+        tracing::trace!("  dll_name {:#?}", dll_name_z);
+        tracing::trace!("  output_path {}", output_path.display());
+        tracing::trace!(
+            "  import names: {}",
+            dll_imports.iter().map(|import| import.name.to_string()).collect::<Vec<_>>().join(", "),
+        );
+
+        let ffi_exports: Vec<LLVMRustCOFFShortExport> = import_name_vector
+            .iter()
+            .map(|name_z| LLVMRustCOFFShortExport::from_name(name_z.as_ptr()))
+            .collect();
+        let result = unsafe {
+            crate::llvm::LLVMRustWriteImportLibrary(
+                dll_name_z.as_ptr(),
+                output_path_z.as_ptr(),
+                ffi_exports.as_ptr(),
+                ffi_exports.len(),
+                llvm_machine_type(&self.config.sess.target.arch) as u16,
+                !self.config.sess.target.is_like_msvc,
+            )
+        };
+
+        if result == crate::llvm::LLVMRustResult::Failure {
+            self.config.sess.fatal(&format!(
+                "Error creating import library for {}: {}",
+                lib_name,
+                llvm::last_error().unwrap_or("unknown LLVM error".to_string())
+            ));
+        }
+
+        self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
+            self.config.sess.fatal(&format!(
+                "failed to add native library {}: {}",
+                output_path.display(),
+                e
+            ));
+        });
+    }
 }
 
 impl<'a> LlvmArchiveBuilder<'a> {
index 728f1224dd86eb566f312a419c4b4c5e4fa4ad1f..776cb2ee99bcbf727f6ce65d5fa6124454eed4f6 100644 (file)
@@ -29,8 +29,8 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{ErrorReported, FatalError, Handler};
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::middle::cstore::EncodedMetadata;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
@@ -248,13 +248,6 @@ fn target_features(&self, sess: &Session) -> Vec<Symbol> {
         target_features(sess)
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, _providers: &mut ty::query::Providers) {}
-    fn provide_extern(&self, _providers: &mut ty::query::Providers) {}
-
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -304,7 +297,7 @@ fn link(
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_name.as_str(),
+            &codegen_results.crate_info.local_crate_name.as_str(),
         );
 
         Ok(())
index 54ef1a284689af60084f14f7a6894c6591c5b91f..91923251018a898671319bc486f5b3e98f651f5e 100644 (file)
@@ -29,6 +29,31 @@ pub enum LLVMRustResult {
     Success,
     Failure,
 }
+
+// Rust version of the C struct with the same name in rustc_llvm/llvm-wrapper/RustWrapper.cpp.
+#[repr(C)]
+pub struct LLVMRustCOFFShortExport {
+    pub name: *const c_char,
+}
+
+impl LLVMRustCOFFShortExport {
+    pub fn from_name(name: *const c_char) -> LLVMRustCOFFShortExport {
+        LLVMRustCOFFShortExport { name }
+    }
+}
+
+/// Translation of LLVM's MachineTypes enum, defined in llvm\include\llvm\BinaryFormat\COFF.h.
+///
+/// We include only architectures supported on Windows.
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum LLVMMachineType {
+    AMD64 = 0x8664,
+    I386 = 0x14c,
+    ARM64 = 0xaa64,
+    ARM = 0x01c0,
+}
+
 // Consts for the LLVM CallConv type, pre-cast to usize.
 
 /// LLVM CallingConv::ID. Should we wrap this?
@@ -582,11 +607,6 @@ struct InvariantOpaque<'a> {
 extern "C" {
     pub type PassManagerBuilder;
 }
-extern "C" {
-    pub type ObjectFile;
-}
-#[repr(C)]
-pub struct SectionIterator<'a>(InvariantOpaque<'a>);
 extern "C" {
     pub type Pass;
 }
@@ -1703,35 +1723,6 @@ pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
 
     pub fn LLVMDisposeMessage(message: *mut c_char);
 
-    // Stuff that's in llvm-wrapper/ because it's not upstream yet.
-
-    /// Opens an object file.
-    pub fn LLVMCreateObjectFile(
-        MemBuf: &'static mut MemoryBuffer,
-    ) -> Option<&'static mut ObjectFile>;
-    /// Closes an object file.
-    pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile);
-
-    /// Enumerates the sections in an object file.
-    pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>;
-    /// Destroys a section iterator.
-    pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>);
-    /// Returns `true` if the section iterator is at the end of the section
-    /// list:
-    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool;
-    /// Moves the section iterator to point to the next section.
-    pub fn LLVMMoveToNextSection(SI: &SectionIterator<'_>);
-    /// Returns the current section size.
-    pub fn LLVMGetSectionSize(SI: &SectionIterator<'_>) -> c_ulonglong;
-    /// Returns the current section contents as a string buffer.
-    pub fn LLVMGetSectionContents(SI: &SectionIterator<'_>) -> *const c_char;
-
-    /// Reads the given file and returns it as a memory buffer. Use
-    /// LLVMDisposeMemoryBuffer() to get rid of it.
-    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(
-        Path: *const c_char,
-    ) -> Option<&'static mut MemoryBuffer>;
-
     pub fn LLVMStartMultithreaded() -> Bool;
 
     /// Returns a string describing the last error caused by an LLVMRust* call.
@@ -2236,12 +2227,6 @@ pub fn LLVMRustArchiveIteratorNext(
     pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>);
     pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
 
-    #[allow(improper_ctypes)]
-    pub fn LLVMRustGetSectionName(
-        SI: &SectionIterator<'_>,
-        data: &mut Option<std::ptr::NonNull<c_char>>,
-    ) -> size_t;
-
     #[allow(improper_ctypes)]
     pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
 
@@ -2305,6 +2290,15 @@ pub fn LLVMRustArchiveMemberNew(
     ) -> &'a mut RustArchiveMember<'a>;
     pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>);
 
+    pub fn LLVMRustWriteImportLibrary(
+        ImportName: *const c_char,
+        Path: *const c_char,
+        Exports: *const LLVMRustCOFFShortExport,
+        NumExports: usize,
+        Machine: u16,
+        MinGW: bool,
+    ) -> LLVMRustResult;
+
     pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine);
 
     pub fn LLVMRustBuildOperandBundleDef(
index bb9c6d47373babf23fc20ca22477da4f3f0390b7..38d56f872116933dccdae216c772ecb547b0aa1a 100644 (file)
@@ -150,50 +150,6 @@ pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) {
     }
 }
 
-// Memory-managed interface to object files.
-
-pub struct ObjectFile {
-    pub llof: &'static mut ffi::ObjectFile,
-}
-
-unsafe impl Send for ObjectFile {}
-
-impl ObjectFile {
-    // This will take ownership of llmb
-    pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
-        unsafe {
-            let llof = LLVMCreateObjectFile(llmb)?;
-            Some(ObjectFile { llof })
-        }
-    }
-}
-
-impl Drop for ObjectFile {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
-        }
-    }
-}
-
-// Memory-managed interface to section iterators.
-
-pub struct SectionIter<'a> {
-    pub llsi: &'a mut SectionIterator<'a>,
-}
-
-impl Drop for SectionIter<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
-        }
-    }
-}
-
-pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> {
-    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
-}
-
 pub fn set_section(llglobal: &Value, section_name: &str) {
     let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
     unsafe {
index 3a677a2437c57233aa2f5b316721be21f5f6803f..9bd5764f0730dbff3e4772db5a50b0947b2afbe7 100644 (file)
@@ -35,6 +35,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 
 [dependencies.object]
-version = "0.22.0"
+version = "0.25.2"
 default-features = false
-features = ["read_core", "elf", "macho", "pe", "unaligned", "archive"]
+features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
index c197d48d4ea64da30bbea8ef8ff51978f08a74fa..63f457bb979e3ff693f0702c228ca693545a9553 100644 (file)
@@ -1,3 +1,5 @@
+use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_middle::middle::cstore::DllImport;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -57,4 +59,11 @@ fn add_rlib(
     fn update_symbols(&mut self);
 
     fn build(self);
+
+    fn inject_dll_import_lib(
+        &mut self,
+        lib_name: &str,
+        dll_imports: &[DllImport],
+        tmpdir: &MaybeTempDir,
+    );
 }
index 32275e9b073481d97b4b7c41fc960ac500743fc8..6a2005b4d23ed01bdb7d93eed3d3f25b2b835adf 100644 (file)
@@ -1,9 +1,9 @@
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::Handler;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
+use rustc_middle::middle::cstore::{DllImport, LibSource};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -14,6 +14,7 @@
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
+use rustc_target::abi::Endian;
 use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
 use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
 };
 
 use cc::windows_registry;
+use object::elf;
+use object::write::Object;
+use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
 use tempfile::Builder as TempFileBuilder;
 
+use std::cmp::Ordering;
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
@@ -278,9 +283,9 @@ pub fn each_linked_rlib(
 /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
 /// directory being searched for `extern crate` (observing an incomplete file).
 /// The returned path is the temporary file containing the complete metadata.
-pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeTempDir) -> PathBuf {
+pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> PathBuf {
     let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
-    let result = fs::write(&out_filename, &metadata.raw_data);
+    let result = fs::write(&out_filename, metadata);
 
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -339,6 +344,12 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
         }
     }
 
+    for (raw_dylib_name, raw_dylib_imports) in
+        collate_raw_dylibs(&codegen_results.crate_info.used_libraries)
+    {
+        ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
+    }
+
     // After adding all files to the archive, we need to update the
     // symbol table of the archive.
     ab.update_symbols();
@@ -366,9 +377,11 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     // code above.
     match flavor {
         RlibFlavor::Normal => {
-            // Instead of putting the metadata in an object file section, rlibs
-            // contain the metadata in a separate file.
-            ab.add_file(&emit_metadata(sess, &codegen_results.metadata, tmpdir));
+            // metadata in rlib files is wrapped in a "dummy" object file for
+            // the target platform so the rlib can be processed entirely by
+            // normal linkers for the platform.
+            let metadata = create_metadata_file(sess, &codegen_results.metadata.raw_data);
+            ab.add_file(&emit_metadata(sess, &metadata, tmpdir));
 
             // After adding all files to the archive, we need to update the
             // symbol table of the archive. This currently dies on macOS (see
@@ -385,8 +398,188 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             }
         }
     }
+    return ab;
+
+    // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
+    // creates a dylib crate type it will pass `--whole-archive` (or the
+    // platform equivalent) to include all object files from an rlib into the
+    // final dylib itself. This causes linkers to iterate and try to include all
+    // files located in an archive, so if metadata is stored in an archive then
+    // it needs to be of a form that the linker will be able to process.
+    //
+    // Note, though, that we don't actually want this metadata to show up in any
+    // final output of the compiler. Instead this is purely for rustc's own
+    // metadata tracking purposes.
+    //
+    // With the above in mind, each "flavor" of object format gets special
+    // handling here depending on the target:
+    //
+    // * MachO - macos-like targets will insert the metadata into a section that
+    //   is sort of fake dwarf debug info. Inspecting the source of the macos
+    //   linker this causes these sections to be skipped automatically because
+    //   it's not in an allowlist of otherwise well known dwarf section names to
+    //   go into the final artifact.
+    //
+    // * WebAssembly - we actually don't have any container format for this
+    //   target. WebAssembly doesn't support the `dylib` crate type anyway so
+    //   there's no need for us to support this at this time. Consequently the
+    //   metadata bytes are simply stored as-is into an rlib.
+    //
+    // * COFF - Windows-like targets create an object with a section that has
+    //   the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
+    //   ever sees the section it doesn't process it and it's removed.
+    //
+    // * ELF - All other targets are similar to Windows in that there's a
+    //   `SHF_EXCLUDE` flag we can set on sections in an object file to get
+    //   automatically removed from the final output.
+    //
+    // Note that this metdata format is kept in sync with
+    // `rustc_codegen_ssa/src/back/metadata.rs`.
+    fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec<u8> {
+        let endianness = match sess.target.options.endian {
+            Endian::Little => Endianness::Little,
+            Endian::Big => Endianness::Big,
+        };
+        let architecture = match &sess.target.arch[..] {
+            "arm" => Architecture::Arm,
+            "aarch64" => Architecture::Aarch64,
+            "x86" => Architecture::I386,
+            "s390x" => Architecture::S390x,
+            "mips" => Architecture::Mips,
+            "mips64" => Architecture::Mips64,
+            "x86_64" => {
+                if sess.target.pointer_width == 32 {
+                    Architecture::X86_64_X32
+                } else {
+                    Architecture::X86_64
+                }
+            }
+            "powerpc" => Architecture::PowerPc,
+            "powerpc64" => Architecture::PowerPc64,
+            "riscv32" => Architecture::Riscv32,
+            "riscv64" => Architecture::Riscv64,
+            "sparc64" => Architecture::Sparc64,
+
+            // This is used to handle all "other" targets. This includes targets
+            // in two categories:
+            //
+            // * Some targets don't have support in the `object` crate just yet
+            //   to write an object file. These targets are likely to get filled
+            //   out over time.
+            //
+            // * Targets like WebAssembly don't support dylibs, so the purpose
+            //   of putting metadata in object files, to support linking rlibs
+            //   into dylibs, is moot.
+            //
+            // In both of these cases it means that linking into dylibs will
+            // not be supported by rustc. This doesn't matter for targets like
+            // WebAssembly and for targets not supported by the `object` crate
+            // yet it means that work will need to be done in the `object` crate
+            // to add a case above.
+            _ => return metadata.to_vec(),
+        };
+
+        if sess.target.is_like_osx {
+            let mut file = Object::new(BinaryFormat::MachO, architecture, endianness);
+
+            let section =
+                file.add_section(b"__DWARF".to_vec(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        } else if sess.target.is_like_windows {
+            const IMAGE_SCN_LNK_REMOVE: u32 = 0;
+            let mut file = Object::new(BinaryFormat::Coff, architecture, endianness);
+
+            let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.section_mut(section).flags =
+                SectionFlags::Coff { characteristics: IMAGE_SCN_LNK_REMOVE };
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        } else {
+            const SHF_EXCLUDE: u64 = 0x80000000;
+            let mut file = Object::new(BinaryFormat::Elf, architecture, endianness);
+
+            match &sess.target.arch[..] {
+                // copied from `mipsel-linux-gnu-gcc foo.c -c` and
+                // inspecting the resulting `e_flags` field.
+                "mips" => {
+                    let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+                // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
+                "mips64" => {
+                    let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+
+                // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though
+                // that the `+d` target feature represents whether the double
+                // float abi is enabled.
+                "riscv64" if sess.target.options.features.contains("+d") => {
+                    let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+
+                _ => {}
+            }
+
+            let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.section_mut(section).flags = SectionFlags::Elf { sh_flags: SHF_EXCLUDE };
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        }
+    }
+}
+
+/// Extract all symbols defined in raw-dylib libraries, collated by library name.
+///
+/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
+/// then the CodegenResults value contains one NativeLib instance for each block.  However, the
+/// linker appears to expect only a single import library for each library used, so we need to
+/// collate the symbols together by library name before generating the import libraries.
+fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> {
+    let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default();
+
+    for lib in used_libraries {
+        if lib.kind == NativeLibKind::RawDylib {
+            let name = lib.name.unwrap_or_else(||
+                bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier")
+            );
+            let name = if matches!(lib.verbatim, Some(true)) {
+                name.to_string()
+            } else {
+                format!("{}.dll", name)
+            };
+            dylib_table
+                .entry(name)
+                .or_default()
+                .extend(lib.dll_imports.iter().map(|import| import.name));
+        }
+    }
 
-    ab
+    // FIXME: when we add support for ordinals, fix this to propagate ordinals.  Also figure out
+    // what we should do if we have two DllImport values with the same name but different
+    // ordinals.
+    let mut result = dylib_table
+        .into_iter()
+        .map(|(lib_name, imported_names)| {
+            let mut names = imported_names
+                .iter()
+                .map(|name| DllImport { name: *name, ordinal: None })
+                .collect::<Vec<_>>();
+            names.sort_unstable_by(|a: &DllImport, b: &DllImport| {
+                match a.name.as_str().cmp(&b.name.as_str()) {
+                    Ordering::Equal => a.ordinal.cmp(&b.ordinal),
+                    x => x,
+                }
+            });
+            (lib_name, names)
+        })
+        .collect::<Vec<_>>();
+    result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
+        a.0.cmp(&b.0)
+    });
+    result
 }
 
 /// Create a static archive.
@@ -865,7 +1058,7 @@ fn escape_string(s: &[u8]) -> String {
     }
 }
 
-fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
+fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
     // On macOS the runtimes are distributed as dylibs which should be linked to
     // both executables and dynamic shared objects. Everywhere else the runtimes
     // are currently distributed as static liraries which should be linked to
@@ -954,7 +1147,8 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
         && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
 }
 
-fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
+// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
+pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
     fn infer_from(
         sess: &Session,
         linker: Option<PathBuf>,
@@ -989,6 +1183,7 @@ fn infer_from(
                     LinkerFlavor::Msvc => "link.exe",
                     LinkerFlavor::Lld(_) => "lld",
                     LinkerFlavor::PtxLinker => "rust-ptx-linker",
+                    LinkerFlavor::BpfLinker => "bpf-linker",
                 }),
                 flavor,
             )),
@@ -1005,6 +1200,8 @@ fn infer_from(
                     || stem.ends_with("-clang")
                 {
                     LinkerFlavor::Gcc
+                } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
+                    LinkerFlavor::Lld(LldFlavor::Wasm)
                 } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
                     LinkerFlavor::Ld
                 } else if stem == "link" || stem == "lld-link" {
@@ -1484,55 +1681,6 @@ fn add_local_crate_metadata_objects(
     }
 }
 
-/// Link native libraries corresponding to the current crate and all libraries corresponding to
-/// all its dependency crates.
-/// FIXME: Consider combining this with the functions above adding object files for the local crate.
-fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'a>>(
-    cmd: &mut dyn Linker,
-    sess: &'a Session,
-    crate_type: CrateType,
-    codegen_results: &CodegenResults,
-    tmpdir: &Path,
-) {
-    // Take careful note of the ordering of the arguments we pass to the linker
-    // here. Linkers will assume that things on the left depend on things to the
-    // right. Things on the right cannot depend on things on the left. This is
-    // all formally implemented in terms of resolving symbols (libs on the right
-    // resolve unknown symbols of libs on the left, but not vice versa).
-    //
-    // For this reason, we have organized the arguments we pass to the linker as
-    // such:
-    //
-    // 1. The local object that LLVM just generated
-    // 2. Local native libraries
-    // 3. Upstream rust libraries
-    // 4. Upstream native libraries
-    //
-    // The rationale behind this ordering is that those items lower down in the
-    // list can't depend on items higher up in the list. For example nothing can
-    // depend on what we just generated (e.g., that'd be a circular dependency).
-    // Upstream rust libraries are not allowed to depend on our local native
-    // libraries as that would violate the structure of the DAG, in that
-    // scenario they are required to link to them as well in a shared fashion.
-    //
-    // Note that upstream rust libraries may contain native dependencies as
-    // well, but they also can't depend on what we just started to add to the
-    // link line. And finally upstream native libraries can't depend on anything
-    // in this DAG so far because they're only dylibs and dylibs can only depend
-    // on other dylibs (e.g., other native deps).
-    //
-    // If -Zlink-native-libraries=false is set, then the assumption is that an
-    // external build system already has the native dependencies defined, and it
-    // will provide them to the linker itself.
-    if sess.opts.debugging_opts.link_native_libraries {
-        add_local_native_libraries(cmd, sess, codegen_results);
-    }
-    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
-    if sess.opts.debugging_opts.link_native_libraries {
-        add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
-    }
-}
-
 /// Add sysroot and other globally set directories to the directory search list.
 fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
     // The default library location, we need this to find the runtime.
@@ -1567,36 +1715,27 @@ fn add_rpath_args(
 ) {
     // FIXME (#2397): At some point we want to rpath our guesses as to
     // where extern libraries might live, based on the
-    // addl_lib_search_paths
+    // add_lib_search_paths
     if sess.opts.cg.rpath {
-        let target_triple = sess.opts.target_triple.triple();
-        let mut get_install_prefix_lib_path = || {
-            let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = rustc_target::target_rustlib_path(&sess.sysroot, target_triple).join("lib");
-            let mut path = PathBuf::from(install_prefix);
-            path.push(&tlib);
-
-            path
-        };
         let mut rpath_config = RPathConfig {
             used_crates: &codegen_results.crate_info.used_crates_dynamic,
             out_filename: out_filename.to_path_buf(),
             has_rpath: sess.target.has_rpath,
             is_like_osx: sess.target.is_like_osx,
             linker_is_gnu: sess.target.linker_is_gnu,
-            get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
         };
         cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
     }
 }
 
 /// Produce the linker command line containing linker path and arguments.
-/// `NO-OPT-OUT` marks the arguments that cannot be removed from the command line
-/// by the user without creating a custom target specification.
-/// `OBJECT-FILES` specify whether the arguments can add object files.
-/// `CUSTOMIZATION-POINT` means that arbitrary arguments defined by the user
-/// or by the target spec can be inserted here.
-/// `AUDIT-ORDER` - need to figure out whether the option is order-dependent or not.
+///
+/// When comments in the function say "order-(in)dependent" they mean order-dependence between
+/// options and libraries/object files. For example `--whole-archive` (order-dependent) applies
+/// to specific libraries passed after it, and `-o` (output file, order-independent) applies
+/// to the linking process as a whole.
+/// Order-independent options may still override each other in order-dependent fashion,
+/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
 fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     path: &Path,
     flavor: LinkerFlavor,
@@ -1614,16 +1753,151 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
     let link_output_kind = link_output_kind(sess, crate_type);
 
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
+    // ------------ Early order-dependent options ------------
+
+    // If we're building something like a dynamic library then some platforms
+    // need to make sure that all symbols are exported correctly from the
+    // dynamic library.
+    // Must be passed before any libraries to prevent the symbols to export from being thrown away,
+    // at least on some platforms (e.g. windows-gnu).
+    cmd.export_symbols(tmpdir, crate_type);
+
+    // Can be used for adding custom CRT objects or overriding order-dependent options above.
+    // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
+    // introduce a target spec option for order-independent linker options and migrate built-in
+    // specs to it.
     add_pre_link_args(cmd, sess, flavor);
 
-    // NO-OPT-OUT, OBJECT-FILES-NO
+    // ------------ Object code and libraries, order-dependent ------------
+
+    // Pre-link CRT objects.
+    add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
+
+    // Sanitizer libraries.
+    add_sanitizer_libraries(sess, crate_type, cmd);
+
+    // Object code from the current crate.
+    // Take careful note of the ordering of the arguments we pass to the linker
+    // here. Linkers will assume that things on the left depend on things to the
+    // right. Things on the right cannot depend on things on the left. This is
+    // all formally implemented in terms of resolving symbols (libs on the right
+    // resolve unknown symbols of libs on the left, but not vice versa).
+    //
+    // For this reason, we have organized the arguments we pass to the linker as
+    // such:
+    //
+    // 1. The local object that LLVM just generated
+    // 2. Local native libraries
+    // 3. Upstream rust libraries
+    // 4. Upstream native libraries
+    //
+    // The rationale behind this ordering is that those items lower down in the
+    // list can't depend on items higher up in the list. For example nothing can
+    // depend on what we just generated (e.g., that'd be a circular dependency).
+    // Upstream rust libraries are not supposed to depend on our local native
+    // libraries as that would violate the structure of the DAG, in that
+    // scenario they are required to link to them as well in a shared fashion.
+    // (The current implementation still doesn't prevent it though, see the FIXME below.)
+    //
+    // Note that upstream rust libraries may contain native dependencies as
+    // well, but they also can't depend on what we just started to add to the
+    // link line. And finally upstream native libraries can't depend on anything
+    // in this DAG so far because they can only depend on other native libraries
+    // and such dependencies are also required to be specified.
+    add_local_crate_regular_objects(cmd, codegen_results);
+    add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
+    add_local_crate_allocator_objects(cmd, codegen_results);
+
+    // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
+    // at the point at which they are specified on the command line.
+    // Must be passed before any (dynamic) libraries to have effect on them.
+    // On Solaris-like systems, `-z ignore` acts as both `--as-needed` and `--gc-sections`
+    // so it will ignore unreferenced ELF sections from relocatable objects.
+    // For that reason, we put this flag after metadata objects as they would otherwise be removed.
+    // FIXME: Support more fine-grained dead code removal on Solaris/illumos
+    // and move this option back to the top.
+    cmd.add_as_needed();
+
+    // FIXME: Move this below to other native libraries
+    // (or alternatively link all native libraries after their respective crates).
+    // This change is somewhat breaking in practice due to local static libraries being linked
+    // as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
+    if sess.opts.debugging_opts.link_native_libraries {
+        add_local_native_libraries(cmd, sess, codegen_results);
+    }
+
+    // Rust libraries.
+    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
+
+    // Native libraries linked with `#[link]` attributes at and `-l` command line options.
+    // If -Zlink-native-libraries=false is set, then the assumption is that an
+    // external build system already has the native dependencies defined, and it
+    // will provide them to the linker itself.
+    if sess.opts.debugging_opts.link_native_libraries {
+        add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
+    }
+
+    // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
+    // command line shorter, reset it to default here before adding more libraries.
+    cmd.reset_per_library_state();
+
+    // FIXME: Built-in target specs occasionally use this for linking system libraries,
+    // eliminate all such uses by migrating them to `#[link]` attributes in `lib(std,c,unwind)`
+    // and remove the option.
+    add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);
+
+    // ------------ Arbitrary order-independent options ------------
+
+    // Add order-independent options determined by rustc from its compiler options,
+    // target properties and source code.
+    add_order_independent_options(
+        cmd,
+        sess,
+        link_output_kind,
+        crt_objects_fallback,
+        flavor,
+        crate_type,
+        codegen_results,
+        out_filename,
+        tmpdir,
+    );
+
+    // Can be used for arbitrary order-independent options.
+    // In practice may also be occasionally used for linking native libraries.
+    // Passed after compiler-generated options to support manual overriding when necessary.
+    add_user_defined_link_args(cmd, sess);
+
+    // ------------ Object code and libraries, order-dependent ------------
+
+    // Post-link CRT objects.
+    add_post_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
+
+    // ------------ Late order-dependent options ------------
+
+    // Doesn't really make sense.
+    // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
+    // introduce a target spec option for order-independent linker options, migrate built-in specs
+    // to it and remove the option.
+    add_post_link_args(cmd, sess, flavor);
+
+    cmd.take_cmd()
+}
+
+fn add_order_independent_options(
+    cmd: &mut dyn Linker,
+    sess: &Session,
+    link_output_kind: LinkOutputKind,
+    crt_objects_fallback: bool,
+    flavor: LinkerFlavor,
+    crate_type: CrateType,
+    codegen_results: &CodegenResults,
+    out_filename: &Path,
+    tmpdir: &Path,
+) {
     add_apple_sdk(cmd, sess, flavor);
 
-    // NO-OPT-OUT
     add_link_script(cmd, sess, tmpdir, crate_type);
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.is_like_fuchsia && crate_type == CrateType::Executable {
         let prefix = if sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
             "asan/"
@@ -1633,30 +1907,17 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix));
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.eh_frame_header {
         cmd.add_eh_frame_header();
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     // Make the binary compatible with data execution prevention schemes.
     cmd.add_no_exec();
 
-    // NO-OPT-OUT, OBJECT-FILES-NO
-    // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
-    // at the point at which they are specified on the command line.
-    // Must be passed before any dynamic libraries.
-    cmd.add_as_needed();
-
-    // NO-OPT-OUT, OBJECT-FILES-NO
     if crt_objects_fallback {
         cmd.no_crt_objects();
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-YES
-    add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.is_like_emscripten {
         cmd.arg("-s");
         cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
@@ -1666,45 +1927,32 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         });
     }
 
-    // OBJECT-FILES-YES, AUDIT-ORDER
-    link_sanitizers(sess, crate_type, cmd);
+    if flavor == LinkerFlavor::PtxLinker {
+        // Provide the linker with fallback to internal `target-cpu`.
+        cmd.arg("--fallback-arch");
+        cmd.arg(&codegen_results.linker_info.target_cpu);
+    } else if flavor == LinkerFlavor::BpfLinker {
+        cmd.arg("--cpu");
+        cmd.arg(&codegen_results.linker_info.target_cpu);
+        cmd.arg("--cpu-features");
+        cmd.arg(match &sess.opts.cg.target_feature {
+            feat if !feat.is_empty() => feat,
+            _ => &sess.target.options.features,
+        });
+    }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
-    // Linker plugins should be specified early in the list of arguments
-    // FIXME: How "early" exactly?
     cmd.linker_plugin_lto();
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Order-dependent, at least relatively to other args adding searh directories.
     add_library_search_dirs(cmd, sess, crt_objects_fallback);
 
-    // OBJECT-FILES-YES
-    add_local_crate_regular_objects(cmd, codegen_results);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     cmd.output_filename(out_filename);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if crate_type == CrateType::Executable && sess.target.is_like_windows {
-        if let Some(ref s) = codegen_results.windows_subsystem {
+        if let Some(ref s) = codegen_results.crate_info.windows_subsystem {
             cmd.subsystem(s);
         }
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // If we're building something like a dynamic library then some platforms
-    // need to make sure that all symbols are exported correctly from the
-    // dynamic library.
-    cmd.export_symbols(tmpdir, crate_type);
-
-    // OBJECT-FILES-YES
-    add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
-
-    // OBJECT-FILES-YES
-    add_local_crate_allocator_objects(cmd, codegen_results);
-
-    // OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Order dependent, applies to the following objects. Where should it be placed?
     // Try to strip as much out of the generated object by removing unused
     // sections if possible. See more comments in linker.rs
     if !sess.link_dead_code() {
@@ -1712,65 +1960,31 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         cmd.gc_sections(keep_metadata);
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     cmd.set_output_kind(link_output_kind, out_filename);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     add_relro_args(cmd, sess);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // Pass optimization flags down to the linker.
     cmd.optimize();
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // Pass debuginfo and strip flags down to the linker.
     cmd.debuginfo(sess.opts.debugging_opts.strip);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // We want to prevent the compiler from accidentally leaking in any system libraries,
     // so by default we tell linkers not to link to any default libraries.
     if !sess.opts.cg.default_linker_libraries && sess.target.no_default_libraries {
         cmd.no_default_libraries();
     }
 
-    // OBJECT-FILES-YES
-    link_local_crate_native_libs_and_dependent_crate_libs::<B>(
-        cmd,
-        sess,
-        crate_type,
-        codegen_results,
-        tmpdir,
-    );
-
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() {
         cmd.pgo_gen();
     }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if sess.opts.cg.control_flow_guard != CFGuard::Disabled {
         cmd.control_flow_guard();
     }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     add_rpath_args(cmd, sess, codegen_results, out_filename);
-
-    // OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_user_defined_link_args(cmd, sess);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    cmd.finalize();
-
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);
-
-    // NO-OPT-OUT, OBJECT-FILES-YES
-    add_post_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
-
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_post_link_args(cmd, sess, flavor);
-
-    cmd.take_cmd()
 }
 
 /// # Native library linking
@@ -1964,11 +2178,8 @@ fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
     }
 
     // Adds the static "rlib" versions of all crates to the command line.
-    // There's a bit of magic which happens here specifically related to LTO and
-    // dynamic libraries. Specifically:
-    //
-    // * For LTO, we remove upstream object files.
-    // * For dylibs we remove metadata and bytecode from upstream rlibs
+    // There's a bit of magic which happens here specifically related to LTO,
+    // namely that we remove upstream object files.
     //
     // When performing LTO, almost(*) all of the bytecode from the upstream
     // libraries has already been included in our object file output. As a
@@ -1981,20 +2192,9 @@ fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
     // their bytecode wasn't included. The object files in those libraries must
     // still be passed to the linker.
     //
-    // When making a dynamic library, linkers by default don't include any
-    // object files in an archive if they're not necessary to resolve the link.
-    // We basically want to convert the archive (rlib) to a dylib, though, so we
-    // *do* want everything included in the output, regardless of whether the
-    // linker thinks it's needed or not. As a result we must use the
-    // --whole-archive option (or the platform equivalent). When using this
-    // option the linker will fail if there are non-objects in the archive (such
-    // as our own metadata and/or bytecode). All in all, for rlibs to be
-    // entirely included in dylibs, we need to remove all non-object files.
-    //
-    // Note, however, that if we're not doing LTO or we're not producing a dylib
-    // (aka we're making an executable), we can just pass the rlib blindly to
-    // the linker (fast) because it's fine if it's not actually included as
-    // we're at the end of the dependency chain.
+    // Note, however, that if we're not doing LTO we can just pass the rlib
+    // blindly to the linker (fast) because it's fine if it's not actually
+    // included as we're at the end of the dependency chain.
     fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
         cmd: &mut dyn Linker,
         sess: &'a Session,
@@ -2006,6 +2206,24 @@ fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
         let src = &codegen_results.crate_info.used_crate_source[&cnum];
         let cratepath = &src.rlib.as_ref().unwrap().0;
 
+        let mut link_upstream = |path: &Path| {
+            // If we're creating a dylib, then we need to include the
+            // whole of each object in our archive into that artifact. This is
+            // because a `dylib` can be reused as an intermediate artifact.
+            //
+            // Note, though, that we don't want to include the whole of a
+            // compiler-builtins crate (e.g., compiler-rt) because it'll get
+            // repeatedly linked anyway.
+            let path = fix_windows_verbatim_for_gcc(path);
+            if crate_type == CrateType::Dylib
+                && codegen_results.crate_info.compiler_builtins != Some(cnum)
+            {
+                cmd.link_whole_rlib(&path);
+            } else {
+                cmd.link_rlib(&path);
+            }
+        };
+
         // See the comment above in `link_staticlib` and `link_rlib` for why if
         // there's a static library that's not relevant we skip all object
         // files.
@@ -2017,10 +2235,9 @@ fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
 
         if (!are_upstream_rust_objects_already_included(sess)
             || ignored_for_lto(sess, &codegen_results.crate_info, cnum))
-            && crate_type != CrateType::Dylib
             && !skip_native
         {
-            cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
+            link_upstream(cratepath);
             return;
         }
 
@@ -2070,21 +2287,7 @@ fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
                 return;
             }
             archive.build();
-
-            // If we're creating a dylib, then we need to include the
-            // whole of each object in our archive into that artifact. This is
-            // because a `dylib` can be reused as an intermediate artifact.
-            //
-            // Note, though, that we don't want to include the whole of a
-            // compiler-builtins crate (e.g., compiler-rt) because it'll get
-            // repeatedly linked anyway.
-            if crate_type == CrateType::Dylib
-                && codegen_results.crate_info.compiler_builtins != Some(cnum)
-            {
-                cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
-            } else {
-                cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
-            }
+            link_upstream(&dst);
         });
     }
 
@@ -2178,10 +2381,7 @@ fn add_upstream_native_libraries(
                 // already included them when we included the rust library
                 // previously
                 NativeLibKind::Static { bundle: None | Some(true), .. } => {}
-                NativeLibKind::RawDylib => {
-                    // FIXME(#58713): Proper handling for raw dylibs.
-                    bug!("raw_dylib feature not yet implemented");
-                }
+                NativeLibKind::RawDylib => {}
             }
         }
     }
index 4dc9a3f5e41be181199eb2e5b74b762705d557f8..1d53e9ad8b34cdc50419009d17f2eefc99032673 100644 (file)
@@ -37,7 +37,7 @@ pub fn disable_localization(linker: &mut Command) {
 /// need out of the shared crate context before we get rid of it.
 #[derive(Encodable, Decodable)]
 pub struct LinkerInfo {
-    target_cpu: String,
+    pub(super) target_cpu: String,
     exports: FxHashMap<CrateType, Vec<String>>,
 }
 
@@ -81,8 +81,10 @@ pub fn to_linker<'a>(
                 Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
             }
 
-            LinkerFlavor::PtxLinker => {
-                Box::new(PtxLinker { cmd, sess, info: self }) as Box<dyn Linker>
+            LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+
+            LinkerFlavor::BpfLinker => {
+                Box::new(BpfLinker { cmd, sess, info: self }) as Box<dyn Linker>
             }
         }
     }
@@ -128,7 +130,7 @@ pub trait Linker {
     fn add_eh_frame_header(&mut self) {}
     fn add_no_exec(&mut self) {}
     fn add_as_needed(&mut self) {}
-    fn finalize(&mut self);
+    fn reset_per_library_state(&mut self) {}
 }
 
 impl dyn Linker + '_ {
@@ -472,7 +474,9 @@ fn gc_sections(&mut self, keep_metadata: bool) {
         // eliminate the metadata. If we're building an executable, however,
         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
         // reduction.
-        } else if self.sess.target.linker_is_gnu && !keep_metadata {
+        } else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm)
+            && !keep_metadata
+        {
             self.linker_arg("--gc-sections");
         }
     }
@@ -480,13 +484,13 @@ fn gc_sections(&mut self, keep_metadata: bool) {
     fn no_gc_sections(&mut self) {
         if self.sess.target.is_like_osx {
             self.linker_arg("-no_dead_strip");
-        } else if self.sess.target.linker_is_gnu {
+        } else if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm {
             self.linker_arg("--no-gc-sections");
         }
     }
 
     fn optimize(&mut self) {
-        if !self.sess.target.linker_is_gnu {
+        if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm {
             return;
         }
 
@@ -647,7 +651,7 @@ fn subsystem(&mut self, subsystem: &str) {
         self.linker_arg(&subsystem);
     }
 
-    fn finalize(&mut self) {
+    fn reset_per_library_state(&mut self) {
         self.hint_dynamic(); // Reset to default before returning the composed command line.
     }
 
@@ -931,8 +935,6 @@ fn subsystem(&mut self, subsystem: &str) {
         }
     }
 
-    fn finalize(&mut self) {}
-
     // MSVC doesn't need group indicators
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1093,8 +1095,6 @@ fn subsystem(&mut self, _subsystem: &str) {
         // noop
     }
 
-    fn finalize(&mut self) {}
-
     // Appears not necessary on Emscripten
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1275,8 +1275,6 @@ fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
-    fn finalize(&mut self) {}
-
     // Not needed for now with LLD
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1330,7 +1328,6 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
 pub struct PtxLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for PtxLinker<'a> {
@@ -1374,9 +1371,105 @@ fn output_filename(&mut self, path: &Path) {
         self.cmd.arg("-o").arg(path);
     }
 
-    fn finalize(&mut self) {
-        // Provide the linker with fallback to internal `target-cpu`.
-        self.cmd.arg("--fallback-arch").arg(&self.info.target_cpu);
+    fn link_dylib(&mut self, _lib: Symbol, _verbatim: bool, _as_needed: bool) {
+        panic!("external dylibs not supported")
+    }
+
+    fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
+        panic!("external dylibs not supported")
+    }
+
+    fn link_staticlib(&mut self, _lib: Symbol, _verbatim: bool) {
+        panic!("staticlibs not supported")
+    }
+
+    fn link_whole_staticlib(&mut self, _lib: Symbol, _verbatim: bool, _search_path: &[PathBuf]) {
+        panic!("staticlibs not supported")
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        panic!("frameworks not supported")
+    }
+
+    fn link_framework(&mut self, _framework: Symbol, _as_needed: bool) {
+        panic!("frameworks not supported")
+    }
+
+    fn full_relro(&mut self) {}
+
+    fn partial_relro(&mut self) {}
+
+    fn no_relro(&mut self) {}
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {}
+
+    fn no_gc_sections(&mut self) {}
+
+    fn pgo_gen(&mut self) {}
+
+    fn no_crt_objects(&mut self) {}
+
+    fn no_default_libraries(&mut self) {}
+
+    fn control_flow_guard(&mut self) {}
+
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+
+    fn subsystem(&mut self, _subsystem: &str) {}
+
+    fn group_start(&mut self) {}
+
+    fn group_end(&mut self) {}
+
+    fn linker_plugin_lto(&mut self) {}
+}
+
+pub struct BpfLinker<'a> {
+    cmd: Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo,
+}
+
+impl<'a> Linker for BpfLinker<'a> {
+    fn cmd(&mut self) -> &mut Command {
+        &mut self.cmd
+    }
+
+    fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
+
+    fn link_rlib(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn link_whole_rlib(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn debuginfo(&mut self, _strip: Strip) {
+        self.cmd.arg("--debug");
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn optimize(&mut self) {
+        self.cmd.arg(match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            OptLevel::Size => "-Os",
+            OptLevel::SizeMin => "-Oz",
+        });
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
     }
 
     fn link_dylib(&mut self, _lib: Symbol, _verbatim: bool, _as_needed: bool) {
@@ -1421,7 +1514,20 @@ fn no_default_libraries(&mut self) {}
 
     fn control_flow_guard(&mut self) {}
 
-    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+        let path = tmpdir.join("symbols");
+        let res: io::Result<()> = try {
+            let mut f = BufWriter::new(File::create(&path)?);
+            for sym in self.info.exports[&crate_type].iter() {
+                writeln!(f, "{}", sym)?;
+            }
+        };
+        if let Err(e) = res {
+            self.sess.fatal(&format!("failed to write symbols file: {}", e));
+        } else {
+            self.cmd.arg("--export-symbols").arg(&path);
+        }
+    }
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
index 37d1f8ecc8328367aaac17c6f3d4568bc0a70233..0fff3195808834e50a7c443d020f1138f1df2d8f 100644 (file)
@@ -3,6 +3,7 @@
 use std::fs::File;
 use std::path::Path;
 
+use object::{Object, ObjectSection};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::rustc_erase_owner;
@@ -46,7 +47,10 @@ fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef
                 let entry = entry_result
                     .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
                 if entry.name() == METADATA_FILENAME.as_bytes() {
-                    return Ok(entry.data());
+                    let data = entry
+                        .data(data)
+                        .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
+                    return search_for_metadata(path, data, ".rmeta");
                 }
             }
 
@@ -55,17 +59,27 @@ fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef
     }
 
     fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
-        use object::{Object, ObjectSection};
-
-        load_metadata_with(path, |data| {
-            let file = object::File::parse(&data)
-                .map_err(|e| format!("failed to parse dylib '{}': {}", path.display(), e))?;
-            file.section_by_name(".rustc")
-                .ok_or_else(|| format!("no .rustc section in '{}'", path.display()))?
-                .data()
-                .map_err(|e| {
-                    format!("failed to read .rustc section in '{}': {}", path.display(), e)
-                })
-        })
+        load_metadata_with(path, |data| search_for_metadata(path, data, ".rustc"))
     }
 }
+
+fn search_for_metadata<'a>(
+    path: &Path,
+    bytes: &'a [u8],
+    section: &str,
+) -> Result<&'a [u8], String> {
+    let file = match object::File::parse(bytes) {
+        Ok(f) => f,
+        // The parse above could fail for odd reasons like corruption, but for
+        // now we just interpret it as this target doesn't support metadata
+        // emission in object files so the entire byte slice itself is probably
+        // a metadata file. Ideally though if necessary we could at least check
+        // the prefix of bytes to see if it's an actual metadata object and if
+        // not forward the error along here.
+        Err(_) => return Ok(bytes),
+    };
+    file.section_by_name(section)
+        .ok_or_else(|| format!("no `{}` section in '{}'", section, path.display()))?
+        .data()
+        .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e))
+}
index 5f21046b05e475e9e3934faa2a671d927ee99383..39b0ccd120de519c747af97a88091c035d1cf4a2 100644 (file)
@@ -13,7 +13,6 @@ pub struct RPathConfig<'a> {
     pub is_like_osx: bool,
     pub has_rpath: bool,
     pub linker_is_gnu: bool,
-    pub get_install_prefix_lib_path: &'a mut dyn FnMut() -> PathBuf,
 }
 
 pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
@@ -63,24 +62,13 @@ fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
     // Use relative paths to the libraries. Binaries can be moved
     // as long as they maintain the relative relationship to the
     // crates they depend on.
-    let rel_rpaths = get_rpaths_relative_to_output(config, libs);
+    let rpaths = get_rpaths_relative_to_output(config, libs);
 
-    // And a final backup rpath to the global library location.
-    let fallback_rpaths = vec![get_install_prefix_rpath(config)];
-
-    fn log_rpaths(desc: &str, rpaths: &[String]) {
-        debug!("{} rpaths:", desc);
-        for rpath in rpaths {
-            debug!("    {}", *rpath);
-        }
+    debug!("rpaths:");
+    for rpath in &rpaths {
+        debug!("    {}", rpath);
     }
 
-    log_rpaths("relative", &rel_rpaths);
-    log_rpaths("fallback", &fallback_rpaths);
-
-    let mut rpaths = rel_rpaths;
-    rpaths.extend_from_slice(&fallback_rpaths);
-
     // Remove duplicates
     minimize_rpaths(&rpaths)
 }
@@ -113,13 +101,6 @@ fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
     diff_paths(path, base)
 }
 
-fn get_install_prefix_rpath(config: &mut RPathConfig<'_>) -> String {
-    let path = (config.get_install_prefix_lib_path)();
-    let path = env::current_dir().unwrap().join(&path);
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    path.to_str().expect("non-utf8 component in rpath").to_owned()
-}
-
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
     let mut set = FxHashSet::default();
     let mut minimized = Vec::new();
index 35836ae719b9c426a13e9476c3270f2015433f0d..24c362db12275b103947ad2cbfcdaaecf4f9faae 100644 (file)
@@ -40,7 +40,6 @@ fn test_rpath_relative() {
             is_like_osx: true,
             linker_is_gnu: false,
             out_filename: PathBuf::from("bin/rustc"),
-            get_install_prefix_lib_path: &mut || panic!(),
         };
         let res = get_rpath_relative_to_output(config, Path::new("lib/libstd.so"));
         assert_eq!(res, "@loader_path/../lib");
@@ -48,7 +47,6 @@ fn test_rpath_relative() {
         let config = &mut RPathConfig {
             used_crates: &[],
             out_filename: PathBuf::from("bin/rustc"),
-            get_install_prefix_lib_path: &mut || panic!(),
             has_rpath: true,
             is_like_osx: false,
             linker_is_gnu: true,
index 14d6f0ba147b53773c15ed6509d46d4270ef4f89..b2ecc3b0f3242e33738c6255ca35e4365ff87f14 100644 (file)
@@ -370,7 +370,6 @@ pub fn provide(providers: &mut Providers) {
 pub fn provide_extern(providers: &mut Providers) {
     providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
     providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
-    providers.wasm_import_module_map = wasm_import_module_map;
 }
 
 fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
index 49774dc6d5c7d4626dfcfd556d6a98cd169e93c5..ff4e64095714086cd4a76222786f164a2587b895 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_session::config::{Passes, SwitchWithOptPath};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
 use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};
 
@@ -426,21 +426,9 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     let (coordinator_send, coordinator_receive) = channel();
     let sess = tcx.sess;
 
-    let crate_name = tcx.crate_name(LOCAL_CRATE);
     let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
     let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
-    let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
-    let windows_subsystem = subsystem.map(|subsystem| {
-        if subsystem != sym::windows && subsystem != sym::console {
-            tcx.sess.fatal(&format!(
-                "invalid windows subsystem `{}`, only \
-                                     `windows` and `console` are allowed",
-                subsystem
-            ));
-        }
-        subsystem.to_string()
-    });
 
     let linker_info = LinkerInfo::new(tcx, target_cpu);
     let crate_info = CrateInfo::new(tcx);
@@ -472,9 +460,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
 
     OngoingCodegen {
         backend,
-        crate_name,
         metadata,
-        windows_subsystem,
         linker_info,
         crate_info,
 
@@ -1812,9 +1798,7 @@ pub fn check(&self, sess: &Session, blocking: bool) {
 
 pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub backend: B,
-    pub crate_name: Symbol,
     pub metadata: EncodedMetadata,
-    pub windows_subsystem: Option<String>,
     pub linker_info: LinkerInfo,
     pub crate_info: CrateInfo,
     pub coordinator_send: Sender<Box<dyn Any + Send>>,
@@ -1857,9 +1841,7 @@ pub fn join(self, sess: &Session) -> (CodegenResults, FxHashMap<WorkProductId, W
 
         (
             CodegenResults {
-                crate_name: self.crate_name,
                 metadata: self.metadata,
-                windows_subsystem: self.windows_subsystem,
                 linker_info: self.linker_info,
                 crate_info: self.crate_info,
 
index b44e74d5ae8209d430a523b82286781049c05aa8..38ab39febe066c4c0db3adfb8f4286d1ff0289e7 100644 (file)
@@ -30,6 +30,7 @@
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, EntryFnType};
 use rustc_session::Session;
+use rustc_span::symbol::sym;
 use rustc_target::abi::{Align, LayoutOf, VariantIdx};
 
 use std::ops::{Deref, DerefMut};
@@ -755,7 +756,22 @@ fn drop(&mut self) {
 
 impl CrateInfo {
     pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
+        let local_crate_name = tcx.crate_name(LOCAL_CRATE);
+        let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+        let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
+        let windows_subsystem = subsystem.map(|subsystem| {
+            if subsystem != sym::windows && subsystem != sym::console {
+                tcx.sess.fatal(&format!(
+                    "invalid windows subsystem `{}`, only \
+                                     `windows` and `console` are allowed",
+                    subsystem
+                ));
+            }
+            subsystem.to_string()
+        });
+
         let mut info = CrateInfo {
+            local_crate_name,
             panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
@@ -769,6 +785,7 @@ pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
             lang_item_to_crate: Default::default(),
             missing_lang_items: Default::default(),
             dependency_formats: tcx.dependency_formats(()),
+            windows_subsystem,
         };
         let lang_items = tcx.lang_items();
 
index 08442c588f87902ba3dede3d04cd3f7cf87f8090..c1dfe1ef85600d63dd9441a1bd2e49094c4af13d 100644 (file)
@@ -28,6 +28,7 @@ pub struct Expression {
 /// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count
 /// for a gap area is only used as the line execution count if there are no other regions on a
 /// line."
+#[derive(Debug)]
 pub struct FunctionCoverage<'tcx> {
     instance: Instance<'tcx>,
     source_hash: u64,
@@ -113,6 +114,14 @@ pub fn add_counter_expression(
             expression_id, lhs, op, rhs, region
         );
         let expression_index = self.expression_index(u32::from(expression_id));
+        debug_assert!(
+            expression_index.as_usize() < self.expressions.len(),
+            "expression_index {} is out of range for expressions.len() = {}
+            for {:?}",
+            expression_index.as_usize(),
+            self.expressions.len(),
+            self,
+        );
         if let Some(previous_expression) = self.expressions[expression_index].replace(Expression {
             lhs,
             op,
index 12da3d9e155e32ab3c93e9a355d7595a148a685a..b6de12fa35e37ee183dcc89412d5ad2af0a08d8a 100644 (file)
@@ -110,11 +110,18 @@ pub struct NativeLib {
     pub name: Option<Symbol>,
     pub cfg: Option<ast::MetaItem>,
     pub verbatim: Option<bool>,
+    pub dll_imports: Vec<cstore::DllImport>,
 }
 
 impl From<&cstore::NativeLib> for NativeLib {
     fn from(lib: &cstore::NativeLib) -> Self {
-        NativeLib { kind: lib.kind, name: lib.name, cfg: lib.cfg.clone(), verbatim: lib.verbatim }
+        NativeLib {
+            kind: lib.kind,
+            name: lib.name,
+            cfg: lib.cfg.clone(),
+            verbatim: lib.verbatim,
+            dll_imports: lib.dll_imports.clone(),
+        }
     }
 }
 
@@ -128,6 +135,7 @@ fn from(lib: &cstore::NativeLib) -> Self {
 /// and the corresponding properties without referencing information outside of a `CrateInfo`.
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
+    pub local_crate_name: Symbol,
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
@@ -141,16 +149,15 @@ pub struct CrateInfo {
     pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
     pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
     pub dependency_formats: Lrc<Dependencies>,
+    pub windows_subsystem: Option<String>,
 }
 
 #[derive(Encodable, Decodable)]
 pub struct CodegenResults {
-    pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
     pub allocator_module: Option<CompiledModule>,
     pub metadata_module: Option<CompiledModule>,
     pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
-    pub windows_subsystem: Option<String>,
     pub linker_info: back::linker::LinkerInfo,
     pub crate_info: CrateInfo,
 }
index 38e928145a8160c30753046aad966bf9d839a6c4..8a22a74f97c34ad23577e3fc971a279c7531ef3f 100644 (file)
@@ -7,11 +7,8 @@
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::traversal;
-use rustc_middle::mir::visit::{
-    MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, Visitor,
-};
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
-use rustc_middle::ty;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_target::abi::LayoutOf;
 
@@ -21,7 +18,9 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
-    analyzer.visit_body(&mir);
+    for (bb, data) in mir.basic_blocks().iter_enumerated() {
+        analyzer.visit_basic_block_data(bb, data);
+    }
 
     for (local, decl) in mir.local_decls.iter_enumerated() {
         let ty = fx.monomorphize(decl.ty);
@@ -142,36 +141,7 @@ fn process_place(
 
             if let mir::ProjectionElem::Deref = elem {
                 // Deref projections typically only read the pointer.
-                // (the exception being `VarDebugInfo` contexts, handled below)
                 base_context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
-
-                // Indirect debuginfo requires going through memory, that only
-                // the debugger accesses, following our emitted DWARF pointer ops.
-                //
-                // FIXME(eddyb) Investigate the possibility of relaxing this, but
-                // note that `llvm.dbg.declare` *must* be used for indirect places,
-                // even if we start using `llvm.dbg.value` for all other cases,
-                // as we don't necessarily know when the value changes, but only
-                // where it lives in memory.
-                //
-                // It's possible `llvm.dbg.declare` could support starting from
-                // a pointer that doesn't point to an `alloca`, but this would
-                // only be useful if we know the pointer being `Deref`'d comes
-                // from an immutable place, and if `llvm.dbg.declare` calls
-                // must be at the very start of the function, then only function
-                // arguments could contain such pointers.
-                if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
-                    // We use `NonUseContext::VarDebugInfo` for the base,
-                    // which might not force the base local to memory,
-                    // so we have to do it manually.
-                    self.visit_local(&place_ref.local, context, location);
-                }
-            }
-
-            // `NonUseContext::VarDebugInfo` needs to flow all the
-            // way down to the base local (see `visit_local`).
-            if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
-                base_context = context;
             }
 
             self.process_place(&place_base, base_context, location);
@@ -186,20 +156,7 @@ fn process_place(
                 );
             }
         } else {
-            // FIXME this is super_place code, is repeated here to avoid cloning place or changing
-            // visit_place API
-            let mut context = context;
-
-            if !place_ref.projection.is_empty() {
-                context = if context.is_mutating_use() {
-                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
-                } else {
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-                };
-            }
-
             self.visit_local(&place_ref.local, context, location);
-            self.visit_projection(*place_ref, context, location);
         }
     }
 }
@@ -228,34 +185,6 @@ fn visit_assign(
         self.visit_rvalue(rvalue, location);
     }
 
-    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
-        let check = match terminator.kind {
-            mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. } => {
-                match *c.ty().kind() {
-                    ty::FnDef(did, _) => Some((did, args)),
-                    _ => None,
-                }
-            }
-            _ => None,
-        };
-        if let Some((def_id, args)) = check {
-            if Some(def_id) == self.fx.cx.tcx().lang_items().box_free_fn() {
-                // box_free(x) shares with `drop x` the property that it
-                // is not guaranteed to be statically dominated by the
-                // definition of x, so x must always be in an alloca.
-                if let mir::Operand::Move(ref place) = args[0] {
-                    self.visit_place(
-                        place,
-                        PlaceContext::MutatingUse(MutatingUseContext::Drop),
-                        location,
-                    );
-                }
-            }
-        }
-
-        self.super_terminator(terminator, location);
-    }
-
     fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
         self.process_place(&place.as_ref(), context, location);
index 98d550d732fe21ddd4d323ade5f27abdf358aa65..b10de567744dd145b16961c481754585cceeb674 100644 (file)
     ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
 ];
 
+const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
+
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primitives may be documented.
 ///
@@ -224,6 +226,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol
         .chain(MIPS_ALLOWED_FEATURES.iter())
         .chain(RISCV_ALLOWED_FEATURES.iter())
         .chain(WASM_ALLOWED_FEATURES.iter())
+        .chain(BPF_ALLOWED_FEATURES.iter())
         .cloned()
 }
 
@@ -237,6 +240,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
         "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
         "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
         "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
+        "bpf" => BPF_ALLOWED_FEATURES,
         _ => &[],
     }
 }
index f28db2fe84b6b00bf0adc35d436c9698b9fd7843..dc4146ec7b58dc132fa1cf454e9fe2a9ae352d70 100644 (file)
@@ -63,9 +63,16 @@ fn target_override(&self, _opts: &config::Options) -> Option<Target> {
         None
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
-    fn provide(&self, _providers: &mut Providers);
-    fn provide_extern(&self, _providers: &mut Providers);
+    /// The metadata loader used to load rlib and dylib metadata.
+    ///
+    /// Alternative codegen backends may want to use different rlib or dylib formats than the
+    /// default native static archives and dynamic libraries.
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
+        Box::new(crate::back::metadata::DefaultMetadataLoader)
+    }
+
+    fn provide(&self, _providers: &mut Providers) {}
+    fn provide_extern(&self, _providers: &mut Providers) {}
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
index 3aabe94bfc641eeeb76ae4d41db5473b01d06d98..05b1a85381f454ff880d854199f102924cbe00d3 100644 (file)
@@ -342,7 +342,7 @@ fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Re
             return Ok(());
         }
 
-        match self.active_cache.entry(cache_key.clone()) {
+        match self.active_cache.entry(cache_key) {
             Entry::Occupied(o) => {
                 let node = &mut self.nodes[*o.get()];
                 if let Some(parent_index) = parent {
@@ -366,8 +366,7 @@ fn register_obligation_at(&mut self, obligation: O, parent: Option<usize>) -> Re
                     && self
                         .error_cache
                         .get(&obligation_tree_id)
-                        .map(|errors| errors.contains(&cache_key))
-                        .unwrap_or(false);
+                        .map_or(false, |errors| errors.contains(v.key()));
 
                 if already_failed {
                     Err(())
index 26706cd2b1b770333f5a77ae607a17cf0ebcca3e..722ce6b6367266730667d510ffe4130bf44b8898 100644 (file)
@@ -43,49 +43,9 @@ macro_rules! rustc_erase_owner {
         use std::ops::Add;
         use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
 
-        /// This is a single threaded variant of AtomicCell provided by crossbeam.
-        /// Unlike `Atomic` this is intended for all `Copy` types,
-        /// but it lacks the explicit ordering arguments.
-        #[derive(Debug)]
-        pub struct AtomicCell<T: Copy>(Cell<T>);
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn new(v: T) -> Self {
-                AtomicCell(Cell::new(v))
-            }
-
-            #[inline]
-            pub fn get_mut(&mut self) -> &mut T {
-                self.0.get_mut()
-            }
-        }
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn into_inner(self) -> T {
-                self.0.into_inner()
-            }
-
-            #[inline]
-            pub fn load(&self) -> T {
-                self.0.get()
-            }
-
-            #[inline]
-            pub fn store(&self, val: T) {
-                self.0.set(val)
-            }
-
-            #[inline]
-            pub fn swap(&self, val: T) -> T {
-                self.0.replace(val)
-            }
-        }
-
         /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
-        /// It differs from `AtomicCell` in that it has explicit ordering arguments
-        /// and is only intended for use with the native atomic types.
+        /// It has explicit ordering arguments and is only intended for use with
+        /// the native atomic types.
         /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
         /// as it's not intended to be used separately.
         #[derive(Debug)]
@@ -159,22 +119,6 @@ pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
             (oper_a(), oper_b())
         }
 
-        pub struct SerialScope;
-
-        impl SerialScope {
-            pub fn spawn<F>(&self, f: F)
-                where F: FnOnce(&SerialScope)
-            {
-                f(self)
-            }
-        }
-
-        pub fn scope<F, R>(f: F) -> R
-            where F: FnOnce(&SerialScope) -> R
-        {
-            f(&SerialScope)
-        }
-
         #[macro_export]
         macro_rules! parallel {
             ($($blocks:tt),*) => {
@@ -318,8 +262,6 @@ fn clone(&self) -> Self {
 
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
-        pub use crossbeam_utils::atomic::AtomicCell;
-
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
index c9b36dd0c24ca9cd40c39a3bada9207640cc2c31..b943977e4c2bb36c7518a4bcdae5c989a4681a49 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_feature::find_gated_cfg;
-use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
+use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
 use rustc_metadata::locator;
@@ -499,7 +499,7 @@ fn make_input(
     }
 }
 
-// Whether to stop or continue compilation.
+/// Whether to stop or continue compilation.
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Compilation {
     Stop,
@@ -765,9 +765,16 @@ fn unw(x: Option<&str>) -> &str {
         println!("commit-date: {}", unw(util::commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(util::release_str()));
-        if cfg!(feature = "llvm") {
-            get_builtin_codegen_backend(&None, "llvm")().print_version();
-        }
+
+        let debug_flags = matches.opt_strs("Z");
+        let backend_name = debug_flags.iter().find_map(|x| {
+            if x.starts_with("codegen-backend=") {
+                Some(&x["codegen-backends=".len()..])
+            } else {
+                None
+            }
+        });
+        get_codegen_backend(&None, backend_name).print_version();
     }
 }
 
@@ -1039,8 +1046,8 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     // Don't handle -W help here, because we might first load plugins.
-    let r = matches.opt_strs("Z");
-    if r.iter().any(|x| *x == "help") {
+    let debug_flags = matches.opt_strs("Z");
+    if debug_flags.iter().any(|x| *x == "help") {
         describe_debug_flags();
         return None;
     }
@@ -1060,9 +1067,14 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     if cg_flags.iter().any(|x| *x == "passes=list") {
-        if cfg!(feature = "llvm") {
-            get_builtin_codegen_backend(&None, "llvm")().print_passes();
-        }
+        let backend_name = debug_flags.iter().find_map(|x| {
+            if x.starts_with("codegen-backend=") {
+                Some(&x["codegen-backends=".len()..])
+            } else {
+                None
+            }
+        });
+        get_codegen_backend(&None, backend_name).print_passes();
         return None;
     }
 
index 2fe5ada257fc2eb3a939d80539ff71d5a3f1d58a..6b16a7d415aa61e17af426913e183271cd229a78 100644 (file)
@@ -16,13 +16,13 @@ fn bar(x: &i32) -> Box<dyn Debug> { // error!
 
 Add `'static` requirement to fix them:
 
-```compile_fail,E0759
+```
 # use std::fmt::Debug;
-fn foo(x: &i32) -> impl Debug + 'static { // ok!
+fn foo(x: &'static i32) -> impl Debug + 'static { // ok!
     x
 }
 
-fn bar(x: &i32) -> Box<dyn Debug + 'static> { // ok!
+fn bar(x: &'static i32) -> Box<dyn Debug + 'static> { // ok!
     Box::new(x)
 }
 ```
index 5d175a3ade9a2438671595d829616d563c3d4499..72395bd31eca556aed999d8f7057489b6a546dca 100644 (file)
@@ -216,7 +216,7 @@ macro_rules! encode_fields {
             $(
                 $enc.emit_struct_field(
                     stringify!($name),
-                    idx,
+                    idx == 0,
                     |enc| $name.encode(enc),
                 )?;
                 idx += 1;
@@ -229,7 +229,7 @@ macro_rules! encode_fields {
 // Special-case encoder to skip tool_metadata if not set
 impl<E: Encoder> Encodable<E> for Diagnostic {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct("diagnostic", 7, |s| {
+        s.emit_struct(false, |s| {
             let mut idx = 0;
 
             idx = encode_fields!(
index e1c218c640851fb2442b7bc6bb876a8ba0fa1450..aab2741c85240c1b4d08ffa72a7ec5a998726702 100644 (file)
@@ -1068,11 +1068,11 @@ pub fn check_unused_macros(&mut self) {
         self.resolver.check_unused_macros();
     }
 
-    /// Resolves a path mentioned inside Rust code.
+    /// Resolves a `path` mentioned inside Rust code, returning an absolute path.
     ///
-    /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
+    /// This unifies the logic used for resolving `include_X!`.
     ///
-    /// Returns an absolute path to the file that `path` refers to.
+    /// FIXME: move this to `rustc_builtin_macros` and make it private.
     pub fn resolve_path(
         &self,
         path: impl Into<PathBuf>,
index f5c6bb3db654202ee1f7db9856107f58ba85fc17..39c0447bd099eadc87a28c52c6804c623b0e396f 100644 (file)
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs};
+use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
 use rustc_ast_pretty::pprust;
-use rustc_attr::{self as attr, is_builtin_attr};
+use rustc_attr::is_builtin_attr;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::Limit;
-use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{ExpnId, FileName, Span, DUMMY_SP};
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{ExpnId, FileName, Span};
 
 use smallvec::{smallvec, SmallVec};
-use std::io::ErrorKind;
 use std::ops::DerefMut;
 use std::path::PathBuf;
 use std::rc::Rc;
-use std::{iter, mem, slice};
+use std::{iter, mem};
 
 macro_rules! ast_fragments {
     (
@@ -1524,139 +1523,6 @@ fn flat_map_generic_param(
         noop_flat_map_generic_param(param, self)
     }
 
-    fn visit_attribute(&mut self, at: &mut ast::Attribute) {
-        // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
-        // contents="file contents")]` attributes
-        if !self.cx.sess.check_name(at, sym::doc) {
-            return noop_visit_attribute(at, self);
-        }
-
-        if let Some(list) = at.meta_item_list() {
-            if !list.iter().any(|it| it.has_name(sym::include)) {
-                return noop_visit_attribute(at, self);
-            }
-
-            let mut items = vec![];
-
-            for mut it in list {
-                if !it.has_name(sym::include) {
-                    items.push({
-                        noop_visit_meta_list_item(&mut it, self);
-                        it
-                    });
-                    continue;
-                }
-
-                if let Some(file) = it.value_str() {
-                    let err_count = self.cx.sess.parse_sess.span_diagnostic.err_count();
-                    self.check_attributes(slice::from_ref(at));
-                    if self.cx.sess.parse_sess.span_diagnostic.err_count() > err_count {
-                        // avoid loading the file if they haven't enabled the feature
-                        return noop_visit_attribute(at, self);
-                    }
-
-                    let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
-                        Ok(filename) => filename,
-                        Err(mut err) => {
-                            err.emit();
-                            continue;
-                        }
-                    };
-
-                    match self.cx.source_map().load_file(&filename) {
-                        Ok(source_file) => {
-                            let src = source_file
-                                .src
-                                .as_ref()
-                                .expect("freshly loaded file should have a source");
-                            let src_interned = Symbol::intern(src.as_str());
-
-                            let include_info = vec![
-                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
-                                    Ident::with_dummy_span(sym::file),
-                                    file,
-                                    DUMMY_SP,
-                                )),
-                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
-                                    Ident::with_dummy_span(sym::contents),
-                                    src_interned,
-                                    DUMMY_SP,
-                                )),
-                            ];
-
-                            let include_ident = Ident::with_dummy_span(sym::include);
-                            let item = attr::mk_list_item(include_ident, include_info);
-                            items.push(ast::NestedMetaItem::MetaItem(item));
-                        }
-                        Err(e) => {
-                            let lit_span = it.name_value_literal_span().unwrap();
-
-                            if e.kind() == ErrorKind::InvalidData {
-                                self.cx
-                                    .struct_span_err(
-                                        lit_span,
-                                        &format!("{} wasn't a utf-8 file", filename.display()),
-                                    )
-                                    .span_label(lit_span, "contains invalid utf-8")
-                                    .emit();
-                            } else {
-                                let mut err = self.cx.struct_span_err(
-                                    lit_span,
-                                    &format!("couldn't read {}: {}", filename.display(), e),
-                                );
-                                err.span_label(lit_span, "couldn't read file");
-
-                                err.emit();
-                            }
-                        }
-                    }
-                } else {
-                    let mut err = self
-                        .cx
-                        .struct_span_err(it.span(), "expected path to external documentation");
-
-                    // Check if the user erroneously used `doc(include(...))` syntax.
-                    let literal = it.meta_item_list().and_then(|list| {
-                        if list.len() == 1 {
-                            list[0].literal().map(|literal| &literal.kind)
-                        } else {
-                            None
-                        }
-                    });
-
-                    let (path, applicability) = match &literal {
-                        Some(LitKind::Str(path, ..)) => {
-                            (path.to_string(), Applicability::MachineApplicable)
-                        }
-                        _ => (String::from("<path>"), Applicability::HasPlaceholders),
-                    };
-
-                    err.span_suggestion(
-                        it.span(),
-                        "provide a file path with `=`",
-                        format!("include = \"{}\"", path),
-                        applicability,
-                    );
-
-                    err.emit();
-                }
-            }
-
-            let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
-            *at = ast::Attribute {
-                kind: ast::AttrKind::Normal(
-                    AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span), tokens: None },
-                    None,
-                ),
-                span: at.span,
-                id: at.id,
-                style: at.style,
-            };
-        } else {
-            noop_visit_attribute(at, self)
-        }
-    }
-
     fn visit_id(&mut self, id: &mut ast::NodeId) {
         if self.monotonic {
             debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
index a84737e80a09f9af152a5a7848a5a971e430296f..0359f503ef96cc78bd7fe7d543757d3d93904799 100644 (file)
@@ -250,6 +250,7 @@ pub fn set(&self, features: &mut Features, span: Span) {
     (active, f16c_target_feature, "1.36.0", Some(44839), None),
     (active, riscv_target_feature, "1.45.0", Some(44839), None),
     (active, ermsb_target_feature, "1.49.0", Some(44839), None),
+    (active, bpf_target_feature, "1.54.0", Some(44839), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates (target features)
@@ -370,9 +371,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
-    /// Allows `#[doc(include = "some-file")]`.
-    (active, external_doc, "1.22.0", Some(44732), None),
-
     /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
     (active, crate_visibility_modifier, "1.23.0", Some(53120), None),
 
index 138398825af586123ec3c59e07c4fdd96f556113..71c10eb650754699eb8d98456c7fe0a4dd2e46ca 100644 (file)
@@ -140,6 +140,10 @@ macro_rules! declare_features {
     (removed, const_fn, "1.54.0", Some(57563), None,
      Some("split into finer-grained feature gates")),
 
+    /// Allows `#[doc(include = "some-file")]`.
+    (removed, external_doc, "1.54.0", Some(44732), None,
+     Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
+
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
index fda1ba809526c762ca4c2766aa7c6b5d9e74605b..49f418d51a82d2d27ef44b833c60f2a314bb5362 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
+use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -338,7 +339,7 @@ pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefI
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
-    pub fn new(stable_crate_id: StableCrateId) -> Definitions {
+    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -347,6 +348,7 @@ pub fn new(stable_crate_id: StableCrateId) -> Definitions {
             },
         };
 
+        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
index 4636d515249d9809ed55b2fe182ef3a2c63e7ab8..2aafc6afa236d8fd5d2b6c7e0361768d1aace5e5 100644 (file)
@@ -1,4 +1,6 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 
 #[test]
@@ -11,16 +13,17 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
-    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+    let d0 = CrateDisambiguator::from(Fingerprint::new(12, 34));
+    let d1 = CrateDisambiguator::from(Fingerprint::new(56, 78));
 
-    let h0 = mk_test_hash(id0);
-    let h1 = mk_test_hash(id1);
+    let h0 = mk_test_hash("foo", d0);
+    let h1 = mk_test_hash("foo", d1);
 
     assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
     assert_ne!(h0.local_hash(), h1.local_hash());
 
-    fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+    fn mk_test_hash(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> DefPathHash {
+        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
         let key = DefKey {
index 2ed0539841aa30b42f896132fbf02779b70354c6..83e80b55daec1b3e2d9eac3bcdc9f7067550ac62 100644 (file)
 use rustc_data_structures::{base_n, flock};
 use rustc_errors::ErrorReported;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 
 use std::fs as std_fs;
 use std::io;
@@ -189,7 +189,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 pub fn prepare_session_directory(
     sess: &Session,
     crate_name: &str,
-    stable_crate_id: StableCrateId,
+    crate_disambiguator: CrateDisambiguator,
 ) -> Result<(), ErrorReported> {
     if sess.opts.incremental.is_none() {
         return Ok(());
@@ -200,7 +200,7 @@ pub fn prepare_session_directory(
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
-    let crate_dir = crate_path(sess, crate_name, stable_crate_id);
+    let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
     debug!("crate-dir: {}", crate_dir.display());
     create_dir(sess, &crate_dir, "crate")?;
 
@@ -648,12 +648,19 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+fn crate_path(
+    sess: &Session,
+    crate_name: &str,
+    crate_disambiguator: CrateDisambiguator,
+) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
-    let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
+    // The full crate disambiguator is really long. 64 bits of it should be
+    // sufficient.
+    let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
+    let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE);
 
-    let crate_name = format!("{}-{}", crate_name, stable_crate_id);
+    let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
     incr_dir.join(crate_name)
 }
 
index b8ecc949588fb0658d3e79b7c416018d220773c1..c3c28d70081512550f398aacac7337d78888947d 100644 (file)
@@ -660,7 +660,12 @@ fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<
         )
     }
 
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        _info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         self.obligations.push(Obligation {
             cause: self.cause.clone(),
             param_env: self.param_env,
index 30214e94203d81d078d413709ea2365f8b8487fa..3a11b5a214490088d71ef7f4ff7cb8518b9c4d7b 100644 (file)
@@ -371,9 +371,12 @@ pub fn instantiate(
         match dir {
             EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
             SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
-            SupertypeOf => {
-                self.sub(a_is_expected).relate_with_variance(ty::Contravariant, a_ty, b_ty)
-            }
+            SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+                ty::Contravariant,
+                ty::VarianceDiagInfo::default(),
+                a_ty,
+                b_ty,
+            ),
         }?;
 
         Ok(())
@@ -574,6 +577,7 @@ fn relate_item_substs(
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -737,7 +741,12 @@ fn consts(
                 if self.tcx().lazy_normalization() =>
             {
                 assert_eq!(promoted, None);
-                let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?;
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
                     val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
@@ -831,6 +840,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -965,7 +975,12 @@ fn consts(
                 if self.tcx().lazy_normalization() =>
             {
                 assert_eq!(promoted, None);
-                let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?;
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
                     val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
index 45ba50bb6349cc9d177d81f6534601508bebdf87..0c93271a1aeca716844af99337c8f8e7e9fd8bb7 100644 (file)
@@ -59,6 +59,7 @@ fn relate_item_substs(
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
index 02662043dba798088284696de403c25f30476984..60f02b84aa344225f73a762884c33e783d628a03 100644 (file)
@@ -43,6 +43,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -96,7 +97,7 @@ fn binders<T>(
         // When higher-ranked types are involved, computing the LUB is
         // very challenging, switch to invariance. This is obviously
         // overly conservative but works ok in practice.
-        self.relate_with_variance(ty::Variance::Invariant, a, b)?;
+        self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
         Ok(a)
     }
 }
index 4fa8f2f1a6a426c82ec5bb6f9348a54a2e23f164..a08323535c55abd6d926abb15df0246800b8d66a 100644 (file)
@@ -43,6 +43,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -96,7 +97,7 @@ fn binders<T>(
         // When higher-ranked types are involved, computing the LUB is
         // very challenging, switch to invariance. This is obviously
         // overly conservative but works ok in practice.
-        self.relate_with_variance(ty::Variance::Invariant, a, b)?;
+        self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
         Ok(a)
     }
 }
index 077d2cc20a25c3fdaf7bc8f20c4325f024baf5d1..20be06adfd09e1a37c64991476ee00f4d85cedca 100644 (file)
@@ -55,6 +55,8 @@ pub struct TypeRelating<'me, 'tcx, D>
     /// - Bivariant means that it doesn't matter.
     ambient_variance: ty::Variance,
 
+    ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
+
     /// When we pass through a set of binders (e.g., when looking into
     /// a `fn` type), we push a new bound region scope onto here. This
     /// will contain the instantiated region for each region in those
@@ -78,7 +80,12 @@ pub trait TypeRelatingDelegate<'tcx> {
     /// satisfied for the two types to be related. `sub` and `sup` may
     /// be regions from the type or new variables created through the
     /// delegate.
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>);
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    );
 
     fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
 
@@ -138,7 +145,14 @@ pub fn new(
         delegate: D,
         ambient_variance: ty::Variance,
     ) -> Self {
-        Self { infcx, delegate, ambient_variance, a_scopes: vec![], b_scopes: vec![] }
+        Self {
+            infcx,
+            delegate,
+            ambient_variance,
+            ambient_variance_info: ty::VarianceDiagInfo::default(),
+            a_scopes: vec![],
+            b_scopes: vec![],
+        }
     }
 
     fn ambient_covariance(&self) -> bool {
@@ -239,10 +253,15 @@ fn replace_bound_region(
 
     /// Push a new outlives requirement into our output set of
     /// constraints.
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         debug!("push_outlives({:?}: {:?})", sup, sub);
 
-        self.delegate.push_outlives(sup, sub);
+        self.delegate.push_outlives(sup, sub, info);
     }
 
     /// Relate a projection type and some value type lazily. This will always
@@ -490,6 +509,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -497,6 +517,7 @@ fn relate_with_variance<T: Relate<'tcx>>(
 
         let old_ambient_variance = self.ambient_variance;
         self.ambient_variance = self.ambient_variance.xform(variance);
+        self.ambient_variance_info = self.ambient_variance_info.clone().xform(info);
 
         debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
 
@@ -574,12 +595,12 @@ fn regions(
 
         if self.ambient_covariance() {
             // Covariance: a <= b. Hence, `b: a`.
-            self.push_outlives(v_b, v_a);
+            self.push_outlives(v_b, v_a, self.ambient_variance_info.clone());
         }
 
         if self.ambient_contravariance() {
             // Contravariant: b <= a. Hence, `a: b`.
-            self.push_outlives(v_a, v_b);
+            self.push_outlives(v_a, v_b, self.ambient_variance_info.clone());
         }
 
         Ok(a)
@@ -835,6 +856,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
index bf5f328233dfd7832ba421924214d53fec58df8d..b3131936ae06608210a7bedab490e1bf38859c58 100644 (file)
@@ -62,6 +62,7 @@ fn with_cause<F, R>(&mut self, cause: Cause, f: F) -> R
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
index 1666754d29ac696cc57e9111b09c299f284d3d42..aa7af609fb54f71c7513e2bd1f836b37b426ded5 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::Crate;
 use rustc_lint::LintStore;
 use rustc_metadata::creader::CStore;
@@ -170,13 +170,9 @@ pub fn register_plugins<'a>(
     let crate_types = util::collect_crate_types(sess, &krate.attrs);
     sess.init_crate_types(crate_types);
 
-    let stable_crate_id = StableCrateId::new(
-        crate_name,
-        sess.crate_types().contains(&CrateType::Executable),
-        sess.opts.cg.metadata.clone(),
-    );
-    sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
-    rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?;
+    let disambiguator = util::compute_crate_disambiguator(sess);
+    sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
+    rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
 
     if sess.opts.incremental.is_some() {
         sess.time("incr_comp_garbage_collect_session_directories", || {
@@ -985,7 +981,7 @@ enum MetadataKind {
             .tempdir_in(out_filename.parent().unwrap())
             .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
         let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
-        let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
+        let metadata_filename = emit_metadata(tcx.sess, &metadata.raw_data, &metadata_tmpdir);
         if let Err(e) = util::non_durable_rename(&metadata_filename, &out_filename) {
             tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
         }
index 969b526235bb2affd4f023ad6555bb92f9380744..2320f0b47d27df0bb04b9a8c530ebc0d6bbfc72f 100644 (file)
@@ -245,8 +245,7 @@ pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.prepare_outputs.compute(|| {
             let expansion_result = self.expansion()?;
             let (krate, boxed_resolver, _) = &*expansion_result.peek();
-            let crate_name = self.crate_name()?;
-            let crate_name = crate_name.peek();
+            let crate_name = self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
@@ -343,32 +342,36 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
     }
 
     pub fn linker(&'tcx self) -> Result<Linker> {
-        let dep_graph = self.dep_graph()?;
-        let prepare_outputs = self.prepare_outputs()?;
-        let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
-        let ongoing_codegen = self.ongoing_codegen()?;
-
         let sess = self.session().clone();
         let codegen_backend = self.codegen_backend().clone();
 
+        let dep_graph = self.dep_graph()?.peek().clone();
+        let prepare_outputs = self.prepare_outputs()?.take();
+        let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
+        let ongoing_codegen = self.ongoing_codegen()?.take();
+
         Ok(Linker {
             sess,
-            dep_graph: dep_graph.peek().clone(),
-            prepare_outputs: prepare_outputs.take(),
-            crate_hash,
-            ongoing_codegen: ongoing_codegen.take(),
             codegen_backend,
+
+            dep_graph,
+            prepare_outputs,
+            crate_hash,
+            ongoing_codegen,
         })
     }
 }
 
 pub struct Linker {
+    // compilation inputs
     sess: Lrc<Session>,
+    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
+
+    // compilation outputs
     dep_graph: DepGraph,
     prepare_outputs: OutputFilenames,
     crate_hash: Svh,
     ongoing_codegen: Box<dyn Any>,
-    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
 }
 
 impl Linker {
index 15cda2992088a87174ff73a4c457f9cd2ea29b3a..6485fbebd665fd028ccc35274b6fd65ef89d9648 100644 (file)
@@ -2,9 +2,11 @@
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
 use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[cfg(parallel_compiler)]
 use rustc_data_structures::jobserver;
+use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
@@ -16,6 +18,7 @@
 use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
 use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::CrateConfig;
+use rustc_session::CrateDisambiguator;
 use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -32,7 +35,7 @@
 use std::panic;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{Arc, Mutex, Once};
+use std::sync::{Arc, Mutex};
 use std::thread;
 use tracing::info;
 
@@ -73,7 +76,10 @@ pub fn create_session(
     let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
         make_codegen_backend(&sopts)
     } else {
-        get_codegen_backend(&sopts)
+        get_codegen_backend(
+            &sopts.maybe_sysroot,
+            sopts.debugging_opts.codegen_backend.as_ref().map(|name| &name[..]),
+        )
     };
 
     // target_override is documented to be called before init(), so this is okay
@@ -241,35 +247,34 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
     }
 }
 
-pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
-    static INIT: Once = Once::new();
-
-    static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
+/// Get the codegen backend based on the name and specified sysroot.
+///
+/// A name of `None` indicates that the default backend should be used.
+pub fn get_codegen_backend(
+    maybe_sysroot: &Option<PathBuf>,
+    backend_name: Option<&str>,
+) -> Box<dyn CodegenBackend> {
+    static LOAD: SyncOnceCell<unsafe fn() -> Box<dyn CodegenBackend>> = SyncOnceCell::new();
 
-    INIT.call_once(|| {
+    let load = LOAD.get_or_init(|| {
         #[cfg(feature = "llvm")]
         const DEFAULT_CODEGEN_BACKEND: &str = "llvm";
 
         #[cfg(not(feature = "llvm"))]
         const DEFAULT_CODEGEN_BACKEND: &str = "cranelift";
 
-        let codegen_name = sopts
-            .debugging_opts
-            .codegen_backend
-            .as_ref()
-            .map(|name| &name[..])
-            .unwrap_or(DEFAULT_CODEGEN_BACKEND);
-
-        let backend = match codegen_name {
+        match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) {
             filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
-            codegen_name => get_builtin_codegen_backend(&sopts.maybe_sysroot, codegen_name),
-        };
-
-        unsafe {
-            LOAD = backend;
+            #[cfg(feature = "llvm")]
+            "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
+            backend_name => get_codegen_sysroot(maybe_sysroot, backend_name),
         }
     });
-    unsafe { LOAD() }
+
+    // SAFETY: In case of a builtin codegen backend this is safe. In case of an external codegen
+    // backend we hope that the backend links against the same rustc_driver version. If this is not
+    // the case, we get UB.
+    unsafe { load() }
 }
 
 // This is used for rustdoc, but it uses similar machinery to codegen backend
@@ -387,17 +392,6 @@ fn current_dll_path() -> Option<PathBuf> {
     }
 }
 
-pub fn get_builtin_codegen_backend(
-    maybe_sysroot: &Option<PathBuf>,
-    backend_name: &str,
-) -> fn() -> Box<dyn CodegenBackend> {
-    match backend_name {
-        #[cfg(feature = "llvm")]
-        "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
-        _ => get_codegen_sysroot(maybe_sysroot, backend_name),
-    }
-}
-
 pub fn get_codegen_sysroot(
     maybe_sysroot: &Option<PathBuf>,
     backend_name: &str,
@@ -493,6 +487,39 @@ pub fn get_codegen_sysroot(
     }
 }
 
+pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
+    use std::hash::Hasher;
+
+    // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
+    // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
+    // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
+    // should still be safe enough to avoid collisions in practice.
+    let mut hasher = StableHasher::new();
+
+    let mut metadata = session.opts.cg.metadata.clone();
+    // We don't want the crate_disambiguator to dependent on the order
+    // -C metadata arguments, so sort them:
+    metadata.sort();
+    // Every distinct -C metadata value is only incorporated once:
+    metadata.dedup();
+
+    hasher.write(b"metadata");
+    for s in &metadata {
+        // Also incorporate the length of a metadata string, so that we generate
+        // different values for `-Cmetadata=ab -Cmetadata=c` and
+        // `-Cmetadata=a -Cmetadata=bc`
+        hasher.write_usize(s.len());
+        hasher.write(s.as_bytes());
+    }
+
+    // Also incorporate crate type, so that we don't get symbol conflicts when
+    // linking against a library of the same name, if this is an executable.
+    let is_exe = session.crate_types().contains(&CrateType::Executable);
+    hasher.write(if is_exe { b"exe" } else { b"lib" });
+
+    CrateDisambiguator::from(hasher.finish::<Fingerprint>())
+}
+
 pub(crate) fn check_attr_crate_type(
     sess: &Session,
     attrs: &[ast::Attribute],
index e7275374b8915f39bb1976d30f649fc298ff8b97..f6a84966f7a91b9a4b5ab92d2cbf026e16101467 100644 (file)
@@ -489,7 +489,7 @@ fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool {
 
     if let Some(list) = attr.meta_item_list() {
         for meta in list {
-            if meta.has_name(sym::include) || meta.has_name(sym::hidden) {
+            if meta.has_name(sym::hidden) {
                 return true;
             }
         }
index 862f8374d30d8ffeaa82c0ed0d66f37861611dbc..a8df1b0952c18297e38febb48793c5ab995947ee 100644 (file)
@@ -334,8 +334,14 @@ pub fn find_lints(&self, mut lint_name: &str) -> Result<Vec<LintId>, FindLintErr
         }
     }
 
-    /// Checks the validity of lint names derived from the command line
-    pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Level) {
+    /// Checks the validity of lint names derived from the command line. Returns
+    /// true if the lint is valid, false otherwise.
+    pub fn check_lint_name_cmdline(
+        &self,
+        sess: &Session,
+        lint_name: &str,
+        level: Option<Level>,
+    ) -> bool {
         let db = match self.check_lint_name(lint_name, None) {
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
@@ -361,18 +367,23 @@ pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Le
         };
 
         if let Some(mut db) = db {
-            let msg = format!(
-                "requested on the command line with `{} {}`",
-                match level {
-                    Level::Allow => "-A",
-                    Level::Warn => "-W",
-                    Level::Deny => "-D",
-                    Level::Forbid => "-F",
-                },
-                lint_name
-            );
-            db.note(&msg);
+            if let Some(level) = level {
+                let msg = format!(
+                    "requested on the command line with `{} {}`",
+                    match level {
+                        Level::Allow => "-A",
+                        Level::Warn => "-W",
+                        Level::Deny => "-D",
+                        Level::Forbid => "-F",
+                    },
+                    lint_name
+                );
+                db.note(&msg);
+            }
             db.emit();
+            false
+        } else {
+            true
         }
     }
 
index 91cdef9b089fa7544b31c255378049d140a467ff..0ee434f5fb50bae3e359d986b90936c9027c1470 100644 (file)
@@ -88,7 +88,7 @@ fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
         self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
 
         for &(ref lint_name, level) in &sess.opts.lint_opts {
-            store.check_lint_name_cmdline(sess, &lint_name, level);
+            store.check_lint_name_cmdline(sess, &lint_name, Some(level));
             let orig_level = level;
 
             // If the cap is less than this specified level, e.g., if we've got
@@ -109,6 +109,16 @@ fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
             }
         }
 
+        for lint_name in &sess.opts.force_warns {
+            let valid = store.check_lint_name_cmdline(sess, lint_name, None);
+            if valid {
+                let lints = store
+                    .find_lints(lint_name)
+                    .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
+                self.sets.force_warns.extend(&lints);
+            }
+        }
+
         self.sets.list.push(LintSet::CommandLine { specs });
     }
 
@@ -142,6 +152,9 @@ fn insert_spec(
                     LintLevelSource::Default => false,
                     LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol),
                     LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol),
+                    LintLevelSource::ForceWarn(_symbol) => {
+                        bug!("forced warn lint returned a forbid lint level")
+                    }
                 };
                 debug!(
                     "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
@@ -166,6 +179,7 @@ fn insert_spec(
                         LintLevelSource::CommandLine(_, _) => {
                             diag_builder.note("`forbid` lint level was set on command line");
                         }
+                        _ => bug!("forced warn lint returned a forbid lint level"),
                     }
                     diag_builder.emit();
                 };
index 319adf42cf1ed2aee243a3d8f2ef2a1803a3344a..a3a87a48768dcde44bfa80ff9e1dc482229a38bb 100644 (file)
@@ -679,16 +679,11 @@ pub fn transparent_newtype_field<'a, 'tcx>(
     variant: &'a ty::VariantDef,
 ) -> Option<&'a ty::FieldDef> {
     let param_env = tcx.param_env(variant.def_id);
-    for field in &variant.fields {
+    variant.fields.iter().find(|field| {
         let field_ty = tcx.type_of(field.did);
         let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
-
-        if !is_zst {
-            return Some(field);
-        }
-    }
-
-    None
+        !is_zst
+    })
 }
 
 /// Is type known to be non-null?
@@ -711,15 +706,10 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
                 return false;
             }
 
-            for variant in &def.variants {
-                if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
-                    if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
-                        return true;
-                    }
-                }
-            }
-
-            false
+            def.variants
+                .iter()
+                .filter_map(|variant| transparent_newtype_field(cx.tcx, variant))
+                .any(|field| ty_is_known_nonnull(cx, field.ty(tcx, substs), mode))
         }
         _ => false,
     }
@@ -909,11 +899,18 @@ fn check_type_for_ffi(&self, cache: &mut FxHashSet<Ty<'tcx>>, ty: Ty<'tcx>) -> F
         }
 
         match *ty.kind() {
-            ty::Adt(def, _) if def.is_box() && matches!(self.mode, CItemKind::Definition) => {
-                FfiSafe
-            }
-
             ty::Adt(def, substs) => {
+                if def.is_box() && matches!(self.mode, CItemKind::Definition) {
+                    if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) {
+                        return FfiSafe;
+                    } else {
+                        return FfiUnsafe {
+                            ty,
+                            reason: format!("box cannot be represented as a single pointer"),
+                            help: None,
+                        };
+                    }
+                }
                 if def.is_phantom_data() {
                     return FfiPhantom(ty);
                 }
index 15246971bae02e82175430a15b2b5f92a65ba82f..352146d64635ad69f72e56cac4c6ac926174426a 100644 (file)
         USELESS_DEPRECATED,
         UNSUPPORTED_NAKED_FUNCTIONS,
         MISSING_ABI,
+        INVALID_DOC_ATTRIBUTES,
         SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
         DISJOINT_CAPTURE_MIGRATION,
         LEGACY_DERIVE_HELPERS,
index 301ed639f3b511b578848a9dcf6de27de345d909..452d1b19a18a84b18e861736f51505a437a0170a 100644 (file)
@@ -86,6 +86,7 @@ fn main() {
         "nvptx",
         "hexagon",
         "riscv",
+        "bpf",
     ];
 
     let required_components = &[
index 2e135fbe2bd8fe7b271c496288c66c730565faf4..9b757eb40c1840b64834fac51a76a36f58f1ed4e 100644 (file)
@@ -6,6 +6,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
 #include "llvm/Support/Signals.h"
@@ -70,17 +71,6 @@ extern "C" void LLVMRustInstallFatalErrorHandler() {
   install_fatal_error_handler(FatalErrorHandler);
 }
 
-extern "C" LLVMMemoryBufferRef
-LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
-      MemoryBuffer::getFile(Path, -1, false);
-  if (!BufOr) {
-    LLVMRustSetLastError(BufOr.getError().message().c_str());
-    return nullptr;
-  }
-  return wrap(BufOr.get().release());
-}
-
 extern "C" char *LLVMRustGetLastError(void) {
   char *Ret = LastError;
   LastError = nullptr;
@@ -1077,30 +1067,6 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
   }
 }
 
-// Note that the two following functions look quite similar to the
-// LLVMGetSectionName function. Sadly, it appears that this function only
-// returns a char* pointer, which isn't guaranteed to be null-terminated. The
-// function provided by LLVM doesn't return the length, so we've created our own
-// function which returns the length as well as the data pointer.
-//
-// For an example of this not returning a null terminated string, see
-// lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
-// branches explicitly creates a StringRef without a null terminator, and then
-// that's returned.
-
-inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
-  return reinterpret_cast<section_iterator *>(SI);
-}
-
-extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
-                                         const char **Ptr) {
-  auto NameOrErr = (*unwrap(SI))->getName();
-  if (!NameOrErr)
-    report_fatal_error(NameOrErr.takeError());
-  *Ptr = NameOrErr->data();
-  return NameOrErr->size();
-}
-
 // LLVMArrayType function does not support 64-bit ElementCount
 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
                                          uint64_t ElementCount) {
@@ -1757,3 +1723,54 @@ extern "C" LLVMValueRef
 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
 }
+
+// This struct contains all necessary info about a symbol exported from a DLL.
+// At the moment, it's just the symbol's name, but we use a separate struct to
+// make it easier to add other information like ordinal later.
+struct LLVMRustCOFFShortExport {
+  const char* name;
+};
+
+// Machine must be a COFF machine type, as defined in PE specs.
+extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
+  const char* ImportName,
+  const char* Path,
+  const LLVMRustCOFFShortExport* Exports,
+  size_t NumExports,
+  uint16_t Machine,
+  bool MinGW)
+{
+  std::vector<llvm::object::COFFShortExport> ConvertedExports;
+  ConvertedExports.reserve(NumExports);
+
+  for (size_t i = 0; i < NumExports; ++i) {
+    ConvertedExports.push_back(llvm::object::COFFShortExport{
+      Exports[i].name,  // Name
+      std::string{},    // ExtName
+      std::string{},    // SymbolName
+      std::string{},    // AliasTarget
+      0,                // Ordinal
+      false,            // Noname
+      false,            // Data
+      false,            // Private
+      false             // Constant
+    });
+  }
+
+  auto Error = llvm::object::writeImportLibrary(
+    ImportName,
+    Path,
+    ConvertedExports,
+    static_cast<llvm::COFF::MachineTypes>(Machine),
+    MinGW);
+  if (Error) {
+    std::string errorString;
+    llvm::raw_string_ostream stream(errorString);
+    stream << Error;
+    stream.flush();
+    LLVMRustSetLastError(errorString.c_str());
+    return LLVMRustResult::Failure;
+  } else {
+    return LLVMRustResult::Success;
+  }
+}
index 555aefb192948303a13864b55a7f167453c3e252..122627eb500ada1b69f2d38924d63e9f4069dcc9 100644 (file)
@@ -167,4 +167,12 @@ fn init() { }
         LLVMInitializeWebAssemblyAsmPrinter,
         LLVMInitializeWebAssemblyAsmParser
     );
+    init_target!(
+        llvm_component = "bpf",
+        LLVMInitializeBPFTargetInfo,
+        LLVMInitializeBPFTarget,
+        LLVMInitializeBPFTargetMC,
+        LLVMInitializeBPFAsmPrinter,
+        LLVMInitializeBPFAsmParser
+    );
 }
index 72bd4804e98c0b81e4f5e20a6228db87f74e07a6..7bc669f2b005c53fc86c89970270b62f617dd799 100644 (file)
@@ -43,12 +43,9 @@ fn decodable_body(
     let decode_body = match s.variants() {
         [vi] => {
             let construct = vi.construct(|field, index| decode_field(field, index, true));
-            let n_fields = vi.ast().fields.len();
             quote! {
                 ::rustc_serialize::Decoder::read_struct(
                     __decoder,
-                    #ty_name,
-                    #n_fields,
                     |__decoder| { ::std::result::Result::Ok(#construct) },
                 )
             }
@@ -77,7 +74,6 @@ fn decodable_body(
             quote! {
                 ::rustc_serialize::Decoder::read_enum(
                     __decoder,
-                    #ty_name,
                     |__decoder| {
                         ::rustc_serialize::Decoder::read_enum_variant(
                             __decoder,
@@ -128,7 +124,7 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro
 
     quote! {
         match ::rustc_serialize::Decoder::#decode_method(
-            __decoder, #opt_field_name #index, #decode_inner_method) {
+            __decoder, #opt_field_name #decode_inner_method) {
             ::std::result::Result::Ok(__res) => __res,
             ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
         }
@@ -183,7 +179,6 @@ fn encodable_body(
         }
     });
 
-    let ty_name = s.ast().ident.to_string();
     let encode_body = match s.variants() {
         [_] => {
             let mut field_idx = 0usize;
@@ -197,11 +192,12 @@ fn encodable_body(
                             .ident
                             .as_ref()
                             .map_or_else(|| field_idx.to_string(), |i| i.to_string());
+                        let first = field_idx == 0;
                         let result = quote! {
                             match ::rustc_serialize::Encoder::emit_struct_field(
                                 __encoder,
                                 #field_name,
-                                #field_idx,
+                                #first,
                                 |__encoder|
                                 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
@@ -215,8 +211,9 @@ fn encodable_body(
                     })
                     .collect::<TokenStream>()
             });
+            let no_fields = field_idx == 0;
             quote! {
-                ::rustc_serialize::Encoder::emit_struct(__encoder, #ty_name, #field_idx, |__encoder| {
+                ::rustc_serialize::Encoder::emit_struct(__encoder, #no_fields, |__encoder| {
                     ::std::result::Result::Ok(match *self { #encode_inner })
                 })
             }
@@ -232,10 +229,11 @@ fn encodable_body(
                     .iter()
                     .map(|binding| {
                         let bind_ident = &binding.binding;
+                        let first = field_idx == 0;
                         let result = quote! {
                             match ::rustc_serialize::Encoder::emit_enum_variant_arg(
                                 __encoder,
-                                #field_idx,
+                                #first,
                                 |__encoder|
                                 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
@@ -260,7 +258,7 @@ fn encodable_body(
                 result
             });
             quote! {
-                ::rustc_serialize::Encoder::emit_enum(__encoder, #ty_name, |__encoder| {
+                ::rustc_serialize::Encoder::emit_enum(__encoder, |__encoder| {
                     match *self {
                         #encode_inner
                     }
index 42c32219aba417e4c2b8826c58a0b4ad3aed2187..e9ae22f8cedbc47926fd0ed4aa39e9ae0469fa10 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
-use rustc_session::Session;
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -222,8 +222,10 @@ pub fn new(
         metadata_loader: &'a MetadataLoaderDyn,
         local_crate_name: &str,
     ) -> Self {
+        let local_crate_stable_id =
+            StableCrateId::new(local_crate_name, sess.local_crate_disambiguator());
         let mut stable_crate_ids = FxHashMap::default();
-        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+        stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE);
 
         CrateLoader {
             sess,
@@ -325,14 +327,17 @@ fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Opt
 
     fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
         // Check for (potential) conflicts with the local crate
-        if self.sess.local_stable_crate_id() == root.stable_crate_id() {
+        if self.local_crate_name == root.name()
+            && self.sess.local_crate_disambiguator() == root.disambiguator()
+        {
             return Err(CrateError::SymbolConflictsCurrent(root.name()));
         }
 
         // Check for conflicts with any crate loaded so far
         let mut res = Ok(());
         self.cstore.iter_crate_data(|_, other| {
-            if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id
+            if other.name() == root.name() && // same crate-name
+               other.disambiguator() == root.disambiguator() && // same crate-disambiguator
                other.hash() != root.hash()
             {
                 // but different SVH
@@ -406,7 +411,7 @@ fn register_crate(
                 None => (&source, &crate_root),
             };
             let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
-            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
+            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?)
         } else {
             None
         };
@@ -659,7 +664,7 @@ fn resolve_crate_deps(
     fn dlsym_proc_macros(
         &self,
         path: &Path,
-        stable_crate_id: StableCrateId,
+        disambiguator: CrateDisambiguator,
     ) -> Result<&'static [ProcMacro], CrateError> {
         // Make sure the path contains a / or the linker will search for it.
         let path = env::current_dir().unwrap().join(path);
@@ -668,7 +673,7 @@ fn dlsym_proc_macros(
             Err(s) => return Err(CrateError::DlOpen(s)),
         };
 
-        let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+        let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
         let decls = unsafe {
             let sym = match lib.symbol(&sym) {
                 Ok(f) => f,
index b830c6b2481ccddecf055edee79b79f6658c4dfe..6e7360950908e9dbd164ff0c7f7ecfebb93f4b91 100644 (file)
 use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::CanonicalizedPath;
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
@@ -787,7 +787,7 @@ pub fn find_plugin_registrar(
     metadata_loader: &dyn MetadataLoader,
     span: Span,
     name: Symbol,
-) -> (PathBuf, StableCrateId) {
+) -> (PathBuf, CrateDisambiguator) {
     match find_plugin_registrar_impl(sess, metadata_loader, name) {
         Ok(res) => res,
         // `core` is always available if we got as far as loading plugins.
@@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>(
     sess: &'a Session,
     metadata_loader: &dyn MetadataLoader,
     name: Symbol,
-) -> Result<(PathBuf, StableCrateId), CrateError> {
+) -> Result<(PathBuf, CrateDisambiguator), CrateError> {
     info!("find plugin registrar `{}`", name);
     let mut locator = CrateLocator::new(
         sess,
@@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>(
 
     match locator.maybe_load_library_crate()? {
         Some(library) => match library.source.dylib {
-            Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())),
+            Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())),
             None => Err(CrateError::NonDylibPlugin(name)),
         },
         None => Err(locator.into_error()),
index bc342119efb991caee85c946c82fa7c9f5331a41..cd4c394ae14ecf752d1deba6ff36927be57ca8ab 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::NativeLib;
+use rustc_middle::middle::cstore::{DllImport, NativeLib};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::utils::NativeLibKind;
@@ -33,8 +33,8 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let abi = match it.kind {
-            hir::ItemKind::ForeignMod { abi, .. } => abi,
+        let (abi, foreign_mod_items) = match it.kind {
+            hir::ItemKind::ForeignMod { abi, items } => (abi, items),
             _ => return,
         };
 
@@ -57,6 +57,7 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
                 foreign_module: Some(it.def_id.to_def_id()),
                 wasm_import_module: None,
                 verbatim: None,
+                dll_imports: Vec::new(),
             };
             let mut kind_specified = false;
 
@@ -196,6 +197,27 @@ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
                 .span_label(m.span, "missing `name` argument")
                 .emit();
             }
+
+            if lib.kind == NativeLibKind::RawDylib {
+                match abi {
+                    Abi::C { .. } => (),
+                    Abi::Cdecl => (),
+                    _ => {
+                        if sess.target.arch == "x86" {
+                            sess.span_fatal(
+                                it.span,
+                                r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
+                            );
+                        }
+                    }
+                };
+                lib.dll_imports.extend(
+                    foreign_mod_items
+                        .iter()
+                        .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+                );
+            }
+
             self.register_native_lib(Some(m.span), lib);
         }
     }
@@ -253,15 +275,42 @@ fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLib) {
             )
             .emit();
         }
-        if lib.kind == NativeLibKind::RawDylib && !self.tcx.features().raw_dylib {
-            feature_err(
-                &self.tcx.sess.parse_sess,
-                sym::raw_dylib,
-                span.unwrap_or(rustc_span::DUMMY_SP),
-                "kind=\"raw-dylib\" is unstable",
-            )
-            .emit();
+        // this just unwraps lib.name; we already established that it isn't empty above.
+        if let (NativeLibKind::RawDylib, Some(lib_name)) = (lib.kind, lib.name) {
+            let span = match span {
+                Some(s) => s,
+                None => {
+                    bug!("raw-dylib libraries are not supported on the command line");
+                }
+            };
+
+            if !self.tcx.sess.target.options.is_like_windows {
+                self.tcx.sess.span_fatal(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows",
+                );
+            } else if !self.tcx.sess.target.options.is_like_msvc {
+                self.tcx.sess.span_warn(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu",
+                );
+            }
+
+            if lib_name.as_str().contains('\0') {
+                self.tcx.sess.span_err(span, "library name may not contain NUL characters");
+            }
+
+            if !self.tcx.features().raw_dylib {
+                feature_err(
+                    &self.tcx.sess.parse_sess,
+                    sym::raw_dylib,
+                    span,
+                    "kind=\"raw-dylib\" is unstable",
+                )
+                .emit();
+            }
         }
+
         self.libs.push(lib);
     }
 
@@ -337,6 +386,7 @@ fn process_command_line(&mut self) {
                     foreign_module: None,
                     wasm_import_module: None,
                     verbatim: passed_lib.verbatim,
+                    dll_imports: Vec::new(),
                 };
                 self.register_native_lib(None, lib);
             } else {
index 59fec58f0a1b3037a65f22b28697825be7c8a0ef..52cb1e1996e382f4cc342ae28a99087d6458d3f5 100644 (file)
@@ -620,6 +620,10 @@ impl CrateRoot<'_> {
         self.name
     }
 
+    crate fn disambiguator(&self) -> CrateDisambiguator {
+        self.disambiguator
+    }
+
     crate fn hash(&self) -> Svh {
         self.hash
     }
@@ -1923,8 +1927,8 @@ impl CrateMetadata {
         self.root.name
     }
 
-    crate fn stable_crate_id(&self) -> StableCrateId {
-        self.root.stable_crate_id
+    crate fn disambiguator(&self) -> CrateDisambiguator {
+        self.root.disambiguator
     }
 
     crate fn hash(&self) -> Svh {
index 9e615e48a3cd0964a1f3300ee696caf13bcda993..7cec4ce1d91b2b34cab0127402a0be17402bbf94 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_session::utils::NativeLibKind;
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Symbol;
 
@@ -186,6 +186,7 @@ fn into_args(self) -> (DefId, DefId) {
     }
     native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
     foreign_modules => { cdata.get_foreign_modules(tcx) }
+    crate_disambiguator => { cdata.root.disambiguator }
     crate_hash => { cdata.root.hash }
     crate_host_hash => { cdata.host_hash }
     crate_name => { cdata.root.name }
@@ -488,8 +489,8 @@ fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
     }
 
-    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId {
-        self.get_crate_data(cnum).root.stable_crate_id
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
+        self.get_crate_data(cnum).root.disambiguator
     }
 
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh {
index 2fd9a46cf428dff7a84e6209c1272c20bea0572e..76007398000415fa8c772be9e21e2d14b49e6579 100644 (file)
@@ -671,6 +671,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
             triple: tcx.sess.opts.target_triple.clone(),
             hash: tcx.crate_hash(LOCAL_CRATE),
+            disambiguator: tcx.sess.local_crate_disambiguator(),
             stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
             panic_strategy: tcx.sess.panic_strategy(),
             edition: tcx.sess.edition(),
@@ -942,7 +943,7 @@ fn encode_def_ids(&mut self) {
             });
             record!(self.tables.span[def_id] <- tcx.def_span(def_id));
             record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
-            record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
+            record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
             if should_encode_visibility(def_kind) {
                 record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
             }
index 9a3a6284c36105abe8fd6911c78d7e74352aa835..04fe5cf5890a00ad24d46855137195fc01f18efa 100644 (file)
@@ -18,6 +18,7 @@
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
+use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{Ident, Symbol};
@@ -201,6 +202,7 @@ macro_rules! Lazy {
     triple: TargetTriple,
     extra_filename: String,
     hash: Svh,
+    disambiguator: CrateDisambiguator,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
     edition: Edition,
index aa54d1ae7b9d118426d9702dac6384725e0b50c4..8476929eaeced2b1d230e5e6f6d964e2e7d2a088 100644 (file)
@@ -285,7 +285,7 @@ pub mod label_strs {
 // required that their size stay the same, but we don't want to change
 // it inadvertently. This assert just ensures we're aware of any change.
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-static_assert_size!(DepNode, 17);
+static_assert_size!(DepNode, 18);
 
 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 static_assert_size!(DepNode, 24);
index 07b39c97c492a23d88928177f3884accbd0ed318..20bbf9097f4255c80287557d66197b27ff3d085e 100644 (file)
@@ -15,7 +15,6 @@
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::*;
 use rustc_index::vec::Idx;
-use rustc_span::def_id::StableCrateId;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -991,24 +990,25 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-    tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+    tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher);
     tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
 
     let crate_hash: Fingerprint = stable_hasher.finish();
     Svh::new(crate_hash.to_smaller_hash())
 }
 
-fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> {
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
     let mut upstream_crates: Vec<_> = cstore
         .crates_untracked()
         .iter()
         .map(|&cnum| {
-            let stable_crate_id = cstore.stable_crate_id_untracked(cnum);
+            let name = cstore.crate_name_untracked(cnum);
+            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
             let hash = cstore.crate_hash_untracked(cnum);
-            (stable_crate_id, hash)
+            (name, disambiguator, hash)
         })
         .collect();
-    upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
+    upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
     upstream_crates
 }
 
index b8407833c903b23d8fcd15e59679cb7ce3befd52..087f772c812bdb2cf5a2aade1900cd4d8c59f398 100644 (file)
@@ -167,4 +167,8 @@ pub fn provide(providers: &mut Providers) {
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
     providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
+    providers.expn_that_defined = |tcx, id| {
+        let id = id.expect_local();
+        tcx.definitions.expansion_that_defined(id)
+    };
 }
index 38d0793a6825fd9c4e545c61d1ebaa240fa3e4d8..4c7ea937ceb7dd1d9f486b05daba3248c89674c7 100644 (file)
@@ -1,7 +1,7 @@
 use std::cmp;
 
 use crate::ich::StableHashingContext;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
@@ -28,6 +28,9 @@ pub enum LintLevelSource {
     /// The provided `Level` is the level specified on the command line.
     /// (The actual level may be lower due to `--cap-lints`.)
     CommandLine(Symbol, Level),
+
+    /// Lint is being forced to warn no matter what.
+    ForceWarn(Symbol),
 }
 
 impl LintLevelSource {
@@ -36,6 +39,7 @@ pub fn name(&self) -> Symbol {
             LintLevelSource::Default => symbol::kw::Default,
             LintLevelSource::Node(name, _, _) => name,
             LintLevelSource::CommandLine(name, _) => name,
+            LintLevelSource::ForceWarn(name) => name,
         }
     }
 
@@ -44,6 +48,7 @@ pub fn span(&self) -> Span {
             LintLevelSource::Default => DUMMY_SP,
             LintLevelSource::Node(_, span, _) => span,
             LintLevelSource::CommandLine(_, _) => DUMMY_SP,
+            LintLevelSource::ForceWarn(_) => DUMMY_SP,
         }
     }
 }
@@ -55,6 +60,7 @@ pub fn span(&self) -> Span {
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
     pub lint_cap: Level,
+    pub force_warns: FxHashSet<LintId>,
 }
 
 #[derive(Debug)]
@@ -73,7 +79,11 @@ pub enum LintSet {
 
 impl LintLevelSets {
     pub fn new() -> Self {
-        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+        LintLevelSets {
+            list: Vec::new(),
+            lint_cap: Level::Forbid,
+            force_warns: FxHashSet::default(),
+        }
     }
 
     pub fn get_lint_level(
@@ -83,6 +93,11 @@ pub fn get_lint_level(
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
     ) -> LevelAndSource {
+        // Check whether we should always warn
+        if self.force_warns.contains(&LintId::of(lint)) {
+            return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name)));
+        }
+
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -176,11 +191,11 @@ pub fn level_and_source(
 impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
+        let LintLevelMap { ref sets, ref id_to_set, .. } = *self;
 
         id_to_set.hash_stable(hcx, hasher);
 
-        let LintLevelSets { ref list, lint_cap } = *sets;
+        let LintLevelSets { ref list, lint_cap, .. } = *sets;
 
         lint_cap.hash_stable(hcx, hasher);
 
@@ -346,6 +361,13 @@ fn struct_lint_level_impl(
                     );
                 }
             }
+            LintLevelSource::ForceWarn(_) => {
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    "warning forced by `force-warns` commandline option",
+                );
+            }
         }
 
         err.code(DiagnosticId::Lint { name, has_future_breakage });
index dd3b0a40d69462fc90792fdde723c47c40d851d5..f09449ab864b7eadad16e6a1396dd2a6e796e611 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_macros::HashStable;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
-use rustc_session::StableCrateId;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
@@ -95,6 +95,13 @@ pub struct NativeLib {
     pub foreign_module: Option<DefId>,
     pub wasm_import_module: Option<Symbol>,
     pub verbatim: Option<bool>,
+    pub dll_imports: Vec<DllImport>,
+}
+
+#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+pub struct DllImport {
+    pub name: Symbol,
+    pub ordinal: Option<u16>,
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
@@ -199,7 +206,7 @@ fn def_path_hash_to_def_id(
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
-    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId;
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
 
     // This is basically a 1-based range of ints, which is a little
index 5ea78e087f8451c34d6503dc45060f4f93bdfc46..288dd0394464581691c16201964eaa7b2f085d8e 100644 (file)
@@ -48,8 +48,8 @@ pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolNam
 
 pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
-        "rust_metadata_{}_{:08x}",
+        "rust_metadata_{}_{}",
         tcx.crate_name(LOCAL_CRATE),
-        tcx.sess.local_stable_crate_id().to_u64(),
+        tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
     )
 }
index c354cdd985b36df3ee1c94aaff3381444eda5dbb..74650f50a1c8aa6385cc7d82fa6cba005be6ff23 100644 (file)
@@ -490,18 +490,15 @@ pub fn build_cgu_name_no_mangle<I, C, S>(
             // local crate's ID. Otherwise there can be collisions between CGUs
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
-                let local_stable_crate_id = tcx.sess.local_stable_crate_id();
-                format!(
-                    "-in-{}.{:08x}",
-                    tcx.crate_name(LOCAL_CRATE),
-                    local_stable_crate_id.to_u64()
-                )
+                let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE));
+                format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8])
             } else {
                 String::new()
             };
 
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id.to_u64(), local_crate_id)
+            let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
+            // Using a shortened disambiguator of about 40 bits
+            format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id)
         });
 
         write!(cgu_name, "{}", crate_prefix).unwrap();
index f65dfea04eb00cc1f2fe62e96ce880e951d4ea85..0860520ef9dfe8aa1dca8fab66ba9198489a9b95 100644 (file)
         desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
-    /// Internal helper query. Use `tcx.expansion_that_defined` instead
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
+        eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
     }
 
     query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
         desc { "looking up the derive registrar for a crate" }
     }
+    query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
+        eval_always
+        desc { "looking up the disambiguator a crate" }
+    }
     // The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
     // Changing the name should cause a compiler error, but in case that changes, be aware.
     query crate_hash(_: CrateNum) -> Svh {
index 8e2c79701af90d76d48d6979e23a08c4f7fd35ea..02ff1b9f4d655ff15fc191617eccd1439e7dfd29 100644 (file)
@@ -46,6 +46,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
index 970e669c16f7024fc9cea806d567855c4f0001c6..047b95f116ec2cec8a79659a4713a4b68459708e 100644 (file)
@@ -1275,24 +1275,24 @@ pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash
 
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
-        // crate name and stable crate id since this code is called from debug!()
+        // crate name and disambiguator since this code is called from debug!()
         // statements within the query system and we'd run into endless
         // recursion otherwise.
-        let (crate_name, stable_crate_id) = if def_id.is_local() {
-            (self.crate_name, self.sess.local_stable_crate_id())
+        let (crate_name, crate_disambiguator) = if def_id.is_local() {
+            (self.crate_name, self.sess.local_crate_disambiguator())
         } else {
             (
                 self.cstore.crate_name_untracked(def_id.krate),
-                self.def_path_hash(def_id.krate.as_def_id()).stable_crate_id(),
+                self.cstore.crate_disambiguator_untracked(def_id.krate),
             )
         };
 
         format!(
             "{}[{}]{}",
             crate_name,
-            // Don't print the whole stable crate id. That's just
+            // Don't print the whole crate disambiguator. That's just
             // annoying in debug output.
-            &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
+            &(crate_disambiguator.to_fingerprint().to_hex())[..4],
             self.def_path(def_id).to_string_no_crate_verbose()
         )
     }
index 03a026500d70259c0db2ae0620362e532253427d..28a44b09de2b112ce0e8a366ca541b3ef51329d6 100644 (file)
@@ -367,7 +367,14 @@ fn univariant_uninterned(
         for &i in &inverse_memory_index {
             let field = fields[i as usize];
             if !sized {
-                bug!("univariant: field #{} of `{}` comes after unsized field", offsets.len(), ty);
+                self.tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    &format!(
+                        "univariant: field #{} of `{}` comes after unsized field",
+                        offsets.len(),
+                        ty
+                    ),
+                );
             }
 
             if field.is_unsized() {
index af2be37f387dc115c953061fb8ba597179b2430c..b58c92b8415175c748752757eed4cff4ef04fb75 100644 (file)
@@ -39,7 +39,6 @@
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
 use rustc_hir::{Constness, Node};
 use rustc_macros::HashStable;
-use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::Align;
@@ -72,7 +71,7 @@
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
     GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
     PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
-    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
+    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
 };
 pub use self::trait_def::TraitDef;
 
@@ -1862,20 +1861,11 @@ pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: De
             && use_name
                 .span
                 .ctxt()
-                .hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id))
-    }
-
-    pub fn expansion_that_defined(self, scope: DefId) -> ExpnId {
-        match scope.as_local() {
-            // Parsing and expansion aren't incremental, so we don't
-            // need to go through a query for the same-crate case.
-            Some(scope) => self.hir().definitions().expansion_that_defined(scope),
-            None => self.expn_that_defined(scope),
-        }
+                .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id))
     }
 
     pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
-        ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope));
+        ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope));
         ident
     }
 
@@ -1886,8 +1876,7 @@ pub fn adjust_ident_and_get_scope(
         block: hir::HirId,
     ) -> (Ident, DefId) {
         let scope =
-            match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope))
-            {
+            match ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) {
                 Some(actual_expansion) => {
                     self.hir().definitions().parent_module_of_macro_def(actual_expansion)
                 }
index a5b540dcb70cd55438db56ecf94148789938fd50..297110ee3ecff36950a33be1bd8babb3b86e57cc 100644 (file)
@@ -47,6 +47,7 @@
 use rustc_serialize::opaque;
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
+use rustc_session::CrateDisambiguator;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast as ast;
index e473559812fe6222c67201231004d279a88bb0a0..ebb52d8863f37ecc727fc8147714dfdea626e0d9 100644 (file)
@@ -18,7 +18,7 @@
     opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
     Decodable, Decoder, Encodable, Encoder,
 };
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{
     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
     SyntaxContext, SyntaxContextData,
@@ -52,7 +52,7 @@ pub struct OnDiskCache<'sess> {
     // session.
     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
 
-    prev_cnums: Vec<(u32, StableCrateId)>,
+    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
 
     source_map: &'sess SourceMap,
@@ -120,7 +120,7 @@ pub struct OnDiskCache<'sess> {
 #[derive(Encodable, Decodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
-    prev_cnums: Vec<(u32, StableCrateId)>,
+    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     query_result_index: EncodedQueryResultIndex,
     diagnostics_index: EncodedQueryResultIndex,
     // The location of all allocations.
@@ -349,8 +349,9 @@ pub fn serialize<'tcx>(
             let prev_cnums: Vec<_> = sorted_cnums
                 .iter()
                 .map(|&cnum| {
-                    let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (cnum.as_u32(), stable_crate_id)
+                    let crate_name = tcx.crate_name(cnum).to_string();
+                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                    (cnum.as_u32(), crate_name, crate_disambiguator)
                 })
                 .collect();
 
@@ -574,23 +575,25 @@ fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
     // maps to None.
     fn compute_cnum_map(
         tcx: TyCtxt<'_>,
-        prev_cnums: &[(u32, StableCrateId)],
+        prev_cnums: &[(u32, String, CrateDisambiguator)],
     ) -> IndexVec<CrateNum, Option<CrateNum>> {
         tcx.dep_graph.with_ignore(|| {
             let current_cnums = tcx
                 .all_crate_nums(())
                 .iter()
                 .map(|&cnum| {
-                    let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (stable_crate_id, cnum)
+                    let crate_name = tcx.crate_name(cnum).to_string();
+                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                    ((crate_name, crate_disambiguator), cnum)
                 })
                 .collect::<FxHashMap<_, _>>();
 
             let map_size = prev_cnums.iter().map(|&(cnum, ..)| cnum).max().unwrap_or(0) + 1;
             let mut map = IndexVec::from_elem_n(None, map_size as usize);
 
-            for &(prev_cnum, stable_crate_id) in prev_cnums {
-                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&stable_crate_id).cloned();
+            for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
+                let key = (crate_name.clone(), crate_disambiguator);
+                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
             }
 
             map[LOCAL_CRATE] = Some(LOCAL_CRATE);
index b6f93c9bd59e79bbe51efb25aefa106fdcea6e10..872d12cac9384ab086d829be8e856facb9c1c643 100644 (file)
@@ -67,6 +67,7 @@ fn relate_item_substs(
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T>;
@@ -111,24 +112,23 @@ fn relate<R: TypeRelation<'tcx>>(
 ///////////////////////////////////////////////////////////////////////////
 // Relate impls
 
-impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::TypeAndMut<'tcx>,
-        b: ty::TypeAndMut<'tcx>,
-    ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
-        debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
-        if a.mutbl != b.mutbl {
-            Err(TypeError::Mutability)
-        } else {
-            let mutbl = a.mutbl;
-            let variance = match mutbl {
-                ast::Mutability::Not => ty::Covariant,
-                ast::Mutability::Mut => ty::Invariant,
-            };
-            let ty = relation.relate_with_variance(variance, a.ty, b.ty)?;
-            Ok(ty::TypeAndMut { ty, mutbl })
-        }
+fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
+    relation: &mut R,
+    a: ty::TypeAndMut<'tcx>,
+    b: ty::TypeAndMut<'tcx>,
+    kind: ty::VarianceDiagMutKind,
+) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
+    debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
+    if a.mutbl != b.mutbl {
+        Err(TypeError::Mutability)
+    } else {
+        let mutbl = a.mutbl;
+        let (variance, info) = match mutbl {
+            ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
+            ast::Mutability::Mut => (ty::Invariant, ty::VarianceDiagInfo::Mut { kind, ty: a.ty }),
+        };
+        let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?;
+        Ok(ty::TypeAndMut { ty, mutbl })
     }
 }
 
@@ -142,7 +142,7 @@ pub fn relate_substs<R: TypeRelation<'tcx>>(
 
     let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
-        relation.relate_with_variance(variance, a, b)
+        relation.relate_with_variance(variance, ty::VarianceDiagInfo::default(), a, b)
     });
 
     tcx.mk_substs(params)
@@ -177,7 +177,12 @@ fn relate<R: TypeRelation<'tcx>>(
                 if is_output {
                     relation.relate(a, b)
                 } else {
-                    relation.relate_with_variance(ty::Contravariant, a, b)
+                    relation.relate_with_variance(
+                        ty::Contravariant,
+                        ty::VarianceDiagInfo::default(),
+                        a,
+                        b,
+                    )
                 }
             })
             .enumerate()
@@ -251,8 +256,18 @@ fn relate<R: TypeRelation<'tcx>>(
                 b.item_def_id,
             )))
         } else {
-            let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
-            let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?;
+            let ty = relation.relate_with_variance(
+                ty::Invariant,
+                ty::VarianceDiagInfo::default(),
+                a.ty,
+                b.ty,
+            )?;
+            let substs = relation.relate_with_variance(
+                ty::Invariant,
+                ty::VarianceDiagInfo::default(),
+                a.substs,
+                b.substs,
+            )?;
             Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
         }
     }
@@ -364,7 +379,12 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
 
         (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => {
             let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
-                relation.relate_with_variance(ty::Contravariant, a_region, b_region)
+                relation.relate_with_variance(
+                    ty::Contravariant,
+                    ty::VarianceDiagInfo::default(),
+                    a_region,
+                    b_region,
+                )
             })?;
             Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
         }
@@ -398,15 +418,20 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
         }
 
         (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
-            let mt = relation.relate(a_mt, b_mt)?;
+            let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::RawPtr)?;
             Ok(tcx.mk_ptr(mt))
         }
 
         (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
-            let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?;
+            let r = relation.relate_with_variance(
+                ty::Contravariant,
+                ty::VarianceDiagInfo::default(),
+                a_r,
+                b_r,
+            )?;
             let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
             let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
-            let mt = relation.relate(a_mt, b_mt)?;
+            let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::Ref)?;
             Ok(tcx.mk_ref(r, mt))
         }
 
@@ -536,8 +561,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if au.def == bu.def && au.promoted == bu.promoted =>
         {
-            let substs =
-                relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?;
+            let substs = relation.relate_with_variance(
+                ty::Variance::Invariant,
+                ty::VarianceDiagInfo::default(),
+                au.substs,
+                bu.substs,
+            )?;
             return Ok(tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: au.def,
index 012d9bd82c816538793af066b3b1c2c229ad9cf0..1d9ff512288db9b05e140f6f4d224fa35b60f36a 100644 (file)
@@ -1890,11 +1890,6 @@ pub fn is_ptr_sized_integral(&self) -> bool {
         matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize))
     }
 
-    #[inline]
-    pub fn is_machine(&self) -> bool {
-        matches!(self.kind(), Int(..) | Uint(..) | Float(..))
-    }
-
     #[inline]
     pub fn has_concrete_skeleton(&self) -> bool {
         !matches!(self.kind(), Param(_) | Infer(_) | Error(_))
@@ -2186,3 +2181,55 @@ pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
         }
     }
 }
+
+/// Extra information about why we ended up with a particular variance.
+/// This is only used to add more information to error messages, and
+/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
+/// may lead to confusing notes in error messages, it will never cause
+/// a miscompilation or unsoundness.
+///
+/// When in doubt, use `VarianceDiagInfo::default()`
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum VarianceDiagInfo<'tcx> {
+    /// No additional information - this is the default.
+    /// We will not add any additional information to error messages.
+    None,
+    /// We switched our variance because a type occurs inside
+    /// the generic argument of a mutable reference or pointer
+    /// (`*mut T` or `&mut T`). In either case, our variance
+    /// will always be `Invariant`.
+    Mut {
+        /// Tracks whether we had a mutable pointer or reference,
+        /// for better error messages
+        kind: VarianceDiagMutKind,
+        /// The type parameter of the mutable pointer/reference
+        /// (the `T` in `&mut T` or `*mut T`).
+        ty: Ty<'tcx>,
+    },
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum VarianceDiagMutKind {
+    /// A mutable raw pointer (`*mut T`)
+    RawPtr,
+    /// A mutable reference (`&mut T`)
+    Ref,
+}
+
+impl<'tcx> VarianceDiagInfo<'tcx> {
+    /// Mirrors `Variance::xform` - used to 'combine' the existing
+    /// and new `VarianceDiagInfo`s when our variance changes.
+    pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
+        // For now, just use the first `VarianceDiagInfo::Mut` that we see
+        match self {
+            VarianceDiagInfo::None => other,
+            VarianceDiagInfo::Mut { .. } => self,
+        }
+    }
+}
+
+impl<'tcx> Default for VarianceDiagInfo<'tcx> {
+    fn default() -> Self {
+        Self::None
+    }
+}
index f3f6b8c10da7ce1d47949d5acc341b4bf5f3b605..9e4cfb2cc00fa0f541e51649c229d0c0f18da8fb 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_data_structures::graph;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use rustc_span::DUMMY_SP;
 
 use crate::borrow_check::{
@@ -26,8 +26,8 @@
 /// Marker trait that controls whether a `R1: R2` constraint
 /// represents an edge `R1 -> R2` or `R2 -> R1`.
 crate trait ConstraintGraphDirecton: Copy + 'static {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid;
-    fn end_region(c: &OutlivesConstraint) -> RegionVid;
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid;
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid;
     fn is_normal() -> bool;
 }
 
 crate struct Normal;
 
 impl ConstraintGraphDirecton for Normal {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid {
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sup
     }
 
-    fn end_region(c: &OutlivesConstraint) -> RegionVid {
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sub
     }
 
@@ -60,11 +60,11 @@ fn is_normal() -> bool {
 crate struct Reverse;
 
 impl ConstraintGraphDirecton for Reverse {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid {
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sub
     }
 
-    fn end_region(c: &OutlivesConstraint) -> RegionVid {
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sup
     }
 
@@ -78,7 +78,7 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
     /// reporting.
-    crate fn new(direction: D, set: &OutlivesConstraintSet, num_region_vars: usize) -> Self {
+    crate fn new(direction: D, set: &OutlivesConstraintSet<'_>, num_region_vars: usize) -> Self {
         let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
         let mut next_constraints = IndexVec::from_elem(None, &set.outlives);
 
@@ -96,21 +96,21 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// Given the constraint set from which this graph was built
     /// creates a region graph so that you can iterate over *regions*
     /// and not constraints.
-    crate fn region_graph<'rg>(
+    crate fn region_graph<'rg, 'tcx>(
         &'rg self,
-        set: &'rg OutlivesConstraintSet,
+        set: &'rg OutlivesConstraintSet<'tcx>,
         static_region: RegionVid,
-    ) -> RegionGraph<'rg, D> {
+    ) -> RegionGraph<'rg, 'tcx, D> {
         RegionGraph::new(set, self, static_region)
     }
 
     /// Given a region `R`, iterate over all constraints `R: R1`.
-    crate fn outgoing_edges<'a>(
+    crate fn outgoing_edges<'a, 'tcx>(
         &'a self,
         region_sup: RegionVid,
-        constraints: &'a OutlivesConstraintSet,
+        constraints: &'a OutlivesConstraintSet<'tcx>,
         static_region: RegionVid,
-    ) -> Edges<'a, D> {
+    ) -> Edges<'a, 'tcx, D> {
         //if this is the `'static` region and the graph's direction is normal,
         //then setup the Edges iterator to return all regions #53178
         if region_sup == static_region && D::is_normal() {
@@ -129,22 +129,22 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     }
 }
 
-crate struct Edges<'s, D: ConstraintGraphDirecton> {
+crate struct Edges<'s, 'tcx, D: ConstraintGraphDirecton> {
     graph: &'s ConstraintGraph<D>,
-    constraints: &'s OutlivesConstraintSet,
+    constraints: &'s OutlivesConstraintSet<'tcx>,
     pointer: Option<OutlivesConstraintIndex>,
     next_static_idx: Option<usize>,
     static_region: RegionVid,
 }
 
-impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
-    type Item = OutlivesConstraint;
+impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
+    type Item = OutlivesConstraint<'tcx>;
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(p) = self.pointer {
             self.pointer = self.graph.next_constraints[p];
 
-            Some(self.constraints[p])
+            Some(self.constraints[p].clone())
         } else if let Some(next_static_idx) = self.next_static_idx {
             self.next_static_idx = if next_static_idx == (self.graph.first_constraints.len() - 1) {
                 None
@@ -157,6 +157,7 @@ fn next(&mut self) -> Option<Self::Item> {
                 sub: next_static_idx.into(),
                 locations: Locations::All(DUMMY_SP),
                 category: ConstraintCategory::Internal,
+                variance_info: VarianceDiagInfo::default(),
             })
         } else {
             None
@@ -167,19 +168,19 @@ fn next(&mut self) -> Option<Self::Item> {
 /// This struct brings together a constraint set and a (normal, not
 /// reverse) constraint graph. It implements the graph traits and is
 /// usd for doing the SCC computation.
-crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
-    set: &'s OutlivesConstraintSet,
+crate struct RegionGraph<'s, 'tcx, D: ConstraintGraphDirecton> {
+    set: &'s OutlivesConstraintSet<'tcx>,
     constraint_graph: &'s ConstraintGraph<D>,
     static_region: RegionVid,
 }
 
-impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> {
     /// Creates a "dependency graph" where each region constraint `R1:
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
     /// reporting.
     crate fn new(
-        set: &'s OutlivesConstraintSet,
+        set: &'s OutlivesConstraintSet<'tcx>,
         constraint_graph: &'s ConstraintGraph<D>,
         static_region: RegionVid,
     ) -> Self {
@@ -188,18 +189,18 @@ impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
 
     /// Given a region `R`, iterate over all regions `R1` such that
     /// there exists a constraint `R: R1`.
-    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
+    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, 'tcx, D> {
         Successors {
             edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
         }
     }
 }
 
-crate struct Successors<'s, D: ConstraintGraphDirecton> {
-    edges: Edges<'s, D>,
+crate struct Successors<'s, 'tcx, D: ConstraintGraphDirecton> {
+    edges: Edges<'s, 'tcx, D>,
 }
 
-impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Successors<'s, 'tcx, D> {
     type Item = RegionVid;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -207,23 +208,26 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, 'tcx, D> {
     type Node = RegionVid;
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, 'tcx, D> {
     fn num_nodes(&self) -> usize {
         self.constraint_graph.first_constraints.len()
     }
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, 'tcx, D> {
     fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::Iter {
         self.outgoing_regions(node)
     }
 }
 
-impl<'s, 'graph, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph> for RegionGraph<'s, D> {
+impl<'s, 'graph, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph>
+    for RegionGraph<'s, 'tcx, D>
+{
     type Item = RegionVid;
-    type Iter = Successors<'graph, D>;
+    // FIXME - why can't this be `'graph, 'tcx`
+    type Iter = Successors<'graph, 'graph, D>;
 }
index 3772b7d8f986db68d79db028e181c9f8c6558dff..b944479ca456b387fe7dd23c44e1be17a2840308 100644 (file)
@@ -1,7 +1,7 @@
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use std::fmt;
 use std::ops::Index;
 
 /// a unique `OutlivesConstraintIndex` and you can index into the set
 /// (`constraint_set[i]`) to access the constraint details.
 #[derive(Clone, Default)]
-crate struct OutlivesConstraintSet {
-    outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint>,
+crate struct OutlivesConstraintSet<'tcx> {
+    outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>>,
 }
 
-impl OutlivesConstraintSet {
-    crate fn push(&mut self, constraint: OutlivesConstraint) {
+impl<'tcx> OutlivesConstraintSet<'tcx> {
+    crate fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
         debug!(
             "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
             constraint.sup, constraint.sub, constraint.locations
@@ -59,21 +59,21 @@ impl OutlivesConstraintSet {
         Sccs::new(region_graph)
     }
 
-    crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint> {
+    crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
         &self.outlives
     }
 }
 
-impl Index<OutlivesConstraintIndex> for OutlivesConstraintSet {
-    type Output = OutlivesConstraint;
+impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> {
+    type Output = OutlivesConstraint<'tcx>;
 
     fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output {
         &self.outlives[i]
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct OutlivesConstraint {
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct OutlivesConstraint<'tcx> {
     // NB. The ordering here is not significant for correctness, but
     // it is for convenience. Before we dump the constraints in the
     // debugging logs, we sort them, and we'd like the "super region"
@@ -89,11 +89,18 @@ pub struct OutlivesConstraint {
 
     /// What caused this constraint?
     pub category: ConstraintCategory,
+
+    /// Variance diagnostic information
+    pub variance_info: VarianceDiagInfo<'tcx>,
 }
 
-impl fmt::Debug for OutlivesConstraint {
+impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(formatter, "({:?}: {:?}) due to {:?}", self.sup, self.sub, self.locations)
+        write!(
+            formatter,
+            "({:?}: {:?}) due to {:?} ({:?})",
+            self.sup, self.sub, self.locations, self.variance_info
+        )
     }
 }
 
index 1b0cae51d585df974fcad6604a62dd800596ab75..e9f1ecb9bbc81dec0af6123ecb6402f742d69c55 100644 (file)
@@ -15,6 +15,7 @@
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
+use crate::borrow_check::region_infer::BlameConstraint;
 use crate::borrow_check::{
     borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
     WriteKind,
@@ -289,12 +290,13 @@ fn free_region_constraint_info(
         borrow_region: RegionVid,
         outlived_region: RegionVid,
     ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
-        let (category, from_closure, span) = self.regioncx.best_blame_constraint(
-            &self.body,
-            borrow_region,
-            NllRegionVariableOrigin::FreeRegion,
-            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
-        );
+        let BlameConstraint { category, from_closure, span, variance_info: _ } =
+            self.regioncx.best_blame_constraint(
+                &self.body,
+                borrow_region,
+                NllRegionVariableOrigin::FreeRegion,
+                |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+            );
 
         let outlived_fr_name = self.give_region_a_name(outlived_region);
 
index 8665ef06126a1b395c80fc8d71cbbc4e13b5352e..feb7672f650ecdd1338e55b04693bd211db9d2b8 100644 (file)
@@ -13,6 +13,7 @@
 
 use crate::util::borrowck_errors;
 
+use crate::borrow_check::region_infer::BlameConstraint;
 use crate::borrow_check::{
     nll::ConstraintDescription,
     region_infer::{values::RegionElement, TypeTest},
@@ -275,12 +276,12 @@ pub(in crate::borrow_check) fn report_region_error(
     ) {
         debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, _, span) =
+        let BlameConstraint { category, span, variance_info, from_closure: _ } =
             self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
                 self.regioncx.provides_universal_region(r, fr, outlived_fr)
             });
 
-        debug!("report_region_error: category={:?} {:?}", category, span);
+        debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
             let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
@@ -309,7 +310,7 @@ pub(in crate::borrow_check) fn report_region_error(
             span,
         };
 
-        let diag = match (category, fr_is_local, outlived_fr_is_local) {
+        let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
                 self.report_fnmut_error(&errci, kind)
             }
@@ -332,6 +333,19 @@ pub(in crate::borrow_check) fn report_region_error(
             }
         };
 
+        match variance_info {
+            ty::VarianceDiagInfo::None => {}
+            ty::VarianceDiagInfo::Mut { kind, ty } => {
+                let kind_name = match kind {
+                    ty::VarianceDiagMutKind::Ref => "reference",
+                    ty::VarianceDiagMutKind::RawPtr => "pointer",
+                };
+                diag.note(&format!("requirement occurs because of a mutable {kind_name} to {ty}",));
+                diag.note(&format!("mutable {kind_name}s are invariant over their type parameter"));
+                diag.help("see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance");
+            }
+        }
+
         diag.buffer(&mut self.errors_buffer);
     }
 
index 5892ef37ebacb56df38b1306bfae5f16a7bc3eed..213ebff12abc0b65940e94f9845232c3c83cfa95 100644 (file)
@@ -74,7 +74,7 @@ fn for_each_constraint(
         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort();
         for constraint in &constraints {
-            let OutlivesConstraint { sup, sub, locations, category } = constraint;
+            let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint;
             let (name, arg) = match locations {
                 Locations::All(span) => {
                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
index 7156612f4730f05d3917bb7b8b2b5e79bda3a27e..b944d74e6f23137b3040974955e291d9ce70e26d 100644 (file)
@@ -35,7 +35,7 @@ struct RawConstraints<'a, 'tcx> {
 
 impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
     type Node = RegionVid;
-    type Edge = OutlivesConstraint;
+    type Edge = OutlivesConstraint<'tcx>;
 
     fn graph_id(&'this self) -> dot::Id<'this> {
         dot::Id::new("RegionInferenceContext").unwrap()
@@ -49,31 +49,31 @@ fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
     fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", n).into())
     }
-    fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
+    fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
     }
 }
 
 impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
     type Node = RegionVid;
-    type Edge = OutlivesConstraint;
+    type Edge = OutlivesConstraint<'tcx>;
 
     fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
         let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
         vids.into()
     }
-    fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
+    fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint<'tcx>> {
         (&self.regioncx.constraints.outlives().raw[..]).into()
     }
 
     // Render `a: b` as `a -> b`, indicating the flow
     // of data during inference.
 
-    fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
+    fn source(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
         edge.sup
     }
 
-    fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
+    fn target(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
         edge.sub
     }
 }
index f4d78ac04cb029832ac6bf40d8f19033c6e825a4..dded7a7e3cf99e47166e2997d7c364369866490e 100644 (file)
@@ -54,7 +54,7 @@ pub struct RegionInferenceContext<'tcx> {
     liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Frozen<OutlivesConstraintSet>,
+    constraints: Frozen<OutlivesConstraintSet<'tcx>>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
@@ -227,10 +227,10 @@ enum RegionRelationCheckResult {
     Error,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum Trace {
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum Trace<'tcx> {
     StartRegion,
-    FromOutlivesConstraint(OutlivesConstraint),
+    FromOutlivesConstraint(OutlivesConstraint<'tcx>),
     NotVisited,
 }
 
@@ -247,7 +247,7 @@ pub(in crate::borrow_check) fn new(
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-        outlives_constraints: OutlivesConstraintSet,
+        outlives_constraints: OutlivesConstraintSet<'tcx>,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
         closure_bounds_mapping: FxHashMap<
             Location,
@@ -1750,20 +1750,35 @@ fn check_member_constraints(
     crate fn retrieve_closure_constraint_info(
         &self,
         body: &Body<'tcx>,
-        constraint: &OutlivesConstraint,
-    ) -> (ConstraintCategory, bool, Span) {
+        constraint: &OutlivesConstraint<'tcx>,
+    ) -> BlameConstraint<'tcx> {
         let loc = match constraint.locations {
-            Locations::All(span) => return (constraint.category, false, span),
+            Locations::All(span) => {
+                return BlameConstraint {
+                    category: constraint.category,
+                    from_closure: false,
+                    span,
+                    variance_info: constraint.variance_info.clone(),
+                };
+            }
             Locations::Single(loc) => loc,
         };
 
         let opt_span_category =
             self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
-        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
-            constraint.category,
-            false,
-            body.source_info(loc).span,
-        ))
+        opt_span_category
+            .map(|&(category, span)| BlameConstraint {
+                category,
+                from_closure: true,
+                span: span,
+                variance_info: constraint.variance_info.clone(),
+            })
+            .unwrap_or(BlameConstraint {
+                category: constraint.category,
+                from_closure: false,
+                span: body.source_info(loc).span,
+                variance_info: constraint.variance_info.clone(),
+            })
     }
 
     /// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
@@ -1774,9 +1789,10 @@ fn check_member_constraints(
         fr1_origin: NllRegionVariableOrigin,
         fr2: RegionVid,
     ) -> (ConstraintCategory, Span) {
-        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
-            self.provides_universal_region(r, fr1, fr2)
-        });
+        let BlameConstraint { category, span, .. } =
+            self.best_blame_constraint(body, fr1, fr1_origin, |r| {
+                self.provides_universal_region(r, fr1, fr2)
+            });
         (category, span)
     }
 
@@ -1792,7 +1808,7 @@ fn check_member_constraints(
         &self,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
+    ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
         let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
         context[from_region] = Trace::StartRegion;
 
@@ -1816,14 +1832,14 @@ fn check_member_constraints(
                 let mut result = vec![];
                 let mut p = r;
                 loop {
-                    match context[p] {
+                    match context[p].clone() {
                         Trace::NotVisited => {
                             bug!("found unvisited region {:?} on path to {:?}", p, r)
                         }
 
                         Trace::FromOutlivesConstraint(c) => {
-                            result.push(c);
                             p = c.sup;
+                            result.push(c);
                         }
 
                         Trace::StartRegion => {
@@ -1846,7 +1862,7 @@ fn check_member_constraints(
 
             // Always inline this closure because it can be hot.
             let mut handle_constraint = #[inline(always)]
-            |constraint: OutlivesConstraint| {
+            |constraint: OutlivesConstraint<'tcx>| {
                 debug_assert_eq!(constraint.sup, r);
                 let sub_region = constraint.sub;
                 if let Trace::NotVisited = context[sub_region] {
@@ -1870,6 +1886,7 @@ fn check_member_constraints(
                     sub: constraint.min_choice,
                     locations: Locations::All(p_c.definition_span),
                     category: ConstraintCategory::OpaqueType,
+                    variance_info: ty::VarianceDiagInfo::default(),
                 };
                 handle_constraint(constraint);
             }
@@ -1967,7 +1984,7 @@ fn check_member_constraints(
         from_region: RegionVid,
         from_region_origin: NllRegionVariableOrigin,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> (ConstraintCategory, bool, Span) {
+    ) -> BlameConstraint<'tcx> {
         debug!(
             "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
             from_region, from_region_origin
@@ -1979,7 +1996,7 @@ fn check_member_constraints(
         debug!(
             "best_blame_constraint: path={:#?}",
             path.iter()
-                .map(|&c| format!(
+                .map(|c| format!(
                     "{:?} ({:?}: {:?})",
                     c,
                     self.constraint_sccs.scc(c.sup),
@@ -1989,13 +2006,18 @@ fn check_member_constraints(
         );
 
         // Classify each of the constraints along the path.
-        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
+        let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
             .iter()
             .map(|constraint| {
                 if constraint.category == ConstraintCategory::ClosureBounds {
                     self.retrieve_closure_constraint_info(body, &constraint)
                 } else {
-                    (constraint.category, false, constraint.locations.span(body))
+                    BlameConstraint {
+                        category: constraint.category,
+                        from_closure: false,
+                        span: constraint.locations.span(body),
+                        variance_info: constraint.variance_info.clone(),
+                    }
                 }
             })
             .collect();
@@ -2067,12 +2089,12 @@ fn check_member_constraints(
         };
 
         let find_region = |i: &usize| {
-            let constraint = path[*i];
+            let constraint = &path[*i];
 
             let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
 
             if blame_source {
-                match categorized_path[*i].0 {
+                match categorized_path[*i].category {
                     ConstraintCategory::OpaqueType
                     | ConstraintCategory::Boring
                     | ConstraintCategory::BoringNoLocation
@@ -2083,7 +2105,7 @@ fn check_member_constraints(
                     _ => constraint_sup_scc != target_scc,
                 }
             } else {
-                match categorized_path[*i].0 {
+                match categorized_path[*i].category {
                     ConstraintCategory::OpaqueType
                     | ConstraintCategory::Boring
                     | ConstraintCategory::BoringNoLocation
@@ -2103,37 +2125,42 @@ fn check_member_constraints(
 
         if let Some(i) = best_choice {
             if let Some(next) = categorized_path.get(i + 1) {
-                if matches!(categorized_path[i].0, ConstraintCategory::Return(_))
-                    && next.0 == ConstraintCategory::OpaqueType
+                if matches!(categorized_path[i].category, ConstraintCategory::Return(_))
+                    && next.category == ConstraintCategory::OpaqueType
                 {
                     // The return expression is being influenced by the return type being
                     // impl Trait, point at the return type and not the return expr.
-                    return *next;
+                    return next.clone();
                 }
             }
 
-            if categorized_path[i].0 == ConstraintCategory::Return(ReturnConstraint::Normal) {
+            if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal)
+            {
                 let field = categorized_path.iter().find_map(|p| {
-                    if let ConstraintCategory::ClosureUpvar(f) = p.0 { Some(f) } else { None }
+                    if let ConstraintCategory::ClosureUpvar(f) = p.category {
+                        Some(f)
+                    } else {
+                        None
+                    }
                 });
 
                 if let Some(field) = field {
-                    categorized_path[i].0 =
+                    categorized_path[i].category =
                         ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
                 }
             }
 
-            return categorized_path[i];
+            return categorized_path[i].clone();
         }
 
         // If that search fails, that is.. unusual. Maybe everything
         // is in the same SCC or something. In that case, find what
         // appears to be the most interesting point to report to the
         // user via an even more ad-hoc guess.
-        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
+        categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
         debug!("`: sorted_path={:#?}", categorized_path);
 
-        *categorized_path.first().unwrap()
+        categorized_path.remove(0)
     }
 }
 
@@ -2228,3 +2255,11 @@ fn apply_requirements(
             .collect()
     }
 }
+
+#[derive(Clone, Debug)]
+pub struct BlameConstraint<'tcx> {
+    pub category: ConstraintCategory,
+    pub from_closure: bool,
+    pub span: Span,
+    pub variance_info: ty::VarianceDiagInfo<'tcx>,
+}
index 8513e5e531bd7e88b7cfe607fc6c43800a908a2c..eb11b9371433d145a24cac55f8738877d39ecb25 100644 (file)
@@ -143,6 +143,7 @@ fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
             category: self.category,
             sub,
             sup,
+            variance_info: ty::VarianceDiagInfo::default(),
         });
     }
 
index bddcd34ed3e47e97762477b4bcc1f625acdbb5fa..a34ae281b70dfdd547ed652226264299e0f37a1f 100644 (file)
@@ -107,7 +107,7 @@ fn compute_live_locals(
 fn regions_that_outlive_free_regions(
     num_region_vars: usize,
     universal_regions: &UniversalRegions<'tcx>,
-    constraint_set: &OutlivesConstraintSet,
+    constraint_set: &OutlivesConstraintSet<'tcx>,
 ) -> FxHashSet<RegionVid> {
     // Build a graph of the outlives constraints thus far. This is
     // a reverse graph, so for each constraint `R1: R2` we have an
index d27fcb2f26f19bce0f529f2b278523973baf0594..e294f128f2e142eb789e3a41051fc6aebbb97e91 100644 (file)
@@ -226,7 +226,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
         let location_table = cx.location_table;
         facts.outlives.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
-            |constraint: &OutlivesConstraint| {
+            |constraint: &OutlivesConstraint<'_>| {
                 if let Some(from_location) = constraint.locations.from_location() {
                     Either::Left(iter::once((
                         constraint.sup,
@@ -572,7 +572,7 @@ fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Locatio
 
         let locations = location.to_locations();
         for constraint in constraints.outlives().iter() {
-            let mut constraint = *constraint;
+            let mut constraint = constraint.clone();
             constraint.locations = locations;
             if let ConstraintCategory::Return(_)
             | ConstraintCategory::UseAsConst
@@ -862,7 +862,7 @@ struct BorrowCheckContext<'a, 'tcx> {
     /// hence it must report on their liveness constraints.
     crate liveness_constraints: LivenessValues<RegionVid>,
 
-    crate outlives_constraints: OutlivesConstraintSet,
+    crate outlives_constraints: OutlivesConstraintSet<'tcx>,
 
     crate member_constraints: MemberConstraintSet<'tcx, RegionVid>,
 
@@ -2535,6 +2535,7 @@ fn add_reborrow_constraint(
                                 sub: borrow_region.to_region_vid(),
                                 locations: location.to_locations(),
                                 category,
+                                variance_info: ty::VarianceDiagInfo::default(),
                             });
 
                             match mutbl {
index 249945f04b7b05748410f88697ca187fd6872bd2..f97252a117a6f018eec4cc881f37a39ceb94f727 100644 (file)
@@ -94,7 +94,12 @@ fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<
         )
     }
 
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         if let Some(borrowck_context) = &mut self.borrowck_context {
             let sub = borrowck_context.universal_regions.to_region_vid(sub);
             let sup = borrowck_context.universal_regions.to_region_vid(sup);
@@ -103,6 +108,7 @@ fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
                 sub,
                 locations: self.locations,
                 category: self.category,
+                variance_info: info,
             });
         }
     }
index 12a36976f1d4b2f93ba1ffb0b1428d60e492a5fc..1da17bddcb777c3b044f4160beb686b8fddf4172 100644 (file)
@@ -15,6 +15,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(exact_size_is_empty)]
+#![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(map_try_insert)]
index ac3420ad339500dd098497311e65ddb6885d28d9..4fbd27c89d9c8f6b7f0338f3d2020ad1c3db6f28 100644 (file)
@@ -729,13 +729,11 @@ fn visit_projection_elem(
                 let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind() {
                     if proj_base.is_empty() {
-                        if let (local, []) = (place_local, proj_base) {
-                            let decl = &self.body.local_decls[local];
-                            if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
-                                let span = decl.source_info.span;
-                                self.check_static(def_id, span);
-                                return;
-                            }
+                        let decl = &self.body.local_decls[place_local];
+                        if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
+                            let span = decl.source_info.span;
+                            self.check_static(def_id, span);
+                            return;
                         }
                     }
                     self.check_op(ops::RawPtrDeref);
index b5c8b4bebc360496349001822c0dc24c1bece0f2..ba10b54c5ae2e37fa579dc694bcfb35a79d50e1f 100644 (file)
@@ -47,7 +47,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // if we applied optimizations, we potentially have some cfg to cleanup to
         // make it easier for further passes
         if should_simplify {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
             simplify_locals(body, tcx);
         }
     }
index c41e71e09a4efc7d64186850460538b2b254d0cb..912505c65983edb8f06df2ef6fe0016035ef90db 100644 (file)
@@ -26,7 +26,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         if has_opts_to_apply {
             let mut opt_applier = OptApplier { tcx, duplicates };
             opt_applier.visit_body(body);
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
index 7934d4ba8499c5364e09b7e00eede429b6d299c3..07127042fa41e82b31ba7b35d7718b6e45480729 100644 (file)
@@ -164,7 +164,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // Since this optimization adds new basic blocks and invalidates others,
         // clean up the cfg to make it nicer for other passes
         if should_cleanup {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
index 003003a8abbeae90f8f736d89e8a3a504e271de8..3560b4b1e8645e77ed17488ac8ba954b9ea4c28c 100644 (file)
@@ -964,7 +964,7 @@ fn create_generator_drop_shim<'tcx>(
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the resume part of the function
-    simplify::remove_dead_blocks(&mut body);
+    simplify::remove_dead_blocks(tcx, &mut body);
 
     dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(()));
 
@@ -1137,7 +1137,7 @@ fn create_generator_resume_function<'tcx>(
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the drop part of the function
-    simplify::remove_dead_blocks(body);
+    simplify::remove_dead_blocks(tcx, body);
 
     dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(()));
 }
index b6f80763bc8c4c2b94b445b999a0d1bb85c2f3bb..f1c95a84ade85a04800a9af36440ba28429fbe6d 100644 (file)
@@ -57,7 +57,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         if inline(tcx, body) {
             debug!("running simplify cfg on {:?}", body.source);
             CfgSimplifier::new(body).simplify();
-            remove_dead_blocks(body);
+            remove_dead_blocks(tcx, body);
         }
     }
 }
index f7a9835353e5cff77c14c762641f2bf99103e088..21b208a08c2dca13cad206c4c28bf986187f3e43 100644 (file)
@@ -167,7 +167,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         if should_cleanup {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
index 4aaa0baa9f46a26fb640f59b73e5f322eb84c6db..cd2db180552868c681f5bf862da1b988b43f9375 100644 (file)
@@ -38,6 +38,6 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             }
         }
 
-        simplify::remove_dead_blocks(body)
+        simplify::remove_dead_blocks(tcx, body)
     }
 }
index 5144d48750de70d7febebd7a0c6dcc013c157781..02e45021a0aaf343fe3f73173934dbbead3e9f0d 100644 (file)
@@ -36,7 +36,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // if we applied optimizations, we potentially have some cfg to cleanup to
         // make it easier for further passes
         if should_simplify {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
index a0f225e6de6014633decdd281cbfa921106ce864..40b1a8a2da9fa80b45ebbb1cd41764564ed9a32d 100644 (file)
@@ -16,32 +16,29 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for block in basic_blocks.iter_mut() {
             for statement in block.statements.iter_mut() {
-                match statement.kind {
-                    StatementKind::Assign(box (place, _)) => {
-                        let place_ty = place.ty(local_decls, tcx).ty;
-                        if !maybe_zst(place_ty) {
-                            continue;
-                        }
-                        let layout = match tcx.layout_of(param_env.and(place_ty)) {
-                            Ok(layout) => layout,
-                            Err(_) => continue,
-                        };
-                        if !layout.is_zst() {
-                            continue;
-                        }
-                        if involves_a_union(place, local_decls, tcx) {
-                            continue;
-                        }
-                        if tcx.consider_optimizing(|| {
-                            format!(
-                                "RemoveZsts - Place: {:?} SourceInfo: {:?}",
-                                place, statement.source_info
-                            )
-                        }) {
-                            statement.make_nop();
-                        }
+                if let StatementKind::Assign(box (place, _)) = statement.kind {
+                    let place_ty = place.ty(local_decls, tcx).ty;
+                    if !maybe_zst(place_ty) {
+                        continue;
+                    }
+                    let layout = match tcx.layout_of(param_env.and(place_ty)) {
+                        Ok(layout) => layout,
+                        Err(_) => continue,
+                    };
+                    if !layout.is_zst() {
+                        continue;
+                    }
+                    if involves_a_union(place, local_decls, tcx) {
+                        continue;
+                    }
+                    if tcx.consider_optimizing(|| {
+                        format!(
+                            "RemoveZsts - Place: {:?} SourceInfo: {:?}",
+                            place, statement.source_info
+                        )
+                    }) {
+                        statement.make_nop();
                     }
-                    _ => {}
                 }
             }
         }
index 65e2d096b209462dd496320f589244ea13d12241..7aebca77e6f2090562816b78a0ab8ee2c1ea4c91 100644 (file)
@@ -29,6 +29,7 @@
 
 use crate::transform::MirPass;
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
@@ -46,9 +47,9 @@ pub fn new(label: &str) -> Self {
     }
 }
 
-pub fn simplify_cfg(body: &mut Body<'_>) {
+pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
     CfgSimplifier::new(body).simplify();
-    remove_dead_blocks(body);
+    remove_dead_blocks(tcx, body);
 
     // FIXME: Should probably be moved into some kind of pass manager
     body.basic_blocks_mut().raw.shrink_to_fit();
@@ -59,9 +60,9 @@ fn name(&self) -> Cow<'_, str> {
         Cow::Borrowed(&self.label)
     }
 
-    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body.source);
-        simplify_cfg(body);
+        simplify_cfg(tcx, body);
     }
 }
 
@@ -286,7 +287,7 @@ fn strip_nops(&mut self) {
     }
 }
 
-pub fn remove_dead_blocks(body: &mut Body<'_>) {
+pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
     let reachable = traversal::reachable_as_bitset(body);
     let num_blocks = body.basic_blocks().len();
     if num_blocks == reachable.count() {
@@ -306,6 +307,11 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
         }
         used_blocks += 1;
     }
+
+    if tcx.sess.instrument_coverage() {
+        save_unreachable_coverage(basic_blocks, used_blocks);
+    }
+
     basic_blocks.raw.truncate(used_blocks);
 
     for block in basic_blocks {
@@ -315,6 +321,75 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
     }
 }
 
+/// Some MIR transforms can determine at compile time that a sequences of
+/// statements will never be executed, so they can be dropped from the MIR.
+/// For example, an `if` or `else` block that is guaranteed to never be executed
+/// because its condition can be evaluated at compile time, such as by const
+/// evaluation: `if false { ... }`.
+///
+/// Those statements are bypassed by redirecting paths in the CFG around the
+/// `dead blocks`; but with `-Z instrument-coverage`, the dead blocks usually
+/// include `Coverage` statements representing the Rust source code regions to
+/// be counted at runtime. Without these `Coverage` statements, the regions are
+/// lost, and the Rust source code will show no coverage information.
+///
+/// What we want to show in a coverage report is the dead code with coverage
+/// counts of `0`. To do this, we need to save the code regions, by injecting
+/// `Unreachable` coverage statements. These are non-executable statements whose
+/// code regions are still recorded in the coverage map, representing regions
+/// with `0` executions.
+fn save_unreachable_coverage(
+    basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
+    first_dead_block: usize,
+) {
+    let has_live_counters = basic_blocks.raw[0..first_dead_block].iter().any(|live_block| {
+        live_block.statements.iter().any(|statement| {
+            if let StatementKind::Coverage(coverage) = &statement.kind {
+                matches!(coverage.kind, CoverageKind::Counter { .. })
+            } else {
+                false
+            }
+        })
+    });
+    if !has_live_counters {
+        // If there are no live `Counter` `Coverage` statements anymore, don't
+        // move dead coverage to the `START_BLOCK`. Just allow the dead
+        // `Coverage` statements to be dropped with the dead blocks.
+        //
+        // The `generator::StateTransform` MIR pass can create atypical
+        // conditions, where all live `Counter`s are dropped from the MIR.
+        //
+        // At least one Counter per function is required by LLVM (and necessary,
+        // to add the `function_hash` to the counter's call to the LLVM
+        // intrinsic `instrprof.increment()`).
+        return;
+    }
+
+    // Retain coverage info for dead blocks, so coverage reports will still
+    // report `0` executions for the uncovered code regions.
+    let mut dropped_coverage = Vec::new();
+    for dead_block in basic_blocks.raw[first_dead_block..].iter() {
+        for statement in dead_block.statements.iter() {
+            if let StatementKind::Coverage(coverage) = &statement.kind {
+                if let Some(code_region) = &coverage.code_region {
+                    dropped_coverage.push((statement.source_info, code_region.clone()));
+                }
+            }
+        }
+    }
+
+    let start_block = &mut basic_blocks[START_BLOCK];
+    for (source_info, code_region) in dropped_coverage {
+        start_block.statements.push(Statement {
+            source_info,
+            kind: StatementKind::Coverage(box Coverage {
+                kind: CoverageKind::Unreachable,
+                code_region: Some(code_region),
+            }),
+        })
+    }
+}
+
 pub struct SimplifyLocals;
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
index 89fddc95c98f7802cfdc9f8b555c5300e2588ccf..dd2ec39c066ab31844b9b031ed34428375290fb0 100644 (file)
@@ -558,7 +558,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
         if did_remove_blocks {
             // We have dead blocks now, so remove those.
-            simplify::remove_dead_blocks(body);
+            simplify::remove_dead_blocks(tcx, body);
         }
     }
 }
index 658c6b6e9db20086855c89e94b73799352195b87..e7fb6b4f6b4ade858cf5210480c5a4aece8647d9 100644 (file)
@@ -60,7 +60,7 @@ fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         }
 
         if replaced {
-            simplify::remove_dead_blocks(body);
+            simplify::remove_dead_blocks(tcx, body);
         }
     }
 }
index 35759a396e87cb3786422ed3446e67af25b23975..e1d0b84f4193f92a0ff002af50b24234b33b32a2 100644 (file)
@@ -342,16 +342,10 @@ pub fn collect_tokens_trailing_token<R: AstLike>(
 
         // If we support tokens at all
         if let Some(target_tokens) = ret.tokens_mut() {
-            if let Some(target_tokens) = target_tokens {
-                assert!(
-                    !self.capture_cfg,
-                    "Encountered existing tokens with capture_cfg set: {:?}",
-                    target_tokens
-                );
-            } else {
+            if target_tokens.is_none() {
                 // Store se our newly captured tokens into the AST node
                 *target_tokens = Some(tokens.clone());
-            };
+            }
         }
 
         let final_attrs = ret.attrs();
index 56c97b5947682c3f9d868cfda7a6daa17937c4e0..a764cf6bdb04e65dd821c0c962c5e6c4b543de16 100644 (file)
@@ -94,17 +94,7 @@ pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
 
     /// Parses an expression, forcing tokens to be collected
     pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
-        // If we have outer attributes, then the call to `collect_tokens_trailing_token`
-        // will be made for us.
-        if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) {
-            self.parse_expr()
-        } else {
-            // If we don't have outer attributes, then we need to ensure
-            // that collection happens by using `collect_tokens_no_attrs`.
-            // Expression don't support custom inner attributes, so `parse_expr`
-            // will never try to collect tokens if we don't have outer attributes.
-            self.collect_tokens_no_attrs(|this| this.parse_expr())
-        }
+        self.collect_tokens_no_attrs(|this| this.parse_expr())
     }
 
     pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
index 4c2bc6ebf3143071d896df2480049798f4636d4f..cd9f84db5e55958005bcb3284c00c4fee3f63e89 100644 (file)
@@ -63,6 +63,7 @@ enum BlockMode {
 
 /// Whether or not we should force collection of tokens for an AST node,
 /// regardless of whether or not it has attributes
+#[derive(Clone, Copy, PartialEq)]
 pub enum ForceCollect {
     Yes,
     No,
index 0c43e304f1ee278e693ac98db56e4f58e149ece7..30a6b61407f69a06cca09094e715dc028bed125d 100644 (file)
@@ -1,5 +1,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast::AstLike;
 use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
@@ -102,7 +103,7 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
-        Ok(match kind {
+        let mut nt = match kind {
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
                 Some(item) => token::NtItem(item),
                 None => {
@@ -169,7 +170,19 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
                     return Err(self.struct_span_err(self.token.span, msg));
                 }
             }
-        })
+        };
+
+        // If tokens are supported at all, they should be collected.
+        if matches!(nt.tokens_mut(), Some(None)) {
+            panic!(
+                "Missing tokens for nt {:?} at {:?}: {:?}",
+                nt,
+                nt.span(),
+                pprust::nonterminal_to_string(&nt)
+            );
+        }
+
+        Ok(nt)
     }
 }
 
index 9cc600d9ede02fb3d9aad3ce583479c067bbde46..953c6915068afd49409201f91b0ad485cb94c953 100644 (file)
@@ -352,49 +352,59 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
         debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
         match self.parse_angle_args() {
             Ok(args) => Ok(args),
-            Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
-                // Cancel error from being unable to find `>`. We know the error
-                // must have been this due to a non-zero unmatched angle bracket
-                // count.
-                e.cancel();
-
+            Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
                 // Swap `self` with our backup of the parser state before attempting to parse
                 // generic arguments.
                 let snapshot = mem::replace(self, snapshot.unwrap());
 
-                debug!(
-                    "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
-                     snapshot.count={:?}",
-                    snapshot.unmatched_angle_bracket_count,
-                );
-
                 // Eat the unmatched angle brackets.
-                for _ in 0..snapshot.unmatched_angle_bracket_count {
-                    self.eat_lt();
-                }
-
-                // Make a span over ${unmatched angle bracket count} characters.
-                let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
-                self.struct_span_err(
-                    span,
-                    &format!(
-                        "unmatched angle bracket{}",
-                        pluralize!(snapshot.unmatched_angle_bracket_count)
-                    ),
-                )
-                .span_suggestion(
-                    span,
-                    &format!(
-                        "remove extra angle bracket{}",
-                        pluralize!(snapshot.unmatched_angle_bracket_count)
-                    ),
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+                let all_angle_brackets = (0..snapshot.unmatched_angle_bracket_count)
+                    .fold(true, |a, _| a && self.eat_lt());
+
+                if !all_angle_brackets {
+                    // If there are other tokens in between the extraneous `<`s, we cannot simply
+                    // suggest to remove them. This check also prevents us from accidentally ending
+                    // up in the middle of a multibyte character (issue #84104).
+                    let _ = mem::replace(self, snapshot);
+                    Err(e)
+                } else {
+                    // Cancel error from being unable to find `>`. We know the error
+                    // must have been this due to a non-zero unmatched angle bracket
+                    // count.
+                    e.cancel();
+
+                    debug!(
+                        "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
+                         snapshot.count={:?}",
+                        snapshot.unmatched_angle_bracket_count,
+                    );
+
+                    // Make a span over ${unmatched angle bracket count} characters.
+                    // This is safe because `all_angle_brackets` ensures that there are only `<`s,
+                    // i.e. no multibyte characters, in this range.
+                    let span =
+                        lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
+                    self.struct_span_err(
+                        span,
+                        &format!(
+                            "unmatched angle bracket{}",
+                            pluralize!(snapshot.unmatched_angle_bracket_count)
+                        ),
+                    )
+                    .span_suggestion(
+                        span,
+                        &format!(
+                            "remove extra angle bracket{}",
+                            pluralize!(snapshot.unmatched_angle_bracket_count)
+                        ),
+                        String::new(),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
 
-                // Try again without unmatched angle bracket characters.
-                self.parse_angle_args()
+                    // Try again without unmatched angle bracket characters.
+                    self.parse_angle_args()
+                }
             }
             Err(e) => Err(e),
         }
index b40eed8c5d118752a4b075b59fff080e3bced2ce..4f0dcfeb5dae06b2f4a858b427fed86ec5441cf5 100644 (file)
@@ -73,7 +73,11 @@ pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
             // that starts like a path (1 token), but it fact not a path.
             // Also, we avoid stealing syntax from `parse_item_`.
-            self.parse_stmt_path_start(lo, attrs, force_collect)?
+            if force_collect == ForceCollect::Yes {
+                self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))
+            } else {
+                self.parse_stmt_path_start(lo, attrs)
+            }?
         } else if let Some(item) =
             self.parse_item_common(attrs.clone(), false, true, |_| true, force_collect)?
         {
@@ -85,7 +89,13 @@ pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<
             self.mk_stmt(lo, StmtKind::Empty)
         } else if self.token != token::CloseDelim(token::Brace) {
             // Remainder are line-expr stmts.
-            let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))?;
+            let e = if force_collect == ForceCollect::Yes {
+                self.collect_tokens_no_attrs(|this| {
+                    this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
+                })
+            } else {
+                self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
+            }?;
             self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
         } else {
             self.error_outer_attrs(&attrs.take_for_recovery());
@@ -93,13 +103,8 @@ pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<
         }))
     }
 
-    fn parse_stmt_path_start(
-        &mut self,
-        lo: Span,
-        attrs: AttrWrapper,
-        force_collect: ForceCollect,
-    ) -> PResult<'a, Stmt> {
-        let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
+    fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
+        let stmt = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let path = this.parse_path(PathStyle::Expr)?;
 
             if this.eat(&token::Not) {
index 89cf2d7876e1d9d523935bb3d9505f2425e7bc5e..de5a5632600e4ee39a1f6c0dd90d01f92fb5ed46 100644 (file)
@@ -334,7 +334,6 @@ fn parse_remaining_bounds(
         mut bounds: GenericBounds,
         plus: bool,
     ) -> PResult<'a, TyKind> {
-        assert_ne!(self.token, token::Question);
         if plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
             bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
index bf574bbfbb5aefc9f23c9f7f43f800ef90d09281..b18ef302962378b1819e909dfd9ca6841535dd24 100644 (file)
@@ -577,7 +577,7 @@ fn check_doc_inline(
         target: Target,
         specified_inline: &mut Option<(bool, Span)>,
     ) -> bool {
-        if target == Target::Use {
+        if target == Target::Use || target == Target::ExternCrate {
             let do_inline = meta.name_or_empty() == sym::inline;
             if let Some((prev_inline, prev_span)) = *specified_inline {
                 if do_inline != prev_inline {
@@ -705,7 +705,7 @@ fn check_doc_attrs(
         let mut is_valid = true;
 
         if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) {
-            for meta in list {
+            for meta in &list {
                 if let Some(i_meta) = meta.meta_item() {
                     match i_meta.name_or_empty() {
                         sym::alias
@@ -757,7 +757,6 @@ fn check_doc_attrs(
                         | sym::html_no_source
                         | sym::html_playground_url
                         | sym::html_root_url
-                        | sym::include
                         | sym::inline
                         | sym::issue_tracker_base_url
                         | sym::keyword
@@ -792,6 +791,30 @@ fn check_doc_attrs(
                                         );
                                         diag.note("`doc(spotlight)` is now a no-op");
                                     }
+                                    if i_meta.has_name(sym::include) {
+                                        if let Some(value) = i_meta.value_str() {
+                                            // if there are multiple attributes, the suggestion would suggest deleting all of them, which is incorrect
+                                            let applicability = if list.len() == 1 {
+                                                Applicability::MachineApplicable
+                                            } else {
+                                                Applicability::MaybeIncorrect
+                                            };
+                                            let inner = if attr.style == AttrStyle::Inner {
+                                                "!"
+                                            } else {
+                                                ""
+                                            };
+                                            diag.span_suggestion(
+                                                attr.meta().unwrap().span,
+                                                "use `doc = include_str!` instead",
+                                                format!(
+                                                    "#{}[doc = include_str!(\"{}\")]",
+                                                    inner, value
+                                                ),
+                                                applicability,
+                                            );
+                                        }
+                                    }
                                     diag.emit();
                                 },
                             );
index 29a0a3c48e53f9e0683fb9b49688468e93f00e60..f41e0e0370680f4b3cafb8eb8c0c5ef2acadd2ee 100644 (file)
@@ -828,11 +828,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
     fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
         if let Some(def_id) = path.res.opt_def_id() {
-            let method_span = match path.segments {
-                [.., _, last] => Some(last.ident.span),
-                _ => None,
-            };
-            self.tcx.check_stability(def_id, Some(id), path.span, method_span)
+            self.tcx.check_stability(def_id, Some(id), path.span, None)
         }
         intravisit::walk_path(self, path)
     }
index 6a84a28be66563b07baf348fd89a3a0a563dd40a..73c00fc49ba39c7794becf632ae0a8d1a9daa973 100644 (file)
@@ -122,21 +122,21 @@ fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String>
         let mut edge_list_data = Vec::with_capacity(edge_count);
 
         for _index in 0..node_count {
-            d.read_struct("NodeInfo", 3, |d| {
-                let dep_node: DepNode<K> = d.read_struct_field("node", 0, Decodable::decode)?;
+            d.read_struct(|d| {
+                let dep_node: DepNode<K> = d.read_struct_field("node", Decodable::decode)?;
                 let _i: SerializedDepNodeIndex = nodes.push(dep_node);
                 debug_assert_eq!(_i.index(), _index);
 
                 let fingerprint: Fingerprint =
-                    d.read_struct_field("fingerprint", 1, Decodable::decode)?;
+                    d.read_struct_field("fingerprint", Decodable::decode)?;
                 let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint);
                 debug_assert_eq!(_i.index(), _index);
 
-                d.read_struct_field("edges", 2, |d| {
+                d.read_struct_field("edges", |d| {
                     d.read_seq(|d, len| {
                         let start = edge_list_data.len().try_into().unwrap();
-                        for e in 0..len {
-                            let edge = d.read_seq_elt(e, Decodable::decode)?;
+                        for _ in 0..len {
+                            let edge = d.read_seq_elt(Decodable::decode)?;
                             edge_list_data.push(edge);
                         }
                         let end = edge_list_data.len().try_into().unwrap();
index 41935e7d6dfd59d0b434592724a0c8262c77b94a..fd9b897111a9885a9b031b0697d1aceef3e661e2 100644 (file)
@@ -1222,7 +1222,7 @@ pub fn new(
         let mut module_map = FxHashMap::default();
         module_map.insert(root_local_def_id, graph_root);
 
-        let definitions = Definitions::new(session.local_stable_crate_id());
+        let definitions = Definitions::new(crate_name, session.local_crate_disambiguator());
         let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
index 842f7f9deee38ed3e887a922be597154188857e6..54b6a1215858153f3924214e466085eff3817aae 100644 (file)
@@ -142,7 +142,12 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &hir::Crate<'_>) {
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
                 name: name.into(),
-                disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
+                disambiguator: self
+                    .tcx
+                    .sess
+                    .local_crate_disambiguator()
+                    .to_fingerprint()
+                    .as_value(),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
index bdffdd5311e3cee2f038ed199345ed855a7a4f01..297383bfed1faf517f919eb4a5fde32485eda55a 100644 (file)
@@ -127,10 +127,7 @@ pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
                 num: n.as_u32(),
                 id: GlobalCrateId {
                     name: self.tcx.crate_name(n).to_string(),
-                    disambiguator: (
-                        self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
-                        0,
-                    ),
+                    disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
                 },
             });
         }
@@ -826,20 +823,6 @@ fn docs_for_attrs(&self, attrs: &[ast::Attribute]) -> String {
                 // FIXME: Should save-analysis beautify doc strings itself or leave it to users?
                 result.push_str(&beautify_doc_string(val).as_str());
                 result.push('\n');
-            } else if self.tcx.sess.check_name(attr, sym::doc) {
-                if let Some(meta_list) = attr.meta_item_list() {
-                    meta_list
-                        .into_iter()
-                        .filter(|it| it.has_name(sym::include))
-                        .filter_map(|it| it.meta_item_list().map(|l| l.to_owned()))
-                        .flat_map(|it| it)
-                        .filter(|meta| meta.has_name(sym::contents))
-                        .filter_map(|meta| meta.value_str())
-                        .for_each(|val| {
-                            result.push_str(&val.as_str());
-                            result.push('\n');
-                        });
-                }
             }
         }
 
index ae6d27e037b2dbda7a1f66ffa7712a4c0de77381..80a7f650188803f0e9a3a99ffdee40c5648b3604 100644 (file)
@@ -21,8 +21,8 @@ fn decode(d: &mut D) -> Result<SmallVec<A>, D::Error> {
         d.read_seq(|d, len| {
             let mut vec = SmallVec::with_capacity(len);
             // FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
-            for i in 0..len {
-                vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                vec.push(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(vec)
         })
@@ -44,8 +44,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for LinkedList<T> {
     fn decode(d: &mut D) -> Result<LinkedList<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut list = LinkedList::new();
-            for i in 0..len {
-                list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                list.push_back(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(list)
         })
@@ -67,8 +67,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for VecDeque<T> {
     fn decode(d: &mut D) -> Result<VecDeque<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut deque: VecDeque<T> = VecDeque::with_capacity(len);
-            for i in 0..len {
-                deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                deque.push_back(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(deque)
         })
@@ -84,7 +84,7 @@ fn encode(&self, e: &mut S) -> Result<(), S::Error> {
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -99,9 +99,9 @@ impl<D: Decoder, K, V> Decodable<D> for BTreeMap<K, V>
     fn decode(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
         d.read_map(|d, len| {
             let mut map = BTreeMap::new();
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -130,8 +130,8 @@ impl<D: Decoder, T> Decodable<D> for BTreeSet<T>
     fn decode(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut set = BTreeSet::new();
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
@@ -148,7 +148,7 @@ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -165,9 +165,9 @@ fn decode(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
         d.read_map(|d, len| {
             let state = Default::default();
             let mut map = HashMap::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -209,8 +209,8 @@ fn decode(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
         d.read_seq(|d, len| {
             let state = Default::default();
             let mut set = HashSet::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
@@ -227,7 +227,7 @@ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -244,9 +244,9 @@ fn decode(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
         d.read_map(|d, len| {
             let state = Default::default();
             let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -278,8 +278,8 @@ fn decode(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
         d.read_seq(|d, len| {
             let state = Default::default();
             let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
index 78a102c5c23304ae043b05f5cc58b1a5bef82def..b79adb6f7bcd92a5d2bb4287c018c3bfa84e2638 100644 (file)
@@ -560,7 +560,7 @@ fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
         Ok(())
     }
 
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
+    fn emit_enum<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -589,46 +589,20 @@ fn emit_enum_variant<F>(&mut self, name: &str, _id: usize, cnt: usize, f: F) ->
         }
     }
 
-    fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+    fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             write!(self.writer, ",")?;
         }
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        name: &str,
-        id: usize,
-        cnt: usize,
-        f: F,
-    ) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, _: usize, f: F) -> EncodeResult
+    fn emit_struct<F>(&mut self, _: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -641,14 +615,14 @@ fn emit_struct<F>(&mut self, _: &str, _: usize, f: F) -> EncodeResult
         Ok(())
     }
 
-    fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult
+    fn emit_struct_field<F>(&mut self, name: &str, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             write!(self.writer, ",")?;
         }
         escape_str(self.writer, name)?;
@@ -675,25 +649,6 @@ fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq_elt(idx, f)
-    }
-
     fn emit_option<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
@@ -774,7 +729,7 @@ fn emit_map_elt_key<F>(&mut self, idx: usize, f: F) -> EncodeResult
         Ok(())
     }
 
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+    fn emit_map_elt_val<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -892,7 +847,7 @@ fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
         Ok(())
     }
 
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
+    fn emit_enum<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
@@ -930,54 +885,28 @@ fn emit_enum_variant<F>(&mut self, name: &str, _id: usize, cnt: usize, f: F) ->
         }
     }
 
-    fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+    fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             writeln!(self.writer, ",")?;
         }
         spaces(self.writer, self.curr_indent)?;
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        name: &str,
-        id: usize,
-        cnt: usize,
-        f: F,
-    ) -> EncodeResult
+    fn emit_struct<F>(&mut self, no_fields: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        if len == 0 {
+        if no_fields {
             write!(self.writer, "{{}}")?;
         } else {
             write!(self.writer, "{{")?;
@@ -991,14 +920,14 @@ fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
         Ok(())
     }
 
-    fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult
+    fn emit_struct_field<F>(&mut self, name: &str, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx == 0 {
+        if first {
             writeln!(self.writer)?;
         } else {
             writeln!(self.writer, ",")?;
@@ -1028,25 +957,6 @@ fn emit_tuple_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq_elt(idx, f)
-    }
-
     fn emit_option<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
@@ -1149,7 +1059,7 @@ fn emit_map_elt_key<F>(&mut self, idx: usize, f: F) -> EncodeResult
         Ok(())
     }
 
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+    fn emit_map_elt_val<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
@@ -2373,7 +2283,7 @@ fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), Self::Error> {
         Ok(())
     }
 
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T>
+    fn read_enum<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2410,33 +2320,14 @@ fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) -> DecodeResult<
         f(self, idx)
     }
 
-    fn read_enum_variant_arg<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_enum_variant_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
         f(self)
     }
 
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T>
-    where
-        F: FnMut(&mut Decoder, usize) -> DecodeResult<T>,
-    {
-        self.read_enum_variant(names, f)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(
-        &mut self,
-        _name: &str,
-        idx: usize,
-        f: F,
-    ) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_enum_variant_arg(idx, f)
-    }
-
-    fn read_struct<T, F>(&mut self, _name: &str, _len: usize, f: F) -> DecodeResult<T>
+    fn read_struct<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2445,7 +2336,7 @@ fn read_struct<T, F>(&mut self, _name: &str, _len: usize, f: F) -> DecodeResult<
         Ok(value)
     }
 
-    fn read_struct_field<T, F>(&mut self, name: &str, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_struct_field<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2483,25 +2374,11 @@ fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) -> DecodeResult<T>
         })
     }
 
-    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_seq_elt(idx, f)
-    }
-
-    fn read_tuple_struct<T, F>(&mut self, _name: &str, len: usize, f: F) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+    fn read_tuple_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
-        self.read_tuple_arg(idx, f)
+        self.read_seq_elt(f)
     }
 
     fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T>
@@ -2527,7 +2404,7 @@ fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T>
         f(self, len)
     }
 
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_seq_elt<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2547,14 +2424,14 @@ fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
         f(self, len)
     }
 
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_map_elt_key<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
         f(self)
     }
 
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_map_elt_val<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
index d3e5f306970c519e0ec58f92795516a19374d00c..bb3c537ef1949c024637efa50612078c794854d0 100644 (file)
@@ -37,7 +37,7 @@ pub trait Encoder {
 
     // Compound types:
     #[inline]
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> Result<(), Self::Error>
+    fn emit_enum<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -59,40 +59,15 @@ fn emit_enum_variant<F>(
     }
 
     #[inline]
-    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error>
+    fn emit_enum_variant_arg<F>(&mut self, _first: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        v_name: &str,
-        v_id: usize,
-        len: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_enum_variant(v_name, v_id, len, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(
-        &mut self,
-        _f_name: &str,
-        f_idx: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_enum_variant_arg(f_idx, f)
-    }
-
     #[inline]
-    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error>
+    fn emit_struct<F>(&mut self, _no_fields: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -100,12 +75,7 @@ fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self:
     }
 
     #[inline]
-    fn emit_struct_field<F>(
-        &mut self,
-        _f_name: &str,
-        _f_idx: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
+    fn emit_struct_field<F>(&mut self, _f_name: &str, _first: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -128,26 +98,12 @@ fn emit_tuple_arg<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
         f(self)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_tuple(len, f)
-    }
-
-    fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_tuple_arg(f_idx, f)
-    }
-
     // Specialized types:
     fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
-        self.emit_enum("Option", f)
+        self.emit_enum(f)
     }
 
     #[inline]
@@ -195,7 +151,7 @@ fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
     }
 
     #[inline]
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+    fn emit_map_elt_val<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -229,7 +185,7 @@ pub trait Decoder {
 
     // Compound types:
     #[inline]
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
+    fn read_enum<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -246,34 +202,15 @@ fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F) -> Result<T, Se
     }
 
     #[inline]
-    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_enum_variant_arg<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
         f(self)
     }
 
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, Self::Error>
-    where
-        F: FnMut(&mut Self, usize) -> Result<T, Self::Error>,
-    {
-        self.read_enum_variant(names, f)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(
-        &mut self,
-        _f_name: &str,
-        f_idx: usize,
-        f: F,
-    ) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_enum_variant_arg(f_idx, f)
-    }
-
     #[inline]
-    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) -> Result<T, Self::Error>
+    fn read_struct<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -281,12 +218,7 @@ fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) -> Result<T, S
     }
 
     #[inline]
-    fn read_struct_field<T, F>(
-        &mut self,
-        _f_name: &str,
-        _f_idx: usize,
-        f: F,
-    ) -> Result<T, Self::Error>
+    fn read_struct_field<T, F>(&mut self, _f_name: &str, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -302,33 +234,19 @@ fn read_tuple<T, F>(&mut self, _len: usize, f: F) -> Result<T, Self::Error>
     }
 
     #[inline]
-    fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_tuple_arg<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
         f(self)
     }
 
-    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_tuple_arg(a_idx, f)
-    }
-
     // Specialized types:
     fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error>
     where
         F: FnMut(&mut Self, bool) -> Result<T, Self::Error>,
     {
-        self.read_enum("Option", move |this| {
+        self.read_enum(move |this| {
             this.read_enum_variant(&["None", "Some"], move |this, idx| match idx {
                 0 => f(this, false),
                 1 => f(this, true),
@@ -346,7 +264,7 @@ fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     }
 
     #[inline]
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_seq_elt<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -362,7 +280,7 @@ fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     }
 
     #[inline]
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_map_elt_key<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -370,7 +288,7 @@ fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error
     }
 
     #[inline]
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_map_elt_val<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -550,8 +468,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
     default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
-            for i in 0..len {
-                v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                v.push(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(v)
         })
@@ -571,7 +489,7 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
             assert!(len == N);
             let mut v = [0u8; N];
             for i in 0..len {
-                v[i] = d.read_seq_elt(i, |d| Decodable::decode(d))?;
+                v[i] = d.read_seq_elt(|d| Decodable::decode(d))?;
             }
             Ok(v)
         })
@@ -615,12 +533,12 @@ fn decode(d: &mut D) -> Result<Option<T>, D::Error> {
 
 impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_enum("Result", |s| match *self {
+        s.emit_enum(|s| match *self {
             Ok(ref v) => {
-                s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
+                s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(true, |s| v.encode(s)))
             }
             Err(ref v) => {
-                s.emit_enum_variant("Err", 1, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
+                s.emit_enum_variant("Err", 1, 1, |s| s.emit_enum_variant_arg(true, |s| v.encode(s)))
             }
         })
     }
@@ -628,10 +546,10 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
 
 impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> {
     fn decode(d: &mut D) -> Result<Result<T1, T2>, D::Error> {
-        d.read_enum("Result", |d| {
+        d.read_enum(|d| {
             d.read_enum_variant(&["Ok", "Err"], |d, disr| match disr {
-                0 => Ok(Ok(d.read_enum_variant_arg(0, |d| T1::decode(d))?)),
-                1 => Ok(Err(d.read_enum_variant_arg(0, |d| T2::decode(d))?)),
+                0 => Ok(Ok(d.read_enum_variant_arg(|d| T1::decode(d))?)),
+                1 => Ok(Err(d.read_enum_variant_arg(|d| T2::decode(d))?)),
                 _ => {
                     panic!(
                         "Encountered invalid discriminant while \
@@ -668,8 +586,7 @@ impl<D: Decoder, $($name: Decodable<D>),+> Decodable<D> for ($($name,)+) {
             fn decode(d: &mut D) -> Result<($($name,)+), D::Error> {
                 let len: usize = count!($($name)+);
                 d.read_tuple(len, |d| {
-                    let mut i = 0;
-                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> {
+                    let ret = ($(d.read_tuple_arg(|d| -> Result<$name, D::Error> {
                         Decodable::decode(d)
                     })?,)+);
                     Ok(ret)
index 52f8b536f4aad7074be615dd90d79c155bb5d30e..57522582683844a86a11f8eb4428b2131974facb 100644 (file)
@@ -677,6 +677,7 @@ fn default() -> Options {
             optimize: OptLevel::No,
             debuginfo: DebugInfo::None,
             lint_opts: Vec::new(),
+            force_warns: Vec::new(),
             lint_cap: None,
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
@@ -1092,6 +1093,13 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
              level",
             "LEVEL",
         ),
+        opt::multi_s(
+            "",
+            "force-warns",
+            "Specifiy lints that should warn even if \
+             they are allowed somewhere else",
+            "LINT",
+        ),
         opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
         opt::flag_s("V", "version", "Print version info and exit"),
         opt::flag_s("v", "verbose", "Use verbose output"),
@@ -1156,7 +1164,8 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
-) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
+    debugging_opts: &DebuggingOptions,
+) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>, Vec<String>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
@@ -1189,7 +1198,18 @@ pub fn get_cmd_lint_options(
         lint::Level::from_str(&cap)
             .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
     });
-    (lint_opts, describe_lints, lint_cap)
+
+    if !debugging_opts.unstable_options && matches.opt_present("force-warns") {
+        early_error(
+            error_format,
+            "the `-Z unstable-options` flag must also be passed to enable \
+            the flag `--force-warns=lints`",
+        );
+    }
+
+    let force_warns = matches.opt_strs("force-warns");
+
+    (lint_opts, describe_lints, lint_cap, force_warns)
 }
 
 /// Parses the `--color` flag.
@@ -1926,9 +1946,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
-    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
-
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
+    let (lint_opts, describe_lints, lint_cap, force_warns) =
+        get_cmd_lint_options(matches, error_format, &debugging_opts);
+
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
 
     if !debugging_opts.unstable_options && json_unused_externs {
@@ -2100,6 +2121,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         optimize: opt_level,
         debuginfo,
         lint_opts,
+        force_warns,
         lint_cap,
         describe_lints,
         output_types,
@@ -2427,30 +2449,32 @@ fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
         )+};
     }
 
+    impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
+        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+            match self {
+                Some(x) => {
+                    Hash::hash(&1, hasher);
+                    DepTrackingHash::hash(x, hasher, error_format);
+                }
+                None => Hash::hash(&0, hasher),
+            }
+        }
+    }
+
     impl_dep_tracking_hash_via_hash!(
         bool,
         usize,
+        NonZeroUsize,
         u64,
         String,
         PathBuf,
         lint::Level,
-        Option<bool>,
-        Option<u32>,
-        Option<usize>,
-        Option<NonZeroUsize>,
-        Option<String>,
-        Option<(String, u64)>,
-        Option<Vec<String>>,
-        Option<MergeFunctions>,
-        Option<RelocModel>,
-        Option<CodeModel>,
-        Option<TlsModel>,
-        Option<WasiExecModel>,
-        Option<PanicStrategy>,
-        Option<RelroLevel>,
-        Option<InstrumentCoverage>,
-        Option<lint::Level>,
-        Option<PathBuf>,
+        WasiExecModel,
+        u32,
+        RelocModel,
+        CodeModel,
+        TlsModel,
+        InstrumentCoverage,
         CrateType,
         MergeFunctions,
         PanicStrategy,
@@ -2468,10 +2492,10 @@ fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
         TargetTriple,
         Edition,
         LinkerPluginLto,
-        Option<SplitDebuginfo>,
+        SplitDebuginfo,
         SwitchWithOptPath,
-        Option<SymbolManglingVersion>,
-        Option<SourceFileHashAlgorithm>,
+        SymbolManglingVersion,
+        SourceFileHashAlgorithm,
         TrimmedDefPaths,
     );
 
index bb82cf4c45d6f5a21cc8aed220b43b41352dc726..58a53b3de6eb05d52cc8a1c5c740a99a7ba334ed 100644 (file)
@@ -130,6 +130,7 @@ pub struct Options {
         debuginfo: DebugInfo [TRACKED],
         lint_opts: Vec<(String, lint::Level)> [TRACKED],
         lint_cap: Option<lint::Level> [TRACKED],
+        force_warns: Vec<String> [TRACKED],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
index 47833dcda4f1f82a345fcef76c09f85713f8a3b4..86b8389a670e624e5b51d3b495ea91d87199ab74 100644 (file)
@@ -22,7 +22,7 @@
 use rustc_errors::registry::Registry;
 use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
 use rustc_lint_defs::FutureBreakage;
-pub use rustc_span::def_id::StableCrateId;
+pub use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
 use rustc_span::{edition::Edition, RealFileName};
 use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
@@ -133,12 +133,12 @@ pub struct Session {
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     crate_types: OnceCell<Vec<CrateType>>,
-    /// The `stable_crate_id` is constructed out of the crate name and all the
-    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
-    /// global identifier for the crate. It is used to allow multiple crates
-    /// with the same name to coexist. See the
+    /// The `crate_disambiguator` is constructed out of all the `-C metadata`
+    /// arguments passed to the compiler. Its value together with the crate-name
+    /// forms a unique global identifier for the crate. It is used to allow
+    /// multiple crates with the same name to coexist. See the
     /// `rustc_codegen_llvm::back::symbol_names` module for more information.
-    pub stable_crate_id: OnceCell<StableCrateId>,
+    pub crate_disambiguator: OnceCell<CrateDisambiguator>,
 
     features: OnceCell<rustc_feature::Features>,
 
@@ -335,8 +335,8 @@ fn emit_future_breakage(&self) {
         self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
     }
 
-    pub fn local_stable_crate_id(&self) -> StableCrateId {
-        self.stable_crate_id.get().copied().unwrap()
+    pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
+        self.crate_disambiguator.get().copied().unwrap()
     }
 
     pub fn crate_types(&self) -> &[CrateType] {
@@ -833,12 +833,12 @@ pub fn must_emit_unwind_tables(&self) -> bool {
 
     /// Returns the symbol name for the registrar function,
     /// given the crate `Svh` and the function `DefIndex`.
-    pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String {
-        format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64())
+    pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
+        format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
-    pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
-        format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
+    pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String {
+        format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
@@ -1397,7 +1397,7 @@ pub fn build_session(
         working_dir,
         one_time_diagnostics: Default::default(),
         crate_types: OnceCell::new(),
-        stable_crate_id: OnceCell::new(),
+        crate_disambiguator: OnceCell::new(),
         features: OnceCell::new(),
         lint_store: OnceCell::new(),
         recursion_limit: OnceCell::new(),
diff --git a/compiler/rustc_span/src/crate_disambiguator.rs b/compiler/rustc_span/src/crate_disambiguator.rs
new file mode 100644 (file)
index 0000000..bd7d851
--- /dev/null
@@ -0,0 +1,35 @@
+// This is here because `rustc_session` wants to refer to it,
+// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`.
+
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::{base_n, impl_stable_hash_via_hash};
+
+use std::fmt;
+
+/// Hash value constructed out of all the `-C metadata` arguments passed to the
+/// compiler. Together with the crate-name forms a unique global identifier for
+/// the crate.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
+pub struct CrateDisambiguator(Fingerprint);
+
+impl CrateDisambiguator {
+    pub fn to_fingerprint(self) -> Fingerprint {
+        self.0
+    }
+}
+
+impl fmt::Display for CrateDisambiguator {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+        let (a, b) = self.0.as_value();
+        let as_u128 = a as u128 | ((b as u128) << 64);
+        f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
+    }
+}
+
+impl From<Fingerprint> for CrateDisambiguator {
+    fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
+        CrateDisambiguator(fingerprint)
+    }
+}
+
+impl_stable_hash_via_hash!(CrateDisambiguator);
index b04a10d22a02f9540544151a8615be7621710d8f..6ee75376ad5bd08384cedfdfa548eca4a8c3b234 100644 (file)
@@ -1,3 +1,4 @@
+use crate::crate_disambiguator::CrateDisambiguator;
 use crate::HashStableContext;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -126,51 +127,26 @@ fn borrow(&self) -> &Fingerprint {
     }
 }
 
-/// A [StableCrateId] is a 64 bit hash of the crate name combined with all
-/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to
-/// [DefId]. It is stable across compilation sessions.
+/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It
+/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across
+/// compilation sessions.
 ///
 /// Since the ID is a hash value there is a (very small) chance that two crates
 /// end up with the same [StableCrateId]. The compiler will check for such
 /// collisions when loading crates and abort compilation in order to avoid
 /// further trouble.
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)]
 pub struct StableCrateId(u64);
 
 impl StableCrateId {
-    pub fn to_u64(self) -> u64 {
-        self.0
-    }
-
     /// Computes the stable ID for a crate with the given name and
-    /// `-Cmetadata` arguments.
-    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    /// disambiguator.
+    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId {
         use std::hash::Hash;
-        use std::hash::Hasher;
 
         let mut hasher = StableHasher::new();
         crate_name.hash(&mut hasher);
-
-        // We don't want the stable crate id to dependent on the order
-        // -C metadata arguments, so sort them:
-        metadata.sort();
-        // Every distinct -C metadata value is only incorporated once:
-        metadata.dedup();
-
-        hasher.write(b"metadata");
-        for s in &metadata {
-            // Also incorporate the length of a metadata string, so that we generate
-            // different values for `-Cmetadata=ab -Cmetadata=c` and
-            // `-Cmetadata=a -Cmetadata=bc`
-            hasher.write_usize(s.len());
-            hasher.write(s.as_bytes());
-        }
-
-        // Also incorporate crate type, so that we don't get symbol conflicts when
-        // linking against a library of the same name, if this is an executable.
-        hasher.write(if is_exe { b"exe" } else { b"lib" });
-
+        crate_disambiguator.hash(&mut hasher);
         StableCrateId(hasher.finish())
     }
 }
@@ -241,20 +217,20 @@ pub fn is_top_level_module(self) -> bool {
 
 impl<E: Encoder> Encodable<E> for DefId {
     default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct("DefId", 2, |s| {
-            s.emit_struct_field("krate", 0, |s| self.krate.encode(s))?;
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("krate", true, |s| self.krate.encode(s))?;
 
-            s.emit_struct_field("index", 1, |s| self.index.encode(s))
+            s.emit_struct_field("index", false, |s| self.index.encode(s))
         })
     }
 }
 
 impl<D: Decoder> Decodable<D> for DefId {
     default fn decode(d: &mut D) -> Result<DefId, D::Error> {
-        d.read_struct("DefId", 2, |d| {
+        d.read_struct(|d| {
             Ok(DefId {
-                krate: d.read_struct_field("krate", 0, Decodable::decode)?,
-                index: d.read_struct_field("index", 1, Decodable::decode)?,
+                krate: d.read_struct_field("krate", Decodable::decode)?,
+                index: d.read_struct_field("index", Decodable::decode)?,
             })
         })
     }
index 51a53918f079267a593de38ce134fc3fb74df677..9cf68cbd23e6da2f7200bf2c6c477e8f6bc252df 100644 (file)
@@ -45,6 +45,8 @@
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
+pub mod crate_disambiguator;
+
 pub mod symbol;
 pub use symbol::{sym, Symbol};
 
@@ -144,11 +146,12 @@ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
 // an added assert statement
 impl<S: Encoder> Encodable<S> for RealFileName {
     fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
-        encoder.emit_enum("RealFileName", |encoder| match *self {
+        encoder.emit_enum(|encoder| match *self {
             RealFileName::LocalPath(ref local_path) => {
                 encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| {
                     Ok({
-                        encoder.emit_enum_variant_arg(0, |encoder| local_path.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
                     })
                 })
             }
@@ -159,8 +162,10 @@ fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
                     // if they have been remapped by --remap-path-prefix
                     assert!(local_path.is_none());
                     Ok({
-                        encoder.emit_enum_variant_arg(0, |encoder| local_path.encode(encoder))?;
-                        encoder.emit_enum_variant_arg(1, |encoder| virtual_name.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
                     })
                 }),
         })
@@ -825,17 +830,17 @@ fn default() -> Self {
 impl<E: Encoder> Encodable<E> for Span {
     default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         let span = self.data();
-        s.emit_struct("Span", 2, |s| {
-            s.emit_struct_field("lo", 0, |s| span.lo.encode(s))?;
-            s.emit_struct_field("hi", 1, |s| span.hi.encode(s))
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("lo", true, |s| span.lo.encode(s))?;
+            s.emit_struct_field("hi", false, |s| span.hi.encode(s))
         })
     }
 }
 impl<D: Decoder> Decodable<D> for Span {
     default fn decode(s: &mut D) -> Result<Span, D::Error> {
-        s.read_struct("Span", 2, |d| {
-            let lo = d.read_struct_field("lo", 0, Decodable::decode)?;
-            let hi = d.read_struct_field("hi", 1, Decodable::decode)?;
+        s.read_struct(|d| {
+            let lo = d.read_struct_field("lo", Decodable::decode)?;
+            let hi = d.read_struct_field("hi", Decodable::decode)?;
 
             Ok(Span::new(lo, hi, SyntaxContext::root()))
         })
@@ -1232,12 +1237,12 @@ pub struct SourceFile {
 
 impl<S: Encoder> Encodable<S> for SourceFile {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("SourceFile", 8, |s| {
-            s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
-            s.emit_struct_field("src_hash", 2, |s| self.src_hash.encode(s))?;
-            s.emit_struct_field("start_pos", 3, |s| self.start_pos.encode(s))?;
-            s.emit_struct_field("end_pos", 4, |s| self.end_pos.encode(s))?;
-            s.emit_struct_field("lines", 5, |s| {
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("name", true, |s| self.name.encode(s))?;
+            s.emit_struct_field("src_hash", false, |s| self.src_hash.encode(s))?;
+            s.emit_struct_field("start_pos", false, |s| self.start_pos.encode(s))?;
+            s.emit_struct_field("end_pos", false, |s| self.end_pos.encode(s))?;
+            s.emit_struct_field("lines", false, |s| {
                 let lines = &self.lines[..];
                 // Store the length.
                 s.emit_u32(lines.len() as u32)?;
@@ -1295,25 +1300,24 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
 
                 Ok(())
             })?;
-            s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?;
-            s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?;
-            s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?;
-            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?;
-            s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s))
+            s.emit_struct_field("multibyte_chars", false, |s| self.multibyte_chars.encode(s))?;
+            s.emit_struct_field("non_narrow_chars", false, |s| self.non_narrow_chars.encode(s))?;
+            s.emit_struct_field("name_hash", false, |s| self.name_hash.encode(s))?;
+            s.emit_struct_field("normalized_pos", false, |s| self.normalized_pos.encode(s))?;
+            s.emit_struct_field("cnum", false, |s| self.cnum.encode(s))
         })
     }
 }
 
 impl<D: Decoder> Decodable<D> for SourceFile {
     fn decode(d: &mut D) -> Result<SourceFile, D::Error> {
-        d.read_struct("SourceFile", 8, |d| {
-            let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
+        d.read_struct(|d| {
+            let name: FileName = d.read_struct_field("name", |d| Decodable::decode(d))?;
             let src_hash: SourceFileHash =
-                d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?;
-            let start_pos: BytePos =
-                d.read_struct_field("start_pos", 3, |d| Decodable::decode(d))?;
-            let end_pos: BytePos = d.read_struct_field("end_pos", 4, |d| Decodable::decode(d))?;
-            let lines: Vec<BytePos> = d.read_struct_field("lines", 5, |d| {
+                d.read_struct_field("src_hash", |d| Decodable::decode(d))?;
+            let start_pos: BytePos = d.read_struct_field("start_pos", |d| Decodable::decode(d))?;
+            let end_pos: BytePos = d.read_struct_field("end_pos", |d| Decodable::decode(d))?;
+            let lines: Vec<BytePos> = d.read_struct_field("lines", |d| {
                 let num_lines: u32 = Decodable::decode(d)?;
                 let mut lines = Vec::with_capacity(num_lines as usize);
 
@@ -1342,13 +1346,13 @@ fn decode(d: &mut D) -> Result<SourceFile, D::Error> {
                 Ok(lines)
             })?;
             let multibyte_chars: Vec<MultiByteChar> =
-                d.read_struct_field("multibyte_chars", 6, |d| Decodable::decode(d))?;
+                d.read_struct_field("multibyte_chars", |d| Decodable::decode(d))?;
             let non_narrow_chars: Vec<NonNarrowChar> =
-                d.read_struct_field("non_narrow_chars", 7, |d| Decodable::decode(d))?;
-            let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?;
+                d.read_struct_field("non_narrow_chars", |d| Decodable::decode(d))?;
+            let name_hash: u128 = d.read_struct_field("name_hash", |d| Decodable::decode(d))?;
             let normalized_pos: Vec<NormalizedPos> =
-                d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?;
-            let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?;
+                d.read_struct_field("normalized_pos", |d| Decodable::decode(d))?;
+            let cnum: CrateNum = d.read_struct_field("cnum", |d| Decodable::decode(d))?;
             Ok(SourceFile {
                 name,
                 start_pos,
index 46ef308cbf27c5fa90e8465316ad36e7b7e23de4..31b425f1a79a08fbe54eacdb0eb0942d0aedbfa7 100644 (file)
         box_free,
         box_patterns,
         box_syntax,
+        bpf_target_feature,
         braced_empty_structs,
         branch,
         breakpoint,
         wrapping_add,
         wrapping_mul,
         wrapping_sub,
+        wreg,
         write_bytes,
         xmm_reg,
         ymm_reg,
index 0c64fe6ea60a9249cbce6f5c1c98d30d77a20ab3..025eaffcbd3285ca8c012281d2f289efe5d33d1f 100644 (file)
@@ -126,9 +126,8 @@ fn get_symbol_hash<'tcx>(
         substs.hash_stable(&mut hcx, &mut hasher);
 
         if let Some(instantiating_crate) = instantiating_crate {
-            tcx.def_path_hash(instantiating_crate.as_def_id())
-                .stable_crate_id()
-                .hash_stable(&mut hcx, &mut hasher);
+            tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher);
+            tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher);
         }
 
         // We want to avoid accidental collision between different types of instances.
index ba59ff96f6554d3e8e5f3ce9f55e448d7d73e9dc..f716ce1efce86f1d952df25a7ee5cfe5fd3d65ad 100644 (file)
@@ -165,12 +165,12 @@ fn compute_symbol_name(
     // FIXME(eddyb) Precompute a custom symbol name based on attributes.
     let is_foreign = if let Some(def_id) = def_id.as_local() {
         if tcx.plugin_registrar_fn(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id);
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         matches!(tcx.hir().get(hir_id), Node::ForeignItem(_))
index e7da56ed0f3c7459ecb1a7b5f1952e14085b17eb..828f1ac0a7989a7cdbc0e3fbb4a62983b9273c2c 100644 (file)
@@ -592,8 +592,8 @@ fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self:
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
         self.push("C");
-        let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-        self.push_disambiguator(stable_crate_id.to_u64());
+        let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
+        self.push_disambiguator(fingerprint.to_smaller_hash());
         let name = self.tcx.crate_name(cnum).as_str();
         self.push_ident(&name);
         Ok(self)
diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/abi/call/bpf.rs
new file mode 100644 (file)
index 0000000..466c525
--- /dev/null
@@ -0,0 +1,31 @@
+// see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFCallingConv.td
+use crate::abi::call::{ArgAbi, FnAbi};
+
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
+    if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 {
+        ret.make_indirect();
+    } else {
+        ret.extend_integer_width_to(32);
+    }
+}
+
+fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
+    if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 {
+        arg.make_indirect();
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
+    if !fn_abi.ret.is_ignore() {
+        classify_ret(&mut fn_abi.ret);
+    }
+
+    for arg in &mut fn_abi.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg(arg);
+    }
+}
index 0cf2441d84e04c5655a2fedf31208e08691d696c..6e0e140374033c3c2eef6ae53780160e3b9090c0 100644 (file)
@@ -6,6 +6,7 @@
 mod amdgpu;
 mod arm;
 mod avr;
+mod bpf;
 mod hexagon;
 mod mips;
 mod mips64;
@@ -654,6 +655,7 @@ pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(),
                 }
             }
             "asmjs" => wasm::compute_c_abi_info(cx, self),
+            "bpf" => bpf::compute_abi_info(self),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
         }
 
index 1679d02937477bbe920c6e1571312e62d08c8f2e..8e71ded3d1de6a7dfbbc006d4d7e8525df3d4866 100644 (file)
@@ -753,11 +753,7 @@ pub fn count(&self) -> usize {
         match *self {
             FieldsShape::Primitive => 0,
             FieldsShape::Union(count) => count.get(),
-            FieldsShape::Array { count, .. } => {
-                let usize_count = count as usize;
-                assert_eq!(usize_count as u64, count);
-                usize_count
-            }
+            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
             FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
         }
     }
@@ -791,11 +787,7 @@ pub fn memory_index(&self, i: usize) -> usize {
                 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
             }
             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
-            FieldsShape::Arbitrary { ref memory_index, .. } => {
-                let r = memory_index[i];
-                assert_eq!(r as usize as u32, r);
-                r as usize
-            }
+            FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
         }
     }
 
diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs
new file mode 100644 (file)
index 0000000..ecb6bdc
--- /dev/null
@@ -0,0 +1,129 @@
+use super::{InlineAsmArch, InlineAsmType, Target};
+use rustc_macros::HashStable_Generic;
+use std::fmt;
+
+def_reg_class! {
+    Bpf BpfInlineAsmRegClass {
+        reg,
+        wreg,
+    }
+}
+
+impl BpfInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        _arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+        match self {
+            Self::reg => types! { _: I8, I16, I32, I64; },
+            Self::wreg => types! { "alu32": I8, I16, I32; },
+        }
+    }
+}
+
+fn only_alu32(
+    _arch: InlineAsmArch,
+    mut has_feature: impl FnMut(&str) -> bool,
+    _target: &Target,
+) -> Result<(), &'static str> {
+    if !has_feature("alu32") {
+        Err("register can't be used without the `alu32` target feature")
+    } else {
+        Ok(())
+    }
+}
+
+def_regs! {
+    Bpf BpfInlineAsmReg BpfInlineAsmRegClass {
+        r0: reg = ["r0"],
+        r1: reg = ["r1"],
+        r2: reg = ["r2"],
+        r3: reg = ["r3"],
+        r4: reg = ["r4"],
+        r5: reg = ["r5"],
+        r6: reg = ["r6"],
+        r7: reg = ["r7"],
+        r8: reg = ["r8"],
+        r9: reg = ["r9"],
+        w0: wreg = ["w0"] % only_alu32,
+        w1: wreg = ["w1"] % only_alu32,
+        w2: wreg = ["w2"] % only_alu32,
+        w3: wreg = ["w3"] % only_alu32,
+        w4: wreg = ["w4"] % only_alu32,
+        w5: wreg = ["w5"] % only_alu32,
+        w6: wreg = ["w6"] % only_alu32,
+        w7: wreg = ["w7"] % only_alu32,
+        w8: wreg = ["w8"] % only_alu32,
+        w9: wreg = ["w9"] % only_alu32,
+
+        #error = ["r10", "w10"] =>
+            "the stack pointer cannot be used as an operand for inline asm",
+    }
+}
+
+impl BpfInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        out.write_str(self.name())
+    }
+
+    pub fn overlapping_regs(self, mut cb: impl FnMut(BpfInlineAsmReg)) {
+        cb(self);
+
+        macro_rules! reg_conflicts {
+            (
+                $(
+                    $r:ident : $w:ident
+                ),*
+            ) => {
+                match self {
+                    $(
+                        Self::$r => {
+                            cb(Self::$w);
+                        }
+                        Self::$w => {
+                            cb(Self::$r);
+                        }
+                    )*
+                }
+            };
+        }
+
+        reg_conflicts! {
+            r0 : w0,
+            r1 : w1,
+            r2 : w2,
+            r3 : w3,
+            r4 : w4,
+            r5 : w5,
+            r6 : w6,
+            r7 : w7,
+            r8 : w8,
+            r9 : w9
+        }
+    }
+}
index c17c2961434e5f6745982174a5f09ee3a1f18b5c..305ea7d50e66ea058a37d579d3223820bf4870c6 100644 (file)
@@ -148,6 +148,7 @@ macro_rules! types {
 
 mod aarch64;
 mod arm;
+mod bpf;
 mod hexagon;
 mod mips;
 mod nvptx;
@@ -159,6 +160,7 @@ macro_rules! types {
 
 pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
 pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
+pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
 pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
 pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
@@ -184,6 +186,7 @@ pub enum InlineAsmArch {
     PowerPC64,
     SpirV,
     Wasm32,
+    Bpf,
 }
 
 impl FromStr for InlineAsmArch {
@@ -205,6 +208,7 @@ fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
             "mips64" => Ok(Self::Mips64),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
+            "bpf" => Ok(Self::Bpf),
             _ => Err(()),
         }
     }
@@ -233,6 +237,7 @@ pub enum InlineAsmReg {
     Mips(MipsInlineAsmReg),
     SpirV(SpirVInlineAsmReg),
     Wasm(WasmInlineAsmReg),
+    Bpf(BpfInlineAsmReg),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -247,6 +252,7 @@ pub fn name(self) -> &'static str {
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::Bpf(r) => r.name(),
             Self::Err => "<reg>",
         }
     }
@@ -260,6 +266,7 @@ pub fn reg_class(self) -> InlineAsmRegClass {
             Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
             Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
             Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
+            Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Err => InlineAsmRegClass::Err,
         }
     }
@@ -304,6 +311,9 @@ pub fn parse(
             InlineAsmArch::Wasm32 => {
                 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
+            InlineAsmArch::Bpf => {
+                Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?)
+            }
         })
     }
 
@@ -323,6 +333,7 @@ pub fn emit(
             Self::PowerPC(r) => r.emit(out, arch, modifier),
             Self::Hexagon(r) => r.emit(out, arch, modifier),
             Self::Mips(r) => r.emit(out, arch, modifier),
+            Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -336,6 +347,7 @@ pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
             Self::PowerPC(_) => cb(self),
             Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
             Self::Mips(_) => cb(self),
+            Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -364,6 +376,7 @@ pub enum InlineAsmRegClass {
     Mips(MipsInlineAsmRegClass),
     SpirV(SpirVInlineAsmRegClass),
     Wasm(WasmInlineAsmRegClass),
+    Bpf(BpfInlineAsmRegClass),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -381,6 +394,7 @@ pub fn name(self) -> Symbol {
             Self::Mips(r) => r.name(),
             Self::SpirV(r) => r.name(),
             Self::Wasm(r) => r.name(),
+            Self::Bpf(r) => r.name(),
             Self::Err => rustc_span::symbol::sym::reg,
         }
     }
@@ -400,6 +414,7 @@ pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Sel
             Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
             Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
             Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
+            Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -426,6 +441,7 @@ pub fn suggest_modifier(
             Self::Mips(r) => r.suggest_modifier(arch, ty),
             Self::SpirV(r) => r.suggest_modifier(arch, ty),
             Self::Wasm(r) => r.suggest_modifier(arch, ty),
+            Self::Bpf(r) => r.suggest_modifier(arch, ty),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -448,6 +464,7 @@ pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str
             Self::Mips(r) => r.default_modifier(arch),
             Self::SpirV(r) => r.default_modifier(arch),
             Self::Wasm(r) => r.default_modifier(arch),
+            Self::Bpf(r) => r.default_modifier(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -469,6 +486,7 @@ pub fn supported_types(
             Self::Mips(r) => r.supported_types(arch),
             Self::SpirV(r) => r.supported_types(arch),
             Self::Wasm(r) => r.supported_types(arch),
+            Self::Bpf(r) => r.supported_types(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -493,6 +511,7 @@ pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
             }
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
         })
     }
 
@@ -510,6 +529,7 @@ pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
             Self::Mips(r) => r.valid_modifiers(arch),
             Self::SpirV(r) => r.valid_modifiers(arch),
             Self::Wasm(r) => r.valid_modifiers(arch),
+            Self::Bpf(r) => r.valid_modifiers(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -679,5 +699,10 @@ pub fn allocatable_registers(
             wasm::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
+        InlineAsmArch::Bpf => {
+            let mut map = bpf::regclass_map();
+            bpf::fill_reg_map(arch, has_feature, target, &mut map);
+            map
+        }
     }
 }
diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs
new file mode 100644 (file)
index 0000000..764cc73
--- /dev/null
@@ -0,0 +1,42 @@
+use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
+use crate::{abi::Endian, spec::abi::Abi};
+
+pub fn opts(endian: Endian) -> TargetOptions {
+    TargetOptions {
+        allow_asm: true,
+        endian,
+        linker_flavor: LinkerFlavor::BpfLinker,
+        atomic_cas: false,
+        executables: true,
+        dynamic_linking: true,
+        no_builtins: true,
+        panic_strategy: PanicStrategy::Abort,
+        position_independent_executables: true,
+        // Disable MergeFunctions since:
+        // - older kernels don't support bpf-to-bpf calls
+        // - on newer kernels, userspace still needs to relocate before calling
+        //   BPF_PROG_LOAD and not all BPF libraries do that yet
+        merge_functions: MergeFunctions::Disabled,
+        obj_is_bitcode: true,
+        requires_lto: false,
+        singlethread: true,
+        max_atomic_width: Some(64),
+        unsupported_abis: vec![
+            Abi::Cdecl,
+            Abi::Stdcall { unwind: false },
+            Abi::Stdcall { unwind: true },
+            Abi::Fastcall,
+            Abi::Vectorcall,
+            Abi::Thiscall { unwind: false },
+            Abi::Thiscall { unwind: true },
+            Abi::Aapcs,
+            Abi::Win64,
+            Abi::SysV64,
+            Abi::PtxKernel,
+            Abi::Msp430Interrupt,
+            Abi::X86Interrupt,
+            Abi::AmdGpuKernel,
+        ],
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
new file mode 100644 (file)
index 0000000..a45da82
--- /dev/null
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "bpfeb".to_string(),
+        data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        pointer_width: 64,
+        arch: "bpf".to_string(),
+        options: bpf_base::opts(Endian::Big),
+    }
+}
diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
new file mode 100644 (file)
index 0000000..6c9afdf
--- /dev/null
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "bpfel".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        pointer_width: 64,
+        arch: "bpf".to_string(),
+        options: bpf_base::opts(Endian::Little),
+    }
+}
index 4683def94f70e2b6de5bca9e03618661e9cd3e1f..0f2aaeb533a97d3ed4b8a9d27750fdd8285ce28c 100644 (file)
@@ -57,6 +57,7 @@
 mod apple_sdk_base;
 mod arm_base;
 mod avr_gnu_base;
+mod bpf_base;
 mod dragonfly_base;
 mod freebsd_base;
 mod fuchsia_base;
@@ -93,6 +94,7 @@ pub enum LinkerFlavor {
     Msvc,
     Lld(LldFlavor),
     PtxLinker,
+    BpfLinker,
 }
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -161,6 +163,7 @@ pub fn desc(&self) -> &str {
     ((LinkerFlavor::Ld), "ld"),
     ((LinkerFlavor::Msvc), "msvc"),
     ((LinkerFlavor::PtxLinker), "ptx-linker"),
+    ((LinkerFlavor::BpfLinker), "bpf-linker"),
     ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
     ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
     ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
@@ -897,6 +900,9 @@ fn $module() {
     ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
     ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
     ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
+
+    ("bpfeb-unknown-none", bpfeb_unknown_none),
+    ("bpfel-unknown-none", bpfel_unknown_none),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
index cc2578aa578e8d54796b5c72d7ec98b30d123708..6e3a241a86e042bd3c1e0b32db903fd2fcd26e82 100644 (file)
@@ -17,6 +17,7 @@ pub fn target() -> Target {
             // dependency on this specific gcc.
             asm_args: vec!["-mcpu=msp430".to_string()],
             linker: Some("msp430-elf-gcc".to_string()),
+            linker_is_gnu: false,
 
             // There are no atomic CAS instructions available in the MSP430
             // instruction set, and the LLVM backend doesn't currently support
index 87e740de08e9175e0099c03bac8ff93252d65c63..4c954a1e567ccb236e95b515fb2c8276be192364 100644 (file)
@@ -102,12 +102,7 @@ pub fn options() -> TargetOptions {
         // we use the LLD shipped with the Rust toolchain by default
         linker: Some("rust-lld".to_owned()),
         lld_flavor: LldFlavor::Wasm,
-
-        // No need for indirection here, simd types can always be passed by
-        // value as the whole module either has simd or not, which is different
-        // from x86 (for example) where programs can have functions that don't
-        // enable simd features.
-        simd_types_indirect: false,
+        linker_is_gnu: false,
 
         pre_link_args,
 
index db396356d67111adc9ed9175f5bbc49d745e33df..19c3385dd4cbcbc119df5a9144fc0cf8a7eea2b0 100644 (file)
@@ -1878,6 +1878,10 @@ fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
         hir::intravisit::NestedVisitorMap::None
     }
 
+    fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
+        // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
+    }
+
     fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
         // We collect the spans of all uses of the "bare" type param, like in `field: T` or
         // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
index 07a3132568b8d26c2a1cafb464535b637049b923..ebc7b0d0d99cfc0eb5a8bc65e386997c2b7fdaba 100644 (file)
@@ -1,11 +1,12 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_middle::hir::map as hir_map;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
     self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
+use rustc_session::CrateDisambiguator;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 
@@ -387,6 +388,11 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
     tcx.param_env(def_id).with_reveal_all_normalized(tcx)
 }
 
+fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.sess.local_crate_disambiguator()
+}
+
 fn instance_def_size_estimate<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance_def: ty::InstanceDef<'tcx>,
@@ -532,6 +538,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         param_env,
         param_env_reveal_all_normalized,
         trait_of_item,
+        crate_disambiguator,
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
index 92d7ea2600300e52bd1b97baba11121fcd55e62b..166410731d29161ad6071bd090466c7adaeba31f 100644 (file)
@@ -1214,10 +1214,19 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
                 }
             }
 
+            // Check that we use types valid for use in the lanes of a SIMD "vector register"
+            // These are scalar types which directly match a "machine" type
+            // Yes: Integers, floats, "thin" pointers
+            // No: char, "fat" pointers, compound types
             match e.kind() {
-                ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
-                _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
-                ty::Array(ty, _c) if ty.is_machine() => { /* struct([f32; 4]) */ }
+                ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
+                ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
+                ty::Array(t, _clen)
+                    if matches!(
+                        t.kind(),
+                        ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)
+                    ) =>
+                { /* struct([f32; 4]) is ok */ }
                 _ => {
                     struct_span_err!(
                         tcx.sess,
index 9cc435a0dec2ec01a45e2a32cd562e5b4d25d71a..33bc25accb319dceffcf2862d321aaf476cbee1f 100644 (file)
@@ -17,6 +17,7 @@
 use super::method::probe;
 
 use std::fmt;
+use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -573,12 +574,19 @@ pub fn check_ref(
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest removing a `&`.
                 if sm.is_imported(expr.span) {
-                    if let Ok(src) = sm.span_to_snippet(sp) {
-                        if let Some(src) = src.strip_prefix('&') {
+                    // Go through the spans from which this span was expanded,
+                    // and find the one that's pointing inside `sp`.
+                    //
+                    // E.g. for `&format!("")`, where we want the span to the
+                    // `format!()` invocation instead of its expansion.
+                    if let Some(call_span) =
+                        iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s))
+                    {
+                        if let Ok(code) = sm.span_to_snippet(call_span) {
                             return Some((
                                 sp,
                                 "consider removing the borrow",
-                                src.to_string(),
+                                code,
                                 Applicability::MachineApplicable,
                             ));
                         }
index de6336b254b3f49c643b3a3dae72a387d076a1a2..01276495c185aea81546f90973c0c04a3db91852 100644 (file)
@@ -310,6 +310,7 @@ fn a_is_expected(&self) -> bool {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
index 5d83375e5a1b8569f8e3257339ecd630117e4c01..f5ee4b21ea616b8073fbdb5df574f305806d8a80 100644 (file)
@@ -2597,6 +2597,7 @@ fn from_target_feature(
                 Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
                 Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
                 Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
index 5197b620f90ba73532765ea268ea91d39a103fbb..19c35ebd011b1307bd91220847740e158648bdc0 100644 (file)
@@ -766,7 +766,7 @@ fn infer_placeholder_type(
             if !ty.references_error() {
                 diag.span_suggestion(
                     span,
-                    "replace `_` with the correct type",
+                    "replace with the correct type",
                     ty.to_string(),
                     Applicability::MaybeIncorrect,
                 );
index df2fb448b7d4dc9b437636fe6ff40f69e3c8257d..7fa5353d09b899e7af4872bdb3ee522b41a4788c 100644 (file)
@@ -94,7 +94,7 @@ changelog-seen = 2
 # support. You'll need to write a target specification at least, and most
 # likely, teach rustc about the C ABI of the target. Get in touch with the
 # Rust team and file an issue if you need assistance in porting!
-#targets = "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
+#targets = "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
 
 # LLVM experimental targets to build support for. These targets are specified in
 # the same format as above, but since these targets are experimental, they are
index c9bdcaa78f3916436b5c05c36e70d341827d00fb..91eec10d575935ab95bf69ac22962c13e5394988 100644 (file)
@@ -551,19 +551,13 @@ fn bench_in_place_collect_droppable(b: &mut Bencher) {
 #[bench]
 fn bench_chain_collect(b: &mut Bencher) {
     let data = black_box([0; LEN]);
-    b.iter(|| data.iter().cloned().chain([1].iter().cloned()).collect::<Vec<_>>());
+    b.iter(|| data.iter().cloned().chain([1]).collect::<Vec<_>>());
 }
 
 #[bench]
 fn bench_chain_chain_collect(b: &mut Bencher) {
     let data = black_box([0; LEN]);
-    b.iter(|| {
-        data.iter()
-            .cloned()
-            .chain([1].iter().cloned())
-            .chain([2].iter().cloned())
-            .collect::<Vec<_>>()
-    });
+    b.iter(|| data.iter().cloned().chain([1]).chain([2]).collect::<Vec<_>>());
 }
 
 #[bench]
index 812765d0b0ded37655344c9eb6321708612fe28f..7b87090fb07138f18c17f990304dd15adf1db729 100644 (file)
@@ -1,4 +1,3 @@
-use core::array;
 use core::cmp::{self};
 use core::mem::replace;
 
@@ -37,7 +36,7 @@ pub fn has_remainder(&self) -> bool {
     }
 
     pub fn remainder(self) -> impl Iterator<Item = &'b [T]> {
-        array::IntoIter::new([self.b0, self.b1])
+        IntoIterator::into_iter([self.b0, self.b1])
     }
 }
 
index 7bc9aa69be98eac13c970ee5ab9494dad8a7e91f..a04e7c8a498daf7d6cda9dff39feee5a810d331d 100644 (file)
@@ -59,7 +59,6 @@
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
index dbe5bc1da460d7c42521ec175d5a8c13f539cde9..1fb645a302e76eb91bd4c0f104bb95ebc4f08147 100644 (file)
@@ -48,7 +48,7 @@
 use core::hash;
 #[cfg(not(no_global_oom_handling))]
 use core::iter::FromIterator;
-use core::iter::FusedIterator;
+use core::iter::{from_fn, FusedIterator};
 #[cfg(not(no_global_oom_handling))]
 use core::ops::Add;
 #[cfg(not(no_global_oom_handling))]
@@ -1290,32 +1290,49 @@ pub fn remove_matches<'a, P>(&'a mut self, pat: P)
     {
         use core::str::pattern::Searcher;
 
-        let matches = {
+        let rejections = {
             let mut searcher = pat.into_searcher(self);
-            let mut matches = Vec::new();
-
-            while let Some(m) = searcher.next_match() {
-                matches.push(m);
-            }
-
-            matches
+            // Per Searcher::next:
+            //
+            // A Match result needs to contain the whole matched pattern,
+            // however Reject results may be split up into arbitrary many
+            // adjacent fragments. Both ranges may have zero length.
+            //
+            // In practice the implementation of Searcher::next_match tends to
+            // be more efficient, so we use it here and do some work to invert
+            // matches into rejections since that's what we want to copy below.
+            let mut front = 0;
+            let rejections: Vec<_> = from_fn(|| {
+                let (start, end) = searcher.next_match()?;
+                let prev_front = front;
+                front = end;
+                Some((prev_front, start))
+            })
+            .collect();
+            rejections.into_iter().chain(core::iter::once((front, self.len())))
         };
 
-        let len = self.len();
-        let mut shrunk_by = 0;
+        let mut len = 0;
+        let ptr = self.vec.as_mut_ptr();
+
+        for (start, end) in rejections {
+            let count = end - start;
+            if start != len {
+                // SAFETY: per Searcher::next:
+                //
+                // The stream of Match and Reject values up to a Done will
+                // contain index ranges that are adjacent, non-overlapping,
+                // covering the whole haystack, and laying on utf8
+                // boundaries.
+                unsafe {
+                    ptr::copy(ptr.add(start), ptr.add(len), count);
+                }
+            }
+            len += count;
+        }
 
-        // SAFETY: start and end will be on utf8 byte boundaries per
-        // the Searcher docs
         unsafe {
-            for (start, end) in matches {
-                ptr::copy(
-                    self.vec.as_mut_ptr().add(end - shrunk_by),
-                    self.vec.as_mut_ptr().add(start - shrunk_by),
-                    len - end,
-                );
-                shrunk_by += end - start;
-            }
-            self.vec.set_len(len - shrunk_by);
+            self.vec.set_len(len);
         }
     }
 
index 105c60e7bf0851c270b853db941db50806f43350..4a1d564e2ab879547f8036133d7c0dc296c34c70 100644 (file)
@@ -921,7 +921,7 @@ pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveE
     ///
     /// ```
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     /// assert_eq!(vec.capacity(), 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
@@ -950,7 +950,7 @@ pub fn shrink_to_fit(&mut self) {
     /// ```
     /// #![feature(shrink_to)]
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     /// assert_eq!(vec.capacity(), 10);
     /// vec.shrink_to(4);
     /// assert!(vec.capacity() >= 4);
@@ -984,7 +984,7 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
     ///
     /// ```
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     ///
     /// assert_eq!(vec.capacity(), 10);
     /// let slice = vec.into_boxed_slice();
@@ -2586,7 +2586,7 @@ fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
     /// ```
     /// let mut v = vec![1, 2, 3];
     /// let new = [7, 8];
-    /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect();
+    /// let u: Vec<_> = v.splice(..2, new).collect();
     /// assert_eq!(v, &[7, 8, 3]);
     /// assert_eq!(u, &[1, 2]);
     /// ```
index 0a27b5b62ecf509830473fda17af573a1e2e51c2..bad765c7f51fab944b3de89a3a956de2dd42f158 100644 (file)
@@ -14,7 +14,7 @@
 /// ```
 /// let mut v = vec![0, 1, 2];
 /// let new = [7, 8];
-/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned());
+/// let iter: std::vec::Splice<_> = v.splice(1.., new);
 /// ```
 #[derive(Debug)]
 #[stable(feature = "vec_splice", since = "1.21.0")]
index 36c81b49709735cb3a126faf27733355b261ccbb..c203cdafecb03dd27be6f502965adffb715b6491 100644 (file)
@@ -793,7 +793,7 @@ fn drop(&mut self) {
 fn test_splice() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(2..4, a.iter().cloned());
+    v.splice(2..4, a);
     assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
     v.splice(1..3, Some(20));
     assert_eq!(v, &[1, 20, 11, 12, 5]);
@@ -803,7 +803,7 @@ fn test_splice() {
 fn test_splice_inclusive_range() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect();
+    let t1: Vec<_> = v.splice(2..=3, a).collect();
     assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
     assert_eq!(t1, &[3, 4]);
     let t2: Vec<_> = v.splice(1..=2, Some(20)).collect();
@@ -816,7 +816,7 @@ fn test_splice_inclusive_range() {
 fn test_splice_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(5..6, a.iter().cloned());
+    v.splice(5..6, a);
 }
 
 #[test]
@@ -824,7 +824,7 @@ fn test_splice_out_of_bounds() {
 fn test_splice_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(5..=5, a.iter().cloned());
+    v.splice(5..=5, a);
 }
 
 #[test]
@@ -848,7 +848,7 @@ fn test_splice_unbounded() {
 fn test_splice_forget() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    std::mem::forget(v.splice(2..4, a.iter().cloned()));
+    std::mem::forget(v.splice(2..4, a));
     assert_eq!(v, &[1, 2]);
 }
 
index e25d006d213c7e20a76bf85243e05f7a1993fc8e..37af3557fdd51ce792459ec680f32019413bbf03 100644 (file)
@@ -416,7 +416,7 @@ macro_rules! array_impl_default {
     {
         // SAFETY: we know for certain that this iterator will yield exactly `N`
         // items.
-        unsafe { collect_into_array_unchecked(&mut IntoIter::new(self).map(f)) }
+        unsafe { collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
     }
 
     /// 'Zips up' two arrays into a single array of pairs.
@@ -437,7 +437,7 @@ macro_rules! array_impl_default {
     /// ```
     #[unstable(feature = "array_zip", issue = "80094")]
     pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
-        let mut iter = IntoIter::new(self).zip(IntoIter::new(rhs));
+        let mut iter = IntoIterator::into_iter(self).zip(rhs);
 
         // SAFETY: we know for certain that this iterator will yield exactly `N`
         // items.
index dcab2cd2d9db1d38c4fdf6fa529019a097489881..2da3d6a72fb6f18049028616880ff5f137a10a0d 100644 (file)
@@ -58,7 +58,7 @@ impl char {
     /// ];
     ///
     /// assert_eq!(
-    ///     decode_utf16(v.iter().cloned())
+    ///     decode_utf16(v)
     ///         .map(|r| r.map_err(|e| e.unpaired_surrogate()))
     ///         .collect::<Vec<_>>(),
     ///     vec![
@@ -82,7 +82,7 @@ impl char {
     /// ];
     ///
     /// assert_eq!(
-    ///     decode_utf16(v.iter().cloned())
+    ///     decode_utf16(v)
     ///        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
     ///        .collect::<String>(),
     ///     "𝄞mus�ic�"
index a023edaca9e940563911eb1117989b774e4182f6..d4e4c5b0d3e543a4138bdf20a52caebd4d312684 100644 (file)
@@ -51,7 +51,6 @@
 #![cfg(not(test))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
 #![feature(const_fn_transmute)]
 #![feature(abi_unadjusted)]
 #![feature(adx_target_feature)]
-#![feature(external_doc)]
 #![feature(associated_type_bounds)]
 #![feature(const_caller_location)]
 #![feature(slice_ptr_get)]
index dbeb3912130061cb8ab951f672f06f1e133ad6ff..684e6bb4a0fba0b34e149fdebf34c9ea19b30f44 100644 (file)
@@ -674,10 +674,10 @@ pub enum Bound<T> {
     Unbounded,
 }
 
-#[unstable(feature = "bound_as_ref", issue = "80996")]
 impl<T> Bound<T> {
     /// Converts from `&Bound<T>` to `Bound<&T>`.
     #[inline]
+    #[unstable(feature = "bound_as_ref", issue = "80996")]
     pub fn as_ref(&self) -> Bound<&T> {
         match *self {
             Included(ref x) => Included(x),
@@ -688,6 +688,7 @@ pub fn as_ref(&self) -> Bound<&T> {
 
     /// Converts from `&mut Bound<T>` to `Bound<&T>`.
     #[inline]
+    #[unstable(feature = "bound_as_ref", issue = "80996")]
     pub fn as_mut(&mut self) -> Bound<&mut T> {
         match *self {
             Included(ref mut x) => Included(x),
@@ -695,6 +696,39 @@ pub fn as_mut(&mut self) -> Bound<&mut T> {
             Unbounded => Unbounded,
         }
     }
+
+    /// Maps a `Bound<T>` to a `Bound<U>` by applying a function to the contained value (including
+    /// both `Included` and `Excluded`), returning a `Bound` of the same kind.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(bound_map)]
+    /// use std::ops::Bound::*;
+    ///
+    /// let bound_string = Included("Hello, World!");
+    ///
+    /// assert_eq!(bound_string.map(|s| s.len()), Included(13));
+    /// ```
+    ///
+    /// ```
+    /// #![feature(bound_map)]
+    /// use std::ops::Bound;
+    /// use Bound::*;
+    ///
+    /// let unbounded_string: Bound<String> = Unbounded;
+    ///
+    /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
+    /// ```
+    #[inline]
+    #[unstable(feature = "bound_map", issue = "86026")]
+    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
+        match self {
+            Unbounded => Unbounded,
+            Included(x) => Included(f(x)),
+            Excluded(x) => Excluded(f(x)),
+        }
+    }
 }
 
 impl<T: Clone> Bound<&T> {
index 3bcea4e6d25ed4eb285f6d1f0a1990b18c35f662..0e5c5ee726e54f4ca07d734a330cd95653287a6d 100644 (file)
@@ -2100,9 +2100,11 @@ pub fn strip_suffix<P: SlicePattern<Item = T> + ?Sized>(&self, suffix: &P) -> Op
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
     ///
@@ -2153,9 +2155,11 @@ pub fn binary_search(&self, x: &T) -> Result<usize, usize>
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
     ///
@@ -2224,9 +2228,11 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
index ce7480ce2ee892317e744af6794574a1e21ebc54..0ae625bdb68c6244f20b7a65c5e6154d6594afd4 100644 (file)
@@ -1,4 +1,4 @@
-use core::array::{self, IntoIter};
+use core::array;
 use core::convert::TryFrom;
 
 #[test]
@@ -41,14 +41,14 @@ macro_rules! test {
 #[test]
 fn iterator_collect() {
     let arr = [0, 1, 2, 5, 9];
-    let v: Vec<_> = IntoIter::new(arr.clone()).collect();
+    let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
     assert_eq!(&arr[..], &v[..]);
 }
 
 #[test]
 fn iterator_rev_collect() {
     let arr = [0, 1, 2, 5, 9];
-    let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
+    let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
     assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
 }
 
@@ -56,11 +56,11 @@ fn iterator_rev_collect() {
 fn iterator_nth() {
     let v = [0, 1, 2, 3, 4];
     for i in 0..v.len() {
-        assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
+        assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
     }
-    assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);
+    assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
 
-    let mut iter = IntoIter::new(v);
+    let mut iter = IntoIterator::into_iter(v);
     assert_eq!(iter.nth(2).unwrap(), v[2]);
     assert_eq!(iter.nth(1).unwrap(), v[4]);
 }
@@ -68,17 +68,17 @@ fn iterator_nth() {
 #[test]
 fn iterator_last() {
     let v = [0, 1, 2, 3, 4];
-    assert_eq!(IntoIter::new(v).last().unwrap(), 4);
-    assert_eq!(IntoIter::new([0]).last().unwrap(), 0);
+    assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
+    assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
 
-    let mut it = IntoIter::new([0, 9, 2, 4]);
+    let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
     assert_eq!(it.next_back(), Some(4));
     assert_eq!(it.last(), Some(2));
 }
 
 #[test]
 fn iterator_clone() {
-    let mut it = IntoIter::new([0, 2, 4, 6, 8]);
+    let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next_back(), Some(8));
     let mut clone = it.clone();
@@ -92,7 +92,7 @@ fn iterator_clone() {
 
 #[test]
 fn iterator_fused() {
-    let mut it = IntoIter::new([0, 9, 2]);
+    let mut it = IntoIterator::into_iter([0, 9, 2]);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(9));
     assert_eq!(it.next(), Some(2));
@@ -105,7 +105,7 @@ fn iterator_fused() {
 
 #[test]
 fn iterator_len() {
-    let mut it = IntoIter::new([0, 1, 2, 5, 9]);
+    let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
     assert_eq!(it.size_hint(), (5, Some(5)));
     assert_eq!(it.len(), 5);
     assert_eq!(it.is_empty(), false);
@@ -121,7 +121,7 @@ fn iterator_len() {
     assert_eq!(it.is_empty(), false);
 
     // Empty
-    let it = IntoIter::new([] as [String; 0]);
+    let it = IntoIterator::into_iter([] as [String; 0]);
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.len(), 0);
     assert_eq!(it.is_empty(), true);
@@ -130,9 +130,9 @@ fn iterator_len() {
 #[test]
 fn iterator_count() {
     let v = [0, 1, 2, 3, 4];
-    assert_eq!(IntoIter::new(v.clone()).count(), 5);
+    assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
 
-    let mut iter2 = IntoIter::new(v);
+    let mut iter2 = IntoIterator::into_iter(v);
     iter2.next();
     iter2.next();
     assert_eq!(iter2.count(), 3);
@@ -140,13 +140,13 @@ fn iterator_count() {
 
 #[test]
 fn iterator_flat_map() {
-    assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
+    assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
 }
 
 #[test]
 fn iterator_debug() {
     let arr = [0, 1, 2, 5, 9];
-    assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",);
+    assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
 }
 
 #[test]
@@ -176,14 +176,14 @@ fn drop(&mut self) {
     // Simple: drop new iterator.
     let i = Cell::new(0);
     {
-        IntoIter::new(five(&i));
+        IntoIterator::into_iter(five(&i));
     }
     assert_eq!(i.get(), 5);
 
     // Call `next()` once.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         let _x = iter.next();
         assert_eq!(i.get(), 0);
         assert_eq!(iter.count(), 4);
@@ -194,7 +194,7 @@ fn drop(&mut self) {
     // Check `clone` and calling `next`/`next_back`.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         iter.next();
         assert_eq!(i.get(), 1);
         iter.next_back();
@@ -217,7 +217,7 @@ fn drop(&mut self) {
     // Check via `nth`.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         let _x = iter.nth(2);
         assert_eq!(i.get(), 2);
         let _y = iter.last();
@@ -227,13 +227,13 @@ fn drop(&mut self) {
 
     // Check every element.
     let i = Cell::new(0);
-    for (index, _x) in IntoIter::new(five(&i)).enumerate() {
+    for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
         assert_eq!(i.get(), index);
     }
     assert_eq!(i.get(), 5);
 
     let i = Cell::new(0);
-    for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
+    for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
         assert_eq!(i.get(), index);
     }
     assert_eq!(i.get(), 5);
index 000c15f72c886d35df0fb64dc6958c3bf9df621b..797bfd957f906ec2cc4c28632cc621e0b3f1fcc2 100644 (file)
@@ -236,9 +236,7 @@ fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
 fn test_double_ended_zip() {
     let xs = [1, 2, 3, 4, 5, 6];
     let ys = [1, 2, 3, 7];
-    let a = xs.iter().cloned();
-    let b = ys.iter().cloned();
-    let mut it = a.zip(b);
+    let mut it = xs.iter().cloned().zip(ys);
     assert_eq!(it.next(), Some((1, 1)));
     assert_eq!(it.next(), Some((2, 2)));
     assert_eq!(it.next_back(), Some((4, 7)));
index 5dcd1e6af365917cf324a5dfbfcc827db9e4de75..d95ea6530c20491e355787972093b814164acc85 100644 (file)
@@ -5,10 +5,7 @@
 
 #![no_std]
 #![unstable(feature = "panic_abort", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![panic_runtime]
 #![allow(unused_features)]
 #![feature(core_intrinsics)]
index 99a0c67fc11b90625918ef1d0a3dd5a32d493424..d32a3f1f8322c79aa190f62b30e7f4dd0b5c64ff 100644 (file)
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(nll)]
index 04a165e09f1e5544ffc51f8ed56d8736a4eba917..3990826ce42e0fe7fc411013a00dfbc4c1568f7a 100644 (file)
@@ -12,7 +12,6 @@
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
 #![deny(missing_docs)]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
index 922c2c2bb8c4dc0749d70c5190e4985733eec1b0..415d874c7faa64740ccd473cf493f1a661826ac6 100644 (file)
@@ -17,7 +17,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.93", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.43" }
+compiler_builtins = { version = "0.1.44" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }
index 8e4c63762fd38b3d407a7ae417c36aeedadd1dba..c4f21587457c1555591e125fe0184bf8aa7092ab 100644 (file)
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
index 9c5615f58c4363274b00a1e42f3c4f46b371bb64..ede147aca12e006769c35469b2c1b25690217de9 100644 (file)
@@ -1420,6 +1420,9 @@ fn clone_from(&mut self, source: &Self) {
 
 #[stable(feature = "box_from_path", since = "1.17.0")]
 impl From<&Path> for Box<Path> {
+    /// Creates a boxed [`Path`] from a reference.
+    ///
+    /// This will allocate and clone `path` to it.
     fn from(path: &Path) -> Box<Path> {
         let boxed: Box<OsStr> = path.inner.into();
         let rw = Box::into_raw(boxed) as *mut Path;
@@ -1429,6 +1432,9 @@ fn from(path: &Path) -> Box<Path> {
 
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, Path>> for Box<Path> {
+    /// Creates a boxed [`Path`] from a clone-on-write pointer.
+    ///
+    /// Converting from a `Cow::Owned` does not clone or allocate.
     #[inline]
     fn from(cow: Cow<'_, Path>) -> Box<Path> {
         match cow {
@@ -1471,6 +1477,9 @@ fn clone(&self) -> Self {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
+    /// Converts a borrowed `OsStr` to a `PathBuf`.
+    ///
+    /// Allocates a [`PathBuf`] and copies the data into it.
     #[inline]
     fn from(s: &T) -> PathBuf {
         PathBuf::from(s.as_ref().to_os_string())
@@ -1575,6 +1584,10 @@ fn default() -> Self {
 
 #[stable(feature = "cow_from_path", since = "1.6.0")]
 impl<'a> From<&'a Path> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from a reference to
+    /// [`Path`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(s: &'a Path) -> Cow<'a, Path> {
         Cow::Borrowed(s)
@@ -1583,6 +1596,10 @@ fn from(s: &'a Path) -> Cow<'a, Path> {
 
 #[stable(feature = "cow_from_path", since = "1.6.0")]
 impl<'a> From<PathBuf> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from an owned
+    /// instance of [`PathBuf`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(s: PathBuf) -> Cow<'a, Path> {
         Cow::Owned(s)
@@ -1591,6 +1608,10 @@ fn from(s: PathBuf) -> Cow<'a, Path> {
 
 #[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
 impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from a reference to
+    /// [`PathBuf`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(p: &'a PathBuf) -> Cow<'a, Path> {
         Cow::Borrowed(p.as_path())
@@ -1599,6 +1620,9 @@ fn from(p: &'a PathBuf) -> Cow<'a, Path> {
 
 #[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
 impl<'a> From<Cow<'a, Path>> for PathBuf {
+    /// Converts a clone-on-write pointer to an owned path.
+    ///
+    /// Converting from a `Cow::Owned` does not clone or allocate.
     #[inline]
     fn from(p: Cow<'a, Path>) -> Self {
         p.into_owned()
@@ -2462,10 +2486,10 @@ pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
     /// Returns `true` if the path points at an existing entity.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
@@ -2513,10 +2537,10 @@ pub fn try_exists(&self) -> io::Result<bool> {
     /// Returns `true` if the path exists on disk and is pointing at a regular file.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
@@ -2545,10 +2569,10 @@ pub fn is_file(&self) -> bool {
     /// Returns `true` if the path exists on disk and is pointing at a directory.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
index 57d91441b6fc320430e0bdda47e644b4f61aeedd..ca9cc8ca7ba391259529d6c9c4c7b7ccc35ab235 100644 (file)
@@ -210,7 +210,6 @@ pub fn abort_internal() -> ! {
     if #[cfg(target_os = "android")] {
         #[link(name = "dl")]
         #[link(name = "log")]
-        #[link(name = "gcc")]
         extern "C" {}
     } else if #[cfg(target_os = "freebsd")] {
         #[link(name = "execinfo")]
index 89addae078948708f7abfe574a21c575760588ec..899cf6841ee1f4300da07f31f40023b123ada175 100644 (file)
@@ -82,7 +82,7 @@
 /// Currently, the following system calls are being used to get the current time using `now()`:
 ///
 /// |  Platform |               System call                                            |
-/// |:---------:|:--------------------------------------------------------------------:|
+/// |-----------|----------------------------------------------------------------------|
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
 /// Currently, the following system calls are being used to get the current time using `now()`:
 ///
 /// |  Platform |               System call                                            |
-/// |:---------:|:--------------------------------------------------------------------:|
+/// |-----------|----------------------------------------------------------------------|
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | Darwin    | [gettimeofday]                                                       |
index 2116b433fce3f8c50d44897bf74b2b9e7c675276..943b276a220c88fc7e330804f0c2edcc6601bfc9 100644 (file)
 //! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    html_playground_url = "https://play.rust-lang.org/",
-    test(attr(deny(warnings)))
-)]
+#![doc(html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))]
 #![deny(missing_docs)]
 #![cfg_attr(windows, feature(libc))]
 
index 5e41d6d9692342067cf405fe971615f28b0bd734..e17fc08a9ae993b0a65eb150bf6d43308d145500 100644 (file)
@@ -169,7 +169,11 @@ pub fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()
 
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
+        if let Some(test_mode) = desc.test_mode() {
+            self.write_plain(&format!("test {} - {} ... ", name, test_mode))?;
+        } else {
+            self.write_plain(&format!("test {} ... ", name))?;
+        }
 
         Ok(())
     }
index 6f46f7255a47ed3c17f9f0b681e158d6773853b9..a2c223c494c293dca5c9ef13bb82269a47d1dded 100644 (file)
@@ -158,7 +158,11 @@ pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
 
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
+        if let Some(test_mode) = desc.test_mode() {
+            self.write_plain(&format!("test {} - {} ... ", name, test_mode))?;
+        } else {
+            self.write_plain(&format!("test {} ... ", name))?;
+        }
 
         Ok(())
     }
index bda5ed888d7e1dc091328e77a16b213cdc99d1ac..3da4d434f48f23843e3ac3b2f588a51f94cae487 100644 (file)
@@ -19,7 +19,7 @@
 
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "50297")]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
+#![doc(test(attr(deny(warnings))))]
 #![cfg_attr(unix, feature(libc))]
 #![feature(rustc_private)]
 #![feature(nll)]
index 6a3f31b74ea5995f834a9563754663787ab969fa..5a4a540b04eb04c92eb2a0b4b8c092194ac65770 100644 (file)
@@ -61,6 +61,10 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: true,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
@@ -71,6 +75,10 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: false,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
@@ -89,6 +97,10 @@ fn f() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -108,6 +120,10 @@ fn f() {}
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -131,6 +147,10 @@ fn f() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -154,6 +174,10 @@ fn f() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage("error message"),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -182,6 +206,10 @@ fn f() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -214,6 +242,10 @@ fn f() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -238,6 +270,10 @@ fn f() {}
                 ignore: false,
                 should_panic,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(f)),
@@ -270,6 +306,10 @@ fn f() {}
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -303,6 +343,10 @@ fn f() {}
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -340,6 +384,10 @@ fn typed_test_desc(test_type: TestType) -> TestDesc {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type,
     }
 }
@@ -451,6 +499,10 @@ pub fn exclude_should_panic_option() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(move || {})),
@@ -473,6 +525,10 @@ fn tests() -> Vec<TestDescAndFn> {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(move || {})),
@@ -565,6 +621,10 @@ fn testfn() {}
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(testfn)),
@@ -642,6 +702,10 @@ fn f(_: &mut Bencher) {}
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -662,6 +726,10 @@ fn f(b: &mut Bencher) {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -676,6 +744,10 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -684,6 +756,10 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
index c5d91f653b3563e6f33bb29275718615aa66bd2d..63907c71ea7cc618b9d08602d4a51c41f32d6b66 100644 (file)
@@ -124,6 +124,10 @@ pub struct TestDesc {
     pub ignore: bool,
     pub should_panic: options::ShouldPanic,
     pub allow_fail: bool,
+    #[cfg(not(bootstrap))]
+    pub compile_fail: bool,
+    #[cfg(not(bootstrap))]
+    pub no_run: bool,
     pub test_type: TestType,
 }
 
@@ -140,6 +144,36 @@ pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
             }
         }
     }
+
+    /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test.
+    /// Descriptions include "should panic", "compile fail" and "compile".
+    #[cfg(not(bootstrap))]
+    pub fn test_mode(&self) -> Option<&'static str> {
+        if self.ignore {
+            return None;
+        }
+        match self.should_panic {
+            options::ShouldPanic::Yes | options::ShouldPanic::YesWithMessage(_) => {
+                return Some("should panic");
+            }
+            options::ShouldPanic::No => {}
+        }
+        if self.allow_fail {
+            return Some("allow fail");
+        }
+        if self.compile_fail {
+            return Some("compile fail");
+        }
+        if self.no_run {
+            return Some("compile");
+        }
+        None
+    }
+
+    #[cfg(bootstrap)]
+    pub fn test_mode(&self) -> Option<&'static str> {
+        None
+    }
 }
 
 #[derive(Debug)]
index 96df3fc5ac4c8351980da712da87705cfac19324..0529d24a27408002b3b36c500c9b87b8cd925d62 100644 (file)
@@ -20,6 +20,20 @@ fn main() {
         // linking for Linux is handled in lib.rs
         if target.contains("musl") {
             llvm_libunwind::compile();
+        } else if target.contains("android") {
+            let build = cc::Build::new();
+
+            // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
+            // check if we have `libunwind` available and if so use it. Otherwise
+            // fall back to `libgcc` to support older ndk versions.
+            let has_unwind =
+                build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
+
+            if has_unwind {
+                println!("cargo:rustc-link-lib=unwind");
+            } else {
+                println!("cargo:rustc-link-lib=gcc");
+            }
         }
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=gcc_s");
index 4b98abfb308bf9921f2b436f7a50ffc8811b1b84..ac8bbfe102dfea63efb4f7491c99946f06cc4046 100644 (file)
@@ -124,6 +124,13 @@ fn main() {
                 cmd.arg("-C").arg("target-feature=-crt-static");
             }
         }
+
+        if stage == "0" {
+            // Cargo doesn't pass RUSTFLAGS to proc_macros:
+            // https://github.com/rust-lang/cargo/issues/4423
+            // Set `--cfg=bootstrap` explicitly instead.
+            cmd.arg("--cfg=bootstrap");
+        }
     }
 
     if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
index 149a899cef7a0cf615c88dfa94c6e3443af4d26d..7c7f162b82c04b43c586df3849d552d32471764a 100644 (file)
@@ -648,18 +648,20 @@ class RustBuild(object):
         rev_parse = ["git", "rev-parse", "--show-toplevel"]
         top_level = subprocess.check_output(rev_parse, universal_newlines=True).strip()
         compiler = "{}/compiler/".format(top_level)
+        library = "{}/library/".format(top_level)
 
         # Look for a version to compare to based on the current commit.
         # Only commits merged by bors will have CI artifacts.
         merge_base = ["git", "log", "--author=bors", "--pretty=%H", "-n1"]
         commit = subprocess.check_output(merge_base, universal_newlines=True).strip()
 
-        # Warn if there were changes to the compiler since the ancestor commit.
-        status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler])
+        # Warn if there were changes to the compiler or standard library since the ancestor commit.
+        status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler, library])
         if status != 0:
             if download_rustc == "if-unchanged":
                 return None
-            print("warning: `download-rustc` is enabled, but there are changes to compiler/")
+            print("warning: `download-rustc` is enabled, but there are changes to \
+                   compiler/ or library/")
 
         if self.verbose:
             print("using downloaded stage1 artifacts from CI (commit {})".format(commit))
index da298f7edb9f45b7141963a92c4739c09e0d85dd..06f8bf89daecde081435011dcc3ce1e980e400fd 100644 (file)
@@ -574,6 +574,18 @@ pub fn default_doc(&self, paths: &[PathBuf]) {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
+    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
+    pub fn doc_rust_lang_org_channel(&self) -> String {
+        let channel = match &*self.config.channel {
+            "stable" => &self.version,
+            "beta" => "beta",
+            "nightly" | "dev" => "nightly",
+            // custom build of rustdoc maybe? link to the latest stable docs just in case
+            _ => "stable",
+        };
+        "https://doc.rust-lang.org/".to_owned() + channel
+    }
+
     fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
         StepDescription::run(v, self, paths);
     }
index e5258d08956f6bbbce497dd0baf68df713bd88f1..ed311e273b19c9ee91b3d87bfef0a73abf2248eb 100644 (file)
@@ -269,7 +269,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
 
     if builder.no_std(target) == Some(true) {
         let mut features = "compiler-builtins-mem".to_string();
-        features.push_str(compiler_builtins_c_feature);
+        if !target.starts_with("bpf") {
+            features.push_str(compiler_builtins_c_feature);
+        }
 
         // for no-std targets we only compile a few no_std crates
         cargo
@@ -326,6 +328,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     if target.contains("riscv") {
         cargo.rustflag("-Cforce-unwind-tables=yes");
     }
+
+    let html_root =
+        format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
+    cargo.rustflag(&html_root);
+    cargo.rustdocflag(&html_root);
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -629,8 +636,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
     cargo
         .env("CFG_RELEASE", builder.rust_release())
         .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
-        .env("CFG_VERSION", builder.rust_version())
-        .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
+        .env("CFG_VERSION", builder.rust_version());
 
     let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
index 2960dd3df6bf48b81a98cbd0ee8c80e42a6176f2..21c7dd11d248bbbaf41ff58702234e532bb60674 100644 (file)
@@ -444,8 +444,13 @@ pub fn new(config: Config) -> Build {
 
         build.verbose("finding compilers");
         cc_detect::find(&mut build);
-        build.verbose("running sanity check");
-        sanity::check(&mut build);
+        // When running `setup`, the profile is about to change, so any requirements we have now may
+        // be different on the next invocation. Don't check for them until the next time x.py is
+        // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
+        if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
+            build.verbose("running sanity check");
+            sanity::check(&mut build);
+        }
 
         // If local-rust is the same major.minor as the current version, then force a
         // local-rebuild
@@ -1366,7 +1371,7 @@ fn ninja(&self) -> bool {
                 eprintln!(
                     "
 Couldn't find required command: ninja
-You should install ninja, or set ninja=false in config.toml
+You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
 "
                 );
                 std::process::exit(1);
index 4f33a13c2536aa503de035ce6611c209ec617a74..449fdb87b0224bdc18e2d1a18fa6fac3c7740c67 100644 (file)
@@ -153,7 +153,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let llvm_targets = match &builder.config.llvm_targets {
             Some(s) => s,
             None => {
-                "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
+                "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
                      Sparc;SystemZ;WebAssembly;X86"
             }
         };
index 7bd29c61b0cdb7b4e6b9f7168fbc4ab7751e9329..cc7c143d4746101f3960c72e42b4cdf68360b6f0 100644 (file)
@@ -1486,6 +1486,7 @@ fn run(self, builder: &Builder<'_>) {
             }
         }
         cmd.env("RUSTC_BOOTSTRAP", "1");
+        cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
         builder.add_rust_test_threads(&mut cmd);
 
         if builder.config.sanitizers_enabled(target) {
index 64e4be6863a62f824d2bf87ca2ddd2fdf93770c0..9d75ad0918a79186b5092b60b728c90c1018c628 100644 (file)
@@ -263,6 +263,7 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
     cargo.env("CFG_VERSION", builder.rust_version());
     cargo.env("CFG_RELEASE_NUM", &builder.version);
+    cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
 
     let info = GitInfo::new(builder.config.ignore_git, &dir);
     if let Some(sha) = info.sha() {
index 4c1cd758f0d1577f8dd06fa30680495bae3e8b01..112979b0bebc86f54047968bee5c7f37ec5eb8f4 100644 (file)
@@ -307,5 +307,6 @@ pub fn use_host_linker(target: TargetSelection) -> bool {
         || target.contains("wasm32")
         || target.contains("nvptx")
         || target.contains("fortanix")
-        || target.contains("fuchsia"))
+        || target.contains("fuchsia")
+        || target.contains("bpf"))
 }
index 077c322bd773678c610be68221c1ace78894dca7..05384117ac17567ffae5a9737e2d47fedb63de5f 100644 (file)
@@ -149,8 +149,7 @@ values:
 
 * `y`, `yes`, `on`, or no value: Unwind tables are forced to be generated.
 * `n`, `no`, or `off`: Unwind tables are not forced to be generated. If unwind
-  tables are required by the target or `-C panic=unwind`, an error will be
-  emitted.
+  tables are required by the target an error will be emitted.
 
 The default if not specified depends on the target.
 
@@ -234,6 +233,8 @@ flavor. Valid options are:
 * `ptx-linker`: use
   [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) for Nvidia
   NVPTX GPGPU support.
+* `bpf-linker`: use
+  [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support.
 * `wasm-ld`: use the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html)
   executable, a port of LLVM `lld` for WebAssembly.
 * `ld64.lld`: use the LLVM `lld` executable with the [`-flavor darwin`
index 321d3c5c44ea1db0e76449438b178137b33556f0..3225e95941cf3e03591d48a9d297eaf32bbb4855 100644 (file)
@@ -219,6 +219,8 @@ target | std | host | notes
 `armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
 `armv7s-apple-ios` | ✓ |  |
 `avr-unknown-gnu-atmega328` | * |  | AVR. Requires `-Z build-std=core`
+`bpfeb-unknown-none` | * |  | BPF (big endian)
+`bpfel-unknown-none` | * |  | BPF (little endian)
 `hexagon-unknown-linux-musl` | ? |  |
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS
 `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+)
index 8e3c62281895486707dbe55f9537f52a469bc802..cb7b85655b5a8fe86b62c32900ec4fdb155e1109 100644 (file)
@@ -424,9 +424,7 @@ without including it in your main documentation. For example, you could write th
 `lib.rs` to test your README as part of your doctests:
 
 ```rust,no_run
-#![feature(external_doc)]
-
-#[doc(include = "../README.md")]
+#[doc = include_str!("../README.md")]
 #[cfg(doctest)]
 pub struct ReadmeDoctests;
 ```
index 28b81a40265d3dfa2afd2e6c5fb3401ff305ff98..e9b15666bb316115d6f9b83d5f3168588a8879a8 100644 (file)
@@ -131,22 +131,6 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 [unstable-masked]: ../unstable-book/language-features/doc-masked.html
 [issue-masked]: https://github.com/rust-lang/rust/issues/44027
 
-### Include external files as API documentation
-
-As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This
-is useful if certain documentation is so long that it would break the flow of reading the source.
-Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to
-instead read that file and use it as if it were written inline.
-
-[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990
-
-`#[doc(include = "...")]` currently requires the `#![feature(external_doc)]` feature gate. For more
-information, see [its chapter in the Unstable Book][unstable-include] and [its tracking
-issue][issue-include].
-
-[unstable-include]: ../unstable-book/language-features/external-doc.html
-[issue-include]: https://github.com/rust-lang/rust/issues/44732
-
 ## Unstable command-line arguments
 
 These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warns.md b/src/doc/unstable-book/src/compiler-flags/force-warns.md
new file mode 100644 (file)
index 0000000..0a205be
--- /dev/null
@@ -0,0 +1,21 @@
+# `force-warns`
+
+The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
+
+------------------------
+
+This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warns` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
+
+## Example
+
+```rust,ignore (partial-example)
+#![allow(dead_code)]
+
+fn dead_function() {}
+// This would normally not produce a warning even though the
+// function is not used, because dead code is being allowed
+
+fn main() {}
+```
+
+We can force a warning to be produced by providing `--force-warns dead_code` to rustc.
diff --git a/src/doc/unstable-book/src/language-features/external-doc.md b/src/doc/unstable-book/src/language-features/external-doc.md
deleted file mode 100644 (file)
index effae5d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# `external_doc`
-
-The tracking issue for this feature is: [#44732]
-
-The `external_doc` feature allows the use of the `include` parameter to the `#[doc]` attribute, to
-include external files in documentation. Use the attribute in place of, or in addition to, regular
-doc comments and `#[doc]` attributes, and `rustdoc` will load the given file when it renders
-documentation for your crate.
-
-With the following files in the same directory:
-
-`external-doc.md`:
-
-```markdown
-# My Awesome Type
-
-This is the documentation for this spectacular type.
-```
-
-`lib.rs`:
-
-```no_run (needs-external-files)
-#![feature(external_doc)]
-
-#[doc(include = "external-doc.md")]
-pub struct MyAwesomeType;
-```
-
-`rustdoc` will load the file `external-doc.md` and use it as the documentation for the `MyAwesomeType`
-struct.
-
-When locating files, `rustdoc` will base paths in the `src/` directory, as if they were alongside the
-`lib.rs` for your crate. So if you want a `docs/` folder to live alongside the `src/` directory,
-start your paths with `../docs/` for `rustdoc` to properly find the file.
-
-This feature was proposed in [RFC #1990] and initially implemented in PR [#44781].
-
-[#44732]: https://github.com/rust-lang/rust/issues/44732
-[RFC #1990]: https://github.com/rust-lang/rfcs/pull/1990
-[#44781]: https://github.com/rust-lang/rust/pull/44781
index 5503b3b4b32fbb22247ee97a5be8b788fc07f66c..03dbf4fb617f4c2fd7f8ed637ed124bc39a788f1 100644 (file)
@@ -30,6 +30,7 @@ Inline assembly is currently supported on the following architectures:
 - Hexagon
 - MIPS32r2 and MIPS64r2
 - wasm32
+- BPF
 
 ## Basic usage
 
@@ -570,6 +571,8 @@ Here is the list of currently supported register classes:
 | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
 | PowerPC | `freg` | `f[0-31]` | `f` |
 | wasm32 | `local` | None\* | `r` |
+| BPF | `reg` | `r[0-10]` | `r` |
+| BPF | `wreg` | `w[0-10]` | `w` |
 
 > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
 >
@@ -615,6 +618,8 @@ Each register class has constraints on which value types they can be used with.
 | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
 | PowerPC | `freg` | None | `f32`, `f64` |
 | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
+| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
+| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
 
 > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
 
@@ -674,6 +679,7 @@ Some registers have multiple names. These are all treated by the compiler as ide
 | Hexagon | `r29` | `sp` |
 | Hexagon | `r30` | `fr` |
 | Hexagon | `r31` | `lr` |
+| BPF | `r[0-10]` | `w[0-10]` |
 
 Some registers cannot be used for input or output operands:
 
index 2f7233685db52b05c4dc9ba10a064cac719b8cdf..8647db5a45dc8277fbf12465c72a865b4f734a50 100644 (file)
@@ -135,6 +135,8 @@ except NameError:
     unichr = chr
 
 
+channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
+
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
 
@@ -270,6 +272,7 @@ def flatten(node):
 
 
 def normalize_xpath(path):
+    path = path.replace("{{channel}}", channel)
     if path.startswith('//'):
         return '.' + path  # avoid warnings
     elif path.startswith('.//'):
@@ -334,6 +337,7 @@ class CachedFiles(object):
 
 
 def check_string(data, pat, regexp):
+    pat = pat.replace("{{channel}}", channel)
     if not pat:
         return True  # special case a presence testing
     elif regexp:
index 3ae516bd6df7c0ccbbe0660ef34a76eab4d1e854..fa1639f9dc3dd4a0bb311361bff4d66338ebe2cf 100644 (file)
@@ -499,7 +499,7 @@ pub fn from_def_id_and_attrs_and_parts(
                                     format!("{}/std/", s.trim_end_matches('/'))
                                 }
                                 Some(ExternalLocation::Unknown) | None => {
-                                    "https://doc.rust-lang.org/nightly/std/".to_string()
+                                    format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
                                 }
                             };
                             // This is a primitive so the url is done "by hand".
@@ -809,7 +809,7 @@ fn cfg(&self, sess: &Session) -> Option<Arc<Cfg>> {
                 // #[doc(...)]
                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
                     for item in list {
-                        // #[doc(include)]
+                        // #[doc(hidden)]
                         if !item.has_name(sym::cfg) {
                             continue;
                         }
@@ -894,9 +894,6 @@ fn get_word_attr(mut self, word: Symbol) -> Option<ast::NestedMetaItem> {
     SugaredDoc,
     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
     RawDoc,
-    /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
-    /// given filename and the file contents.
-    Include { filename: Symbol },
 }
 
 // The goal of this function is to apply the `DocFragment` transformations that are required when
@@ -930,18 +927,8 @@ fn from_iter<T>(iter: T) -> Self
     where
         T: IntoIterator<Item = &'a DocFragment>,
     {
-        let mut prev_kind: Option<DocFragmentKind> = None;
         iter.into_iter().fold(String::new(), |mut acc, frag| {
-            if !acc.is_empty()
-                && prev_kind
-                    .take()
-                    .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
-                    .unwrap_or(false)
-            {
-                acc.push('\n');
-            }
             add_doc_fragment(&mut acc, &frag);
-            prev_kind = Some(frag.kind);
             acc
         })
     }
@@ -988,45 +975,6 @@ impl Attributes {
         self.other_attrs.lists(name)
     }
 
-    /// Reads a `MetaItem` from within an attribute, looks for whether it is a
-    /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
-    /// its expansion.
-    crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
-        mi.meta_item_list().and_then(|list| {
-            for meta in list {
-                if meta.has_name(sym::include) {
-                    // the actual compiled `#[doc(include="filename")]` gets expanded to
-                    // `#[doc(include(file="filename", contents="file contents")]` so we need to
-                    // look for that instead
-                    return meta.meta_item_list().and_then(|list| {
-                        let mut filename: Option<Symbol> = None;
-                        let mut contents: Option<Symbol> = None;
-
-                        for it in list {
-                            if it.has_name(sym::file) {
-                                if let Some(name) = it.value_str() {
-                                    filename = Some(name);
-                                }
-                            } else if it.has_name(sym::contents) {
-                                if let Some(docs) = it.value_str() {
-                                    contents = Some(docs);
-                                }
-                            }
-                        }
-
-                        if let (Some(filename), Some(contents)) = (filename, contents) {
-                            Some((filename, contents))
-                        } else {
-                            None
-                        }
-                    });
-                }
-            }
-
-            None
-        })
-    }
-
     crate fn has_doc_flag(&self, flag: Symbol) -> bool {
         for attr in &self.other_attrs {
             if !attr.has_name(sym::doc) {
@@ -1050,18 +998,9 @@ impl Attributes {
         let mut doc_strings: Vec<DocFragment> = vec![];
         let mut doc_line = 0;
 
-        fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
+        fn update_need_backline(doc_strings: &mut Vec<DocFragment>) {
             if let Some(prev) = doc_strings.last_mut() {
-                if matches!(prev.kind, DocFragmentKind::Include { .. })
-                    || prev.kind != frag.kind
-                    || prev.parent_module != frag.parent_module
-                {
-                    // add a newline for extra padding between segments
-                    prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
-                        || prev.kind == DocFragmentKind::RawDoc
-                } else {
-                    prev.need_backline = true;
-                }
+                prev.need_backline = true;
             }
         }
 
@@ -1087,31 +1026,12 @@ fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment)
                     indent: 0,
                 };
 
-                update_need_backline(&mut doc_strings, &frag);
+                update_need_backline(&mut doc_strings);
 
                 doc_strings.push(frag);
 
                 None
             } else {
-                if attr.has_name(sym::doc) {
-                    if let Some(mi) = attr.meta() {
-                        if let Some((filename, contents)) = Attributes::extract_include(&mi) {
-                            let line = doc_line;
-                            doc_line += contents.as_str().lines().count();
-                            let frag = DocFragment {
-                                line,
-                                span: attr.span,
-                                doc: contents,
-                                kind: DocFragmentKind::Include { filename },
-                                parent_module,
-                                need_backline: false,
-                                indent: 0,
-                            };
-                            update_need_backline(&mut doc_strings, &frag);
-                            doc_strings.push(frag);
-                        }
-                    }
-                }
                 Some(attr.clone())
             }
         };
@@ -1137,10 +1057,7 @@ fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment)
         let mut out = String::new();
         add_doc_fragment(&mut out, &ori);
         while let Some(new_frag) = iter.next() {
-            if matches!(ori.kind, DocFragmentKind::Include { .. })
-                || new_frag.kind != ori.kind
-                || new_frag.parent_module != ori.parent_module
-            {
+            if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
                 break;
             }
             add_doc_fragment(&mut out, &new_frag);
@@ -1767,37 +1684,6 @@ impl PrimitiveType {
         }
     }
 
-    crate fn as_str(&self) -> &'static str {
-        use self::PrimitiveType::*;
-        match *self {
-            Isize => "isize",
-            I8 => "i8",
-            I16 => "i16",
-            I32 => "i32",
-            I64 => "i64",
-            I128 => "i128",
-            Usize => "usize",
-            U8 => "u8",
-            U16 => "u16",
-            U32 => "u32",
-            U64 => "u64",
-            U128 => "u128",
-            F32 => "f32",
-            F64 => "f64",
-            Str => "str",
-            Bool => "bool",
-            Char => "char",
-            Array => "array",
-            Slice => "slice",
-            Tuple => "tuple",
-            Unit => "unit",
-            RawPointer => "pointer",
-            Reference => "reference",
-            Fn => "fn",
-            Never => "never",
-        }
-    }
-
     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
     }
@@ -1860,10 +1746,6 @@ impl PrimitiveType {
         })
     }
 
-    crate fn to_url_str(&self) -> &'static str {
-        self.as_str()
-    }
-
     crate fn as_sym(&self) -> Symbol {
         use PrimitiveType::*;
         match self {
index 2c31a502565aaba84f340e59134d7308ac4164bd..706a56fbcbfe6c7f01961bca88ee2fdfe6126e1d 100644 (file)
@@ -2,7 +2,7 @@
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
-    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -451,35 +451,48 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
     auto_impls.into_iter().chain(blanket_impls)
 }
 
+/// If `res` has a documentation page associated, store it in the cache.
+///
+/// This is later used by [`href()`] to determine the HTML link for the item.
+///
+/// [`href()`]: crate::html::format::href
 crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
+    use DefKind::*;
     debug!("register_res({:?})", res);
 
     let (did, kind) = match res {
-        Res::Def(DefKind::Fn, i) => (i, ItemType::Function),
-        Res::Def(DefKind::TyAlias, i) => (i, ItemType::Typedef),
-        Res::Def(DefKind::Enum, i) => (i, ItemType::Enum),
-        Res::Def(DefKind::Trait, i) => (i, ItemType::Trait),
         Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => {
+            // associated items are documented, but on the page of their parent
             (cx.tcx.parent(i).unwrap(), ItemType::Trait)
         }
-        Res::Def(DefKind::Struct, i) => (i, ItemType::Struct),
-        Res::Def(DefKind::Union, i) => (i, ItemType::Union),
-        Res::Def(DefKind::Mod, i) => (i, ItemType::Module),
-        Res::Def(DefKind::ForeignTy, i) => (i, ItemType::ForeignType),
-        Res::Def(DefKind::Const, i) => (i, ItemType::Constant),
-        Res::Def(DefKind::Static, i) => (i, ItemType::Static),
         Res::Def(DefKind::Variant, i) => {
+            // variant items are documented, but on the page of their parent
             (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum)
         }
-        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
-            MacroKind::Bang => (i, ItemType::Macro),
-            MacroKind::Attr => (i, ItemType::ProcAttribute),
-            MacroKind::Derive => (i, ItemType::ProcDerive),
-        },
-        Res::Def(DefKind::TraitAlias, i) => (i, ItemType::TraitAlias),
-        Res::SelfTy(Some(def_id), _) => (def_id, ItemType::Trait),
-        Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id,
-        _ => return res.def_id(),
+        // Each of these have their own page.
+        Res::Def(
+            kind
+            @
+            (Fn | TyAlias | Enum | Trait | Struct | Union | Mod | ForeignTy | Const | Static
+            | Macro(..) | TraitAlias),
+            i,
+        ) => (i, kind.into()),
+        // This is part of a trait definition; document the trait.
+        Res::SelfTy(Some(trait_def_id), _) => (trait_def_id, ItemType::Trait),
+        // This is an inherent impl; it doesn't have its own page.
+        Res::SelfTy(None, Some((impl_def_id, _))) => return impl_def_id,
+        Res::SelfTy(None, None)
+        | Res::PrimTy(_)
+        | Res::ToolMod
+        | Res::SelfCtor(_)
+        | Res::Local(_)
+        | Res::NonMacroAttr(_)
+        | Res::Err => return res.def_id(),
+        Res::Def(
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
+            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            id,
+        ) => return id,
     };
     if did.is_local() {
         return did;
@@ -543,3 +556,9 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
             && attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag))
     })
 }
+
+/// A link to `doc.rust-lang.org` that includes the channel name. Use this instead of manual links
+/// so that the channel is consistent.
+///
+/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
+crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
index 90b3733821622a9f249d6bb9402325dd51e7fcef..1b5a00dde59bce80aeac714e5c982662e96a13c4 100644 (file)
@@ -628,7 +628,8 @@ fn println_condition(condition: Condition) {
         let generate_redirect_map = matches.opt_present("generate-redirect-map");
         let show_type_layout = matches.opt_present("show-type-layout");
 
-        let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
+        let (lint_opts, describe_lints, lint_cap, _) =
+            get_cmd_lint_options(matches, error_format, &debugging_opts);
 
         Ok(Options {
             input,
index 3dd13a8f17072940d1812cd71038339a69c31b55..c3d9c4ea7f25ae6a84d20fe1695033830311c79d 100644 (file)
@@ -217,8 +217,9 @@ impl<'tcx> DocContext<'tcx> {
     // By default, rustdoc ignores all lints.
     // Specifically unblock lints relevant to documentation or the lint machinery itself.
     let mut lints_to_show = vec![
-        // it's unclear whether this should be part of rustdoc directly (#77364)
+        // it's unclear whether these should be part of rustdoc directly (#77364)
         rustc_lint::builtin::MISSING_DOCS.name.to_string(),
+        rustc_lint::builtin::INVALID_DOC_ATTRIBUTES.name.to_string(),
         // these are definitely not part of rustdoc, but we want to warn on them anyway.
         rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
         rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
@@ -399,15 +400,18 @@ impl<'tcx> DocContext<'tcx> {
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
     if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
-        let help = "The following guide may be of use:\n\
-                https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
+        let help = format!(
+            "The following guide may be of use:\n\
+            {}/rustdoc/how-to-write-documentation.html",
+            crate::DOC_RUST_LANG_ORG_CHANNEL
+        );
         tcx.struct_lint_node(
             crate::lint::MISSING_CRATE_LEVEL_DOCS,
             DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
             |lint| {
                 let mut diag =
                     lint.build("no documentation found for this crate's top-level module");
-                diag.help(help);
+                diag.help(&help);
                 diag.emit();
             },
         );
index 3a4d39e1d7f72c9662be328a89fa00b6ffecbcdd..88e2f6048e9c700d3d66088bd7b183540b63d98d 100644 (file)
@@ -880,6 +880,7 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) {
         let target = self.options.target.clone();
         let target_str = target.to_string();
         let unused_externs = self.unused_extern_reports.clone();
+        let no_run = config.no_run || options.no_run;
         if !config.compile_fail {
             self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
         }
@@ -941,13 +942,16 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) {
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
                 allow_fail: config.allow_fail,
+                #[cfg(not(bootstrap))]
+                compile_fail: config.compile_fail,
+                #[cfg(not(bootstrap))]
+                no_run,
                 test_type: testing::TestType::DocTest,
             },
             testfn: testing::DynTestFn(box move || {
                 let report_unused_externs = |uext| {
                     unused_externs.lock().unwrap().push(uext);
                 };
-                let no_run = config.no_run || options.no_run;
                 let res = run_test(
                     &test,
                     &cratename,
index 3c1d03a78f1cd86d5f7ed0b8ed64e179523f6902..d5213fd77117a00655ab27ee796fa826f9320340 100644 (file)
@@ -574,7 +574,7 @@ fn primitive_link(
                     f,
                     "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
                     "../".repeat(len),
-                    prim.to_url_str()
+                    prim.as_sym()
                 )?;
                 needs_termination = true;
             }
@@ -603,7 +603,7 @@ fn primitive_link(
                         f,
                         "<a class=\"primitive\" href=\"{}/primitive.{}.html\">",
                         loc.join("/"),
-                        prim.to_url_str()
+                        prim.as_sym()
                     )?;
                     needs_termination = true;
                 }
@@ -677,7 +677,7 @@ fn fmt_type<'cx>(
             fmt::Display::fmt(&tybounds(param_names, cx), f)
         }
         clean::Infer => write!(f, "_"),
-        clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cx),
+        clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
         clean::BareFunction(ref decl) => {
             if f.alternate() {
                 write!(
index 429863f3635a8b55838ebf360adada4734d24591..d2d1757b9009ada499bcbb2bf75b9ee23b9f6bbe 100644 (file)
@@ -87,7 +87,7 @@ impl<'a> Page<'a> {
         {sidebar}\
     </nav>\
     <div class=\"theme-picker\">\
-        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
+        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\" title=\"themes\">\
             <img src=\"{static_root_path}brush{suffix}.svg\" \
                  width=\"18\" height=\"18\" \
                  alt=\"Pick another theme!\">\
@@ -105,8 +105,8 @@ impl<'a> Page<'a> {
                            placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                            type=\"search\">\
                 </div>\
-                <button type=\"button\" id=\"help-button\">?</button>
-                <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
+                <button type=\"button\" id=\"help-button\" title=\"help\">?</button>\
+                <a id=\"settings-menu\" href=\"{root_path}settings.html\" title=\"settings\">\
                     <img src=\"{static_root_path}wheel{suffix}.svg\" \
                          width=\"18\" height=\"18\" \
                          alt=\"Change settings\">\
@@ -161,7 +161,7 @@ impl<'a> Page<'a> {
             }
         },
         title = page.title,
-        description = page.description,
+        description = Escape(page.description),
         keywords = page.keywords,
         favicon = if layout.favicon.is_empty() {
             format!(
index 10f5184e39a676e6a3420fef07a147c89cd21aae..4b6faefc2fb076b7e58aca765045f333bc2876d2 100644 (file)
@@ -322,7 +322,13 @@ fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str, class: &
             if !e.is_empty() {
                 let mut e: Vec<&ItemEntry> = e.iter().collect();
                 e.sort();
-                write!(f, "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">", title, title, class);
+                write!(
+                    f,
+                    "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">",
+                    title.replace(' ', "-"), // IDs cannot contain whitespaces.
+                    title,
+                    class
+                );
 
                 for s in e.iter() {
                     write!(f, "<li>{}</li>", s.print());
@@ -346,7 +352,7 @@ fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str, class: &
              </h1>",
         );
         // Note: print_entries does not escape the title, because we know the current set of titles
-        // don't require escaping.
+        // doesn't require escaping.
         print_entries(f, &self.structs, "Structs", "structs");
         print_entries(f, &self.enums, "Enums", "enums");
         print_entries(f, &self.unions, "Unions", "unions");
index 1c5d9a26441f459bfe41c1d236e7ea70711ca3b8..04464b622d7a39d6273e8800ac2e116fa0a148a7 100644 (file)
@@ -78,7 +78,7 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
     write!(buf, "<a class=\"{}\" href=\"#\">{}</a>", item.type_(), item.name.as_ref().unwrap());
     write!(
         buf,
-        "<button id=\"copy-path\" onclick=\"copy_path(this)\">\
+        "<button id=\"copy-path\" onclick=\"copy_path(this)\" title=\"copy path\">\
             <img src=\"{static_root_path}clipboard{suffix}.svg\" \
                 width=\"19\" height=\"18\" \
                 alt=\"Copy item import\" \
index d3f8a7aa67dd731ebe921dd10d39f7262ea1edf9..578e8ce5acbefd1bd9c6c8e05edfbce8e1587300 100644 (file)
@@ -800,6 +800,8 @@ a {
 
 .search-results .result-name > span {
        display: inline-block;
+       margin: 0;
+       font-weight: normal;
 }
 
 body.blur > :not(#help) {
index c6646ba9ae4d2bc52faeb7cfe4681640ee5b4e7a..bee62915ea9b1f841cb2d9122f4db46d42706df6 100644 (file)
@@ -379,7 +379,7 @@ fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
                     .unwrap_or_default(),
             },
             Generic(s) => Type::Generic(s.to_string()),
-            Primitive(p) => Type::Primitive(p.as_str().to_string()),
+            Primitive(p) => Type::Primitive(p.as_sym().to_string()),
             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
             Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
             Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
index bf0be62635630d99dd8a4fcb47e3a0866b029b1f..ee7a716655bd2d7b1d2bc98df19e5a631e24e788 100644 (file)
@@ -81,6 +81,8 @@
 use rustc_session::getopts;
 use rustc_session::{early_error, early_warn};
 
+use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL;
+
 /// A macro to create a FxHashMap.
 ///
 /// Example:
@@ -510,6 +512,14 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
+        unstable("force-warns", |o| {
+            o.optopt(
+                "",
+                "force-warns",
+                "Lints that will warn even if allowed somewhere else",
+                "LINTS",
+            )
+        }),
         unstable("index-page", |o| {
             o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
         }),
@@ -603,7 +613,10 @@ fn usage(argv0: &str) {
     }
     println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
     println!("    @path               Read newline separated options from `path`\n");
-    println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
+    println!(
+        "More information available at {}/rustdoc/what-is-rustdoc.html",
+        DOC_RUST_LANG_ORG_CHANNEL
+    );
 }
 
 /// A result type used by several functions under `main()`.
index 81c90f4eaa75b3c0cb846e17710b79d0600486ee..247a020f2a20d28f3ccba04026e310384e5a774e 100644 (file)
@@ -91,10 +91,10 @@ fn article(self) -> &'static str {
         }
     }
 
-    fn name(self, tcx: TyCtxt<'_>) -> String {
+    fn name(self, tcx: TyCtxt<'_>) -> Symbol {
         match self {
-            Res::Def(_, id) => tcx.item_name(id).to_string(),
-            Res::Primitive(prim) => prim.as_str().to_string(),
+            Res::Def(_, id) => tcx.item_name(id),
+            Res::Primitive(prim) => prim.as_sym(),
         }
     }
 
@@ -388,7 +388,7 @@ fn resolve_primitive_associated_item(
                         ty::AssocKind::Const => "associatedconstant",
                         ty::AssocKind::Type => "associatedtype",
                     };
-                    let fragment = format!("{}#{}.{}", prim_ty.as_str(), out, item_name);
+                    let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
                     (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
                 })
         })
@@ -481,7 +481,7 @@ fn resolve<'path>(
                             AnchorFailure::RustdocAnchorConflict(res),
                         ));
                     }
-                    return Ok((res, Some(ty.as_str().to_owned())));
+                    return Ok((res, Some(ty.as_sym().to_string())));
                 }
                 _ => return Ok((res, extra_fragment.clone())),
             }
@@ -1148,7 +1148,7 @@ fn resolve_link(
                         return None;
                     }
                     res = prim;
-                    fragment = Some(prim.name(self.cx.tcx));
+                    fragment = Some(prim.name(self.cx.tcx).to_string());
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
@@ -1999,8 +1999,11 @@ fn disambiguator_error(
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
-        let msg = "see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators";
-        diag.note(msg);
+        let msg = format!(
+            "see {}/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
+            crate::DOC_RUST_LANG_ORG_CHANNEL
+        );
+        diag.note(&msg);
     });
 }
 
index 5f67a5715771b7d29e4713e8d68338602d216dcf..39c5555872cc5d379cc3535a31dc0cdac969466f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5f67a5715771b7d29e4713e8d68338602d216dcf
+Subproject commit 39c5555872cc5d379cc3535a31dc0cdac969466f
diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs
new file mode 100644 (file)
index 0000000..cc3863d
--- /dev/null
@@ -0,0 +1,154 @@
+// min-llvm-version: 10.0.1
+// assembly-output: emit-asm
+// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
+// needs-llvm-components: bpf
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const u64;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("{} = {}", out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+extern "C" {
+    fn extern_func();
+}
+
+// CHECK-LABEL: sym_fn
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16 i16 reg);
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32 i32 reg);
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64 i64 reg);
+
+// CHECK-LABEL: wreg_i8:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i8 i8 wreg);
+
+// CHECK-LABEL: wreg_i16:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i16 i16 wreg);
+
+// CHECK-LABEL: wreg_i32:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i32 i32 wreg);
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i8 i8 "r0");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i16 i16 "r0");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i32 i32 "r0");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i64 i64 "r0");
+
+// CHECK-LABEL: w0_i8:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i8 i8 "w0");
+
+// CHECK-LABEL: w0_i16:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i16 i16 "w0");
+
+// CHECK-LABEL: w0_i32:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i32 i32 "w0");
diff --git a/src/test/codegen/bpf-alu32.rs b/src/test/codegen/bpf-alu32.rs
new file mode 100644 (file)
index 0000000..c68bffd
--- /dev/null
@@ -0,0 +1,11 @@
+// only-bpf
+#![crate_type = "lib"]
+#![feature(bpf_target_feature)]
+#![no_std]
+
+#[no_mangle]
+#[target_feature(enable = "alu32")]
+// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0 {
+pub unsafe fn foo(arg: u8) -> u8 {
+    arg
+}
index 8bb5dbc48feefa955bf205eafb431c4404bfaa17..2566d745ecd060d128de11ea32f6fa3335caf9e0 100644 (file)
@@ -30,7 +30,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 +                                          // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
index 54f1200a21fe110c379d3bcc71996ce9da302e40..093e228a0ce44a57fc8d56f5441d2e16b8533edb 100644 (file)
@@ -32,7 +32,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 +                                          // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
index db6e1369161fb37d03a8fef90d6da5c5587b955c..0517e7fac40e26eb6a7dd42991b30f8b3c222be6 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index db6e1369161fb37d03a8fef90d6da5c5587b955c..0517e7fac40e26eb6a7dd42991b30f8b3c222be6 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index d7bc035e667afdb2ae7fba27c04147c02b33883d..28c80b346e76048b60ddf5a83a2dc34047b065a4 100644 (file)
@@ -22,7 +22,7 @@
                                            // + val: Unevaluated(FOO, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
           _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
index 4e19465189c933ec742b116bc3ef9196ce8c66b5..ae77443e019d5fff416415cb8e7868133565a514 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 +         _1 = const 4_i32;                // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
index a58dabdaa4159cd9192750930507461858e7398e..402a28f3f9f40d5241ea0ca7d9d6b69fb386ea0c 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
-+                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
index bb265b2af7d30150fe9245400ab6917af9941d6c..b97d7d1be1596f381dbaab32ada65822a81df045 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
           StorageDead(_2);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index bb7570fabbba8e02c0ac6cc37472f13b60d346df..48ede27112c9243df0935409ada9f6e99ce275d4 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index d5a36182e35017536045d3efd24fc1c23081c8ca..27791852d6dac9fee00a810914597fc43663c732 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index d5a36182e35017536045d3efd24fc1c23081c8ca..27791852d6dac9fee00a810914597fc43663c732 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index 5ceefce6114f0410a39fb9e0b2bbb24b8421fcfe..1aabee83be6842dbb651797a2c773b8cf98870a3 100644 (file)
@@ -38,7 +38,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
         Retag(_10);                      // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         Retag(_4);                       // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
@@ -52,7 +52,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_9);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
index e955feb7d1f41fcc9662be0f78863421ec2abe16..95a8ef997fa49f405698ba7e439644fa2badb30f 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index e955feb7d1f41fcc9662be0f78863421ec2abe16..95a8ef997fa49f405698ba7e439644fa2badb30f 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index ff8c410a7268d4e1b289a6c96523d1c8aa5861cb..261eb3b27eafd1982e3db0969577f20173cb0ee9 100644 (file)
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index ff8c410a7268d4e1b289a6c96523d1c8aa5861cb..261eb3b27eafd1982e3db0969577f20173cb0ee9 100644 (file)
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index acb8aca75904b1e9459531f0597c9832e03eb587..a37df4da9ae40561396268af1f3c55597ab46f3a 100644 (file)
@@ -50,7 +50,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[2]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
@@ -74,7 +74,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
-                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
@@ -98,7 +98,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
-                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
index c27ee528b80b7e457abd99aa28978ae2070cc49e..5af242376c9304066de78725f9c5cfb9acd0d119 100644 (file)
@@ -57,7 +57,7 @@ fn full_tested_match() -> () {
                                          // + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
-                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
index 787310d072a9b72c2439d14ebca60eea750f4d03..c6ef403c3c130297d3f4835d13512d09c880e5d4 100644 (file)
@@ -127,7 +127,7 @@ fn array_casts() -> () {
                                          // + val: Unevaluated(array_casts, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 8abc6a3e4b515d7127e0f9306f180f893aff0b52..4bab5a974881a6b4f05cd6f7490c26092bd19907 100644 (file)
@@ -113,7 +113,7 @@ fn main() -> () {
         StorageLive(_14);                // scope 1 at $DIR/retag.rs:40:31: 43:6
         _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:40:31: 43:6
                                          // closure
-                                         // + def_id: DefId(0:14 ~ retag[13e7]::main::{closure#0})
+                                         // + def_id: DefId(0:14 ~ retag[317d]::main::{closure#0})
                                          // + substs: [
                                          //     i8,
                                          //     for<'r> extern "rust-call" fn((&'r i32,)) -> &'r i32,
@@ -153,7 +153,7 @@ fn main() -> () {
                                          // + val: Unevaluated(main, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
index 322f5681b3fd9278243359047748a891ca46fe21..dc06a485a8fc124bd26a7779b81c9bd0ebd1dbef 100644 (file)
@@ -12,6 +12,7 @@
    12|      1|    if b {
    13|      1|        println!("non_async_func println in block");
    14|      1|    }
+                   ^0
    15|      1|}
    16|       |
    17|       |
index 656a26597759d337bac841ad5a4bfa956cac3a9b..2d8a98a5d0c92f6a19ebc1c7b3fa63a63515f57c 100644 (file)
@@ -5,6 +5,7 @@
     5|      1|    if true {
     6|      1|        countdown = 10;
     7|      1|    }
+                   ^0
     8|       |
     9|       |    const B: u32 = 100;
    10|      1|    let x = if countdown > 7 {
@@ -24,6 +25,7 @@
    24|      1|    if true {
    25|      1|        countdown = 10;
    26|      1|    }
+                   ^0
    27|       |
    28|      1|    if countdown > 7 {
    29|      1|        countdown -= 4;
@@ -42,6 +44,7 @@
    41|      1|        if true {
    42|      1|            countdown = 10;
    43|      1|        }
+                       ^0
    44|       |
    45|      1|        if countdown > 7 {
    46|      1|            countdown -= 4;
    53|       |        } else {
    54|      0|            return;
    55|       |        }
-   56|       |    } // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
-   57|       |      // `true` was const-evaluated. The compiler knows the `if` block will be executed.
+   56|      0|    }
+   57|       |
    58|       |
    59|      1|    let mut countdown = 0;
    60|      1|    if true {
    61|      1|        countdown = 1;
    62|      1|    }
+                   ^0
    63|       |
    64|      1|    let z = if countdown > 7 {
                       ^0
index 1b6bb9ff8891de6c5ad657868580e8d31afe28ff..7ae0e978808e7e7c717422a44ed141ae1e43b37d 100644 (file)
@@ -9,7 +9,7 @@
     8|      1|//!     assert_eq!(1, 1);
     9|       |//! } else {
    10|       |//!     // this is not!
-   11|       |//!     assert_eq!(1, 2);
+   11|      0|//!     assert_eq!(1, 2);
    12|       |//! }
    13|      1|//! ```
    14|       |//!
@@ -84,7 +84,7 @@
    74|      1|    if true {
    75|      1|        assert_eq!(1, 1);
    76|       |    } else {
-   77|       |        assert_eq!(1, 2);
+   77|      0|        assert_eq!(1, 2);
    78|       |    }
    79|      1|}
    80|       |
index fab5be41901c9b544ba12e3379b30cb96d331177..fe6a9e93cbf710ab516bdc1e2b283ed7ffae99eb 100644 (file)
    19|      1|    if true {
    20|      1|        println!("Exiting with error...");
    21|      1|        return Err(1);
-   22|       |    }
-   23|       |
-   24|       |    let _ = Firework { strength: 1000 };
-   25|       |
-   26|       |    Ok(())
+   22|      0|    }
+   23|      0|
+   24|      0|    let _ = Firework { strength: 1000 };
+   25|      0|
+   26|      0|    Ok(())
    27|      1|}
    28|       |
    29|       |// Expected program output:
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt
new file mode 100644 (file)
index 0000000..0fb3808
--- /dev/null
@@ -0,0 +1,32 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |
+    3|       |use std::ops::{Generator, GeneratorState};
+    4|       |use std::pin::Pin;
+    5|       |
+    6|       |// The following implementation of a function called from a `yield` statement
+    7|       |// (apparently requiring the Result and the `String` type or constructor)
+    8|       |// creates conditions where the `generator::StateTransform` MIR transform will
+    9|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+   10|       |// to handle this condition, and still report dead block coverage.
+   11|      1|fn get_u32(val: bool) -> Result<u32, String> {
+   12|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
+                                          ^0
+   13|      1|}
+   14|       |
+   15|      1|fn main() {
+   16|      1|    let is_true = std::env::args().len() == 1;
+   17|      1|    let mut generator = || {
+   18|      1|        yield get_u32(is_true);
+   19|      1|        return "foo";
+   20|      1|    };
+   21|       |
+   22|      1|    match Pin::new(&mut generator).resume(()) {
+   23|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   24|      0|        _ => panic!("unexpected return from resume"),
+   25|       |    }
+   26|      1|    match Pin::new(&mut generator).resume(()) {
+   27|      1|        GeneratorState::Complete("foo") => {}
+   28|      0|        _ => panic!("unexpected return from resume"),
+   29|       |    }
+   30|      1|}
+
index be0dbf71607f57ee8436e150b123c3f43335a939..8569513e8425b19704879c584298ca63fe5332df 100644 (file)
    30|      1|    if true {
    31|      1|        println!("Exiting with error...");
    32|      1|        return Err(1);
-   33|       |    } // The remaining lines below have no coverage because `if true` (with the constant literal
-   34|       |      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
-   35|       |      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
-   36|       |      // in other tests, the lines below would have coverage (which would show they had `0`
-   37|       |      // executions, assuming the condition still evaluated to `true`).
-   38|       |
-   39|       |    let _ = Firework { strength: 1000 };
-   40|       |
-   41|       |    Ok(())
+   33|      0|    }
+   34|      0|
+   35|      0|
+   36|      0|
+   37|      0|
+   38|      0|
+   39|      0|    let _ = Firework { strength: 1000 };
+   40|      0|
+   41|      0|    Ok(())
    42|      1|}
    43|       |
    44|       |// Expected program output:
index 81d5c7d90346d08a397e577d120352dbe465f124..5d572db7cc60da3b6b90c2a9dd799c7eda9143ed 100644 (file)
@@ -9,23 +9,23 @@
     9|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    10|      1|        if true {
    11|      1|            if false {
-   12|       |                while true {
-   13|       |                }
+   12|      0|                while true {
+   13|      0|                }
    14|      1|            }
-   15|      1|            write!(f, "error")?;
-                                            ^0
-   16|       |        } else {
-   17|       |        }
+   15|      1|            write!(f, "cool")?;
+                                           ^0
+   16|      0|        } else {
+   17|      0|        }
    18|       |
    19|     10|        for i in 0..10 {
    20|     10|            if true {
    21|     10|                if false {
-   22|       |                    while true {}
+   22|      0|                    while true {}
    23|     10|                }
-   24|     10|                write!(f, "error")?;
-                                                ^0
-   25|       |            } else {
-   26|       |            }
+   24|     10|                write!(f, "cool")?;
+                                               ^0
+   25|      0|            } else {
+   26|      0|            }
    27|       |        }
    28|      1|        Ok(())
    29|      1|    }
    34|       |impl std::fmt::Display for DisplayTest {
    35|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    36|      1|        if false {
-   37|       |        } else {
+   37|      0|        } else {
    38|      1|            if false {
-   39|       |                while true {}
+   39|      0|                while true {}
    40|      1|            }
-   41|      1|            write!(f, "error")?;
-                                            ^0
+   41|      1|            write!(f, "cool")?;
+                                           ^0
    42|       |        }
    43|     10|        for i in 0..10 {
    44|     10|            if false {
-   45|       |            } else {
+   45|      0|            } else {
    46|     10|                if false {
-   47|       |                    while true {}
+   47|      0|                    while true {}
    48|     10|                }
-   49|     10|                write!(f, "error")?;
-                                                ^0
+   49|     10|                write!(f, "cool")?;
+                                               ^0
    50|       |            }
    51|       |        }
    52|      1|        Ok(())
index 5adeef7d0850b462b369da348651e695db38307b..2d4c57f451a2de3871bb0223d6cfbd72b71d2dac 100644 (file)
@@ -1,6 +1,6 @@
     1|      1|fn main() {
     2|      1|    if false {
-    3|       |        loop {}
+    3|      0|        loop {}
     4|      1|    }
     5|      1|}
 
index 8a2a0b53e5862f3031364e1e340834aedfbefda8..057599d1b471ab2e12a63f6a4a0b5b2fc9a3f654 100644 (file)
@@ -53,8 +53,8 @@ fn main() {
         } else {
             return;
         }
-    } // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
-      // `true` was const-evaluated. The compiler knows the `if` block will be executed.
+    }
+
 
     let mut countdown = 0;
     if true {
diff --git a/src/test/run-make-fulldeps/coverage/generator.rs b/src/test/run-make-fulldeps/coverage/generator.rs
new file mode 100644 (file)
index 0000000..4319991
--- /dev/null
@@ -0,0 +1,30 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+// The following implementation of a function called from a `yield` statement
+// (apparently requiring the Result and the `String` type or constructor)
+// creates conditions where the `generator::StateTransform` MIR transform will
+// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+// to handle this condition, and still report dead block coverage.
+fn get_u32(val: bool) -> Result<u32, String> {
+    if val { Ok(1) } else { Err(String::from("some error")) }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut generator = || {
+        yield get_u32(is_true);
+        return "foo";
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(Ok(1)) => {}
+        _ => panic!("unexpected return from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected return from resume"),
+    }
+}
index cbeda35d3b8cfe8a5b226f769282d568f9689012..18b38868496d4bc10a699e6fe68035adaf2690e2 100644 (file)
@@ -30,11 +30,11 @@ fn main() -> Result<(),u8> {
     if true {
         println!("Exiting with error...");
         return Err(1);
-    } // The remaining lines below have no coverage because `if true` (with the constant literal
-      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
-      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
-      // in other tests, the lines below would have coverage (which would show they had `0`
-      // executions, assuming the condition still evaluated to `true`).
+    }
+
+
+
+
 
     let _ = Firework { strength: 1000 };
 
index 4d9bbad3367f6ef50c9d072327ab996ec5d62cb9..7116ce47f4b9dcdf28bbd8fd161509f0e74faa6a 100644 (file)
@@ -12,7 +12,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                 while true {
                 }
             }
-            write!(f, "error")?;
+            write!(f, "cool")?;
         } else {
         }
 
@@ -21,7 +21,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                 if false {
                     while true {}
                 }
-                write!(f, "error")?;
+                write!(f, "cool")?;
             } else {
             }
         }
@@ -38,7 +38,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
             if false {
                 while true {}
             }
-            write!(f, "error")?;
+            write!(f, "cool")?;
         }
         for i in 0..10 {
             if false {
@@ -46,7 +46,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                 if false {
                     while true {}
                 }
-                write!(f, "error")?;
+                write!(f, "cool")?;
             }
         }
         Ok(())
index a9e99d3c10ecc6b0614e4a5b6d5dad90f0dcc358..443e2df357fb408fc30a30293718ffb2764ecff3 100644 (file)
@@ -1,4 +1,5 @@
 #![feature(rustc_private)]
+#![deny(warnings)]
 
 extern crate rustc_codegen_ssa;
 extern crate rustc_errors;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::{CodegenResults, CrateInfo};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::ErrorReported;
-use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::OutputFilenames;
 use rustc_session::Session;
-use rustc_target::spec::Target;
 use std::any::Any;
-use std::path::Path;
 
 struct TheBackend;
 
 impl CodegenBackend for TheBackend {
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, providers: &mut Providers) {}
-    fn provide_extern(&self, providers: &mut Providers) {}
-
     fn codegen_crate<'a, 'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
         metadata: EncodedMetadata,
         _need_metadata_module: bool,
     ) -> Box<dyn Any> {
-        use rustc_hir::def_id::LOCAL_CRATE;
-
         Box::new(CodegenResults {
-            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules: vec![],
             allocator_module: None,
             metadata_module: None,
             metadata,
-            windows_subsystem: None,
             linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()),
             crate_info: CrateInfo::new(tcx),
         })
@@ -77,7 +62,7 @@ fn link(
     ) -> Result<(), ErrorReported> {
         use rustc_session::{config::CrateType, output::out_filename};
         use std::io::Write;
-        let crate_name = codegen_results.crate_name;
+        let crate_name = codegen_results.crate_info.local_crate_name;
         for &crate_type in sess.opts.crate_types.iter() {
             if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
index 00ad0eb8d5072f770ff5ed8db812f5d5c62758bc..2fd55699d44ddce99163b985a1f73468190ba115 100644 (file)
@@ -1,6 +1,4 @@
-#![feature(external_doc)]
-
-#[doc(include="input.md")]
+#[doc = include_str!("input.md")]
 pub struct SomeStruct;
 
 pub fn main() {
index 483eeed0b39f0507eea36248a07d7ac5aadc1c4d..dd70675032f77748e56dab0617dcaa42b301677a 100644 (file)
@@ -2,7 +2,6 @@
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 #![feature(associated_type_defaults)]
-#![feature(external_doc)]
 
 extern crate rustc_graphviz;
 // A simple rust project
@@ -454,9 +453,9 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
+#[doc = include_str!("extra-docs.md")]
+struct StructWithDocs;
+
 trait Foo {
     type Bar = FrameBuffer;
 }
-
-#[doc(include = "extra-docs.md")]
-struct StructWithDocs;
diff --git a/src/test/run-make/raw-dylib/Makefile b/src/test/run-make/raw-dylib/Makefile
new file mode 100644 (file)
index 0000000..7ce46fd
--- /dev/null
@@ -0,0 +1,21 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows
+# only-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+       $(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+       $(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
+       $(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+       $(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+       $(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+       "$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/output.txt output.txt
+else
+       $(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib/driver.rs b/src/test/run-make/raw-dylib/driver.rs
new file mode 100644 (file)
index 0000000..4059ede
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib/extern_1.c b/src/test/run-make/raw-dylib/extern_1.c
new file mode 100644 (file)
index 0000000..72737c0
--- /dev/null
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2; didn't get the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+    printf("extern_fn_with_long_name; got the rename\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib/extern_2.c b/src/test/run-make/raw-dylib/extern_2.c
new file mode 100644 (file)
index 0000000..ae87fc3
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+    printf("extern_fn_3\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib/lib.rs b/src/test/run-make/raw-dylib/lib.rs
new file mode 100644 (file)
index 0000000..d8e6301
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+    fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_3();
+}
+
+pub fn library_function() {
+    #[link(name = "extern_1", kind = "raw-dylib")]
+    extern { fn extern_fn_2(); }
+
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+        extern_fn_3();
+    }
+}
diff --git a/src/test/run-make/raw-dylib/output.txt b/src/test/run-make/raw-dylib/output.txt
new file mode 100644 (file)
index 0000000..7800cba
--- /dev/null
@@ -0,0 +1,3 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
index b8769d5f6905178c2aab86e27a20ef053a158ee2..aa20d6aa4bf27b35accfeaed036ec6f0ebd77d1d 100644 (file)
@@ -2,3 +2,4 @@
 
 all:
        $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
+       $(RUSTC) --force-warns dead_code x.rs 2>&1 | diff - force-warns.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warns.stderr b/src/test/run-make/unstable-flag-required/force-warns.stderr
new file mode 100644 (file)
index 0000000..e093619
--- /dev/null
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warns=lints`
+
index 65a56e03d9dfcf4c1c36261525d7ed7aa12e2dd8..2b44ba24b4426d1847c88a7dac371af58b8c2427 100644 (file)
@@ -1,5 +1,6 @@
 // check-pass
 // compile-flags: -Z unstable-options --check
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 
 #![warn(missing_docs)]
 //~^ WARN
index 2e1fc1eca4d6e7e9c0e400249d1fa1130f407915..8c9e70e57fe7b09a68aee20468b181b779d60aed 100644 (file)
@@ -1,5 +1,5 @@
 warning: missing documentation for the crate
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -10,13 +10,13 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:4:9
+  --> $DIR/check.rs:5:9
    |
 LL | #![warn(missing_docs)]
    |         ^^^^^^^^^^^^
 
 warning: missing documentation for a function
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^
@@ -24,16 +24,16 @@ LL | pub fn foo() {}
 warning: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -44,14 +44,14 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.rs b/src/test/rustdoc-ui/doc-include-suggestion.rs
new file mode 100644 (file)
index 0000000..0c01007
--- /dev/null
@@ -0,0 +1,10 @@
+// check-pass
+
+#[doc(include = "external-cross-doc.md")]
+//~^ WARNING unknown `doc` attribute `include`
+//~| HELP use `doc = include_str!` instead
+// FIXME(#85497): make this a deny instead so it's more clear what's happening
+//~| NOTE on by default
+//~| WARNING previously accepted
+//~| NOTE see issue #82730
+pub struct NeedMoreDocs;
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.stderr b/src/test/rustdoc-ui/doc-include-suggestion.stderr
new file mode 100644 (file)
index 0000000..870b7ef
--- /dev/null
@@ -0,0 +1,12 @@
+warning: unknown `doc` attribute `include`
+  --> $DIR/doc-include-suggestion.rs:3:7
+   |
+LL | #[doc(include = "external-cross-doc.md")]
+   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
+   |
+   = note: `#[warn(invalid_doc_attributes)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+warning: 1 warning emitted
+
index 94b69a99879c073ac12dd0d53fd6359bc5cbdb73..4b58778eacd17605e54d0ce7f062c620556f3f9a 100644 (file)
@@ -1,9 +1,8 @@
-// check-pass
 // run-rustfix
-
+#![deny(warnings)]
 #![feature(doc_notable_trait)]
 
 #[doc(notable_trait)]
-//~^ WARN unknown `doc` attribute `spotlight`
+//~^ ERROR unknown `doc` attribute `spotlight`
 //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 trait MyTrait {}
index cc5f159a8093e9c64923cbb89c3cb4614c27ddd5..16e387245802b128364f52c61b7091844c823e30 100644 (file)
@@ -1,9 +1,8 @@
-// check-pass
 // run-rustfix
-
+#![deny(warnings)]
 #![feature(doc_notable_trait)]
 
 #[doc(spotlight)]
-//~^ WARN unknown `doc` attribute `spotlight`
+//~^ ERROR unknown `doc` attribute `spotlight`
 //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 trait MyTrait {}
index e5fa6293f3d8d6bb976b54967fe307f65d14707f..8e7831139a86058f75e249c1215c3968ac5515b8 100644 (file)
@@ -1,14 +1,19 @@
-warning: unknown `doc` attribute `spotlight`
-  --> $DIR/doc-spotlight.rs:6:7
+error: unknown `doc` attribute `spotlight`
+  --> $DIR/doc-spotlight.rs:5:7
    |
 LL | #[doc(spotlight)]
    |       ^^^^^^^^^ help: use `notable_trait` instead
    |
-   = note: `#[warn(invalid_doc_attributes)]` on by default
+note: the lint level is defined here
+  --> $DIR/doc-spotlight.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
    = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
    = note: `doc(spotlight)` is now a no-op
 
-warning: 1 warning emitted
+error: aborting due to previous error
 
index b8bb5ccb403299f428dbd931c1138b6d9c02792b..af3a90a74100f9bde4126829ae5524403552c864 100644 (file)
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) ... FAILED
+test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) - compile fail ... FAILED
 
 failures:
 
index 7367a7d651919e010b38b9f02bb234a1c6711b66..bacbb47b5f9ff4ad28b94258e85b953376413889 100644 (file)
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) ... FAILED
+test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) - compile fail ... FAILED
 
 failures:
 
index 417618c74582cda0c897cf8a7658eb6e0f1ef3b0..9465e8e7ab99649bfff1c0a9fe6f64c3f267ca03 100644 (file)
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Email me at <hello@localhost>.
index f287f87408c48f79787c705e4733fa403275392d..1b07828fc6e55e4217022e220646b0d61ef530a9 100644 (file)
@@ -1,16 +1,16 @@
 error: unknown disambiguator `hello`
-  --> $DIR/email-address-localhost.rs:3:18
+  --> $DIR/email-address-localhost.rs:4:18
    |
 LL | //! Email me at <hello@localhost>.
    |                  ^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/email-address-localhost.rs:1:9
+  --> $DIR/email-address-localhost.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to previous error
 
index 925fc515a3e657f31df6f1b662c32dc2dfc57a4d..0aa1e5a415aa747877c425b2ece259a2ecb024da 100644 (file)
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Linking to [foo@banana] and [`bar@banana!()`].
index 94d6d4616518ea7599ef5f7151a2025975a3e0fd..d280e6497e096c163af4d6161262a8ff9d4a328b 100644 (file)
@@ -1,56 +1,56 @@
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:3:17
+  --> $DIR/unknown-disambiguator.rs:4:17
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                 ^^^
    |
 note: the lint level is defined here
-  --> $DIR/unknown-disambiguator.rs:1:9
+  --> $DIR/unknown-disambiguator.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `bar`
-  --> $DIR/unknown-disambiguator.rs:3:35
+  --> $DIR/unknown-disambiguator.rs:4:35
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                                   ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:34
+  --> $DIR/unknown-disambiguator.rs:10:34
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                  ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:48
+  --> $DIR/unknown-disambiguator.rs:10:48
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                                ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:31
+  --> $DIR/unknown-disambiguator.rs:7:31
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                               ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:57
+  --> $DIR/unknown-disambiguator.rs:7:57
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                                                         ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to 6 previous errors
 
index 1dd19f468274c4d162b270545868e292464d2511..d2b1cd1d550cf2a4201be07e5c7aea366073a1ee 100644 (file)
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/issue-80992.rs - test (line 7) ... ok
+test $DIR/issue-80992.rs - test (line 7) - compile fail ... ok
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
index 3939ec6827adea26c8369e901bd356895a326a67..a186410acf483c819cee69576f3e9baeedca1801 100644 (file)
@@ -1,4 +1,5 @@
 // error-pattern: no documentation found
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(rustdoc::missing_crate_level_docs)]
 //^~ NOTE defined here
 
index 55ead1a55cfcd76aabf517a93f55bf56f367268a..1a1f8085a1b467b082b6f0963c48b8c6bc010f9b 100644 (file)
@@ -1,12 +1,12 @@
 error: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/no-crate-level-doc-lint.rs:2:9
+  --> $DIR/no-crate-level-doc-lint.rs:3:9
    |
 LL | #![deny(rustdoc::missing_crate_level_docs)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 error: aborting due to previous error
 
index d92f5da833567fb6f611a8ab9788449ad1024125..02f28aaf60da054a6040cb29927dd9b3ea3af28f 100644 (file)
@@ -1,12 +1,12 @@
 
 running 7 tests
-test $DIR/no-run-flag.rs - f (line 11) ... ok
+test $DIR/no-run-flag.rs - f (line 11) - compile ... ok
 test $DIR/no-run-flag.rs - f (line 14) ... ignored
-test $DIR/no-run-flag.rs - f (line 17) ... ok
-test $DIR/no-run-flag.rs - f (line 23) ... ok
-test $DIR/no-run-flag.rs - f (line 28) ... ok
-test $DIR/no-run-flag.rs - f (line 32) ... ok
-test $DIR/no-run-flag.rs - f (line 8) ... ok
+test $DIR/no-run-flag.rs - f (line 17) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 23) - compile fail ... ok
+test $DIR/no-run-flag.rs - f (line 28) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 32) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 8) - compile ... ok
 
 test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/src/test/rustdoc-ui/test-type.rs b/src/test/rustdoc-ui/test-type.rs
new file mode 100644 (file)
index 0000000..882da5c
--- /dev/null
@@ -0,0 +1,26 @@
+// compile-flags: --test --test-args=--test-threads=1
+// check-pass
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+///     println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-type.stdout b/src/test/rustdoc-ui/test-type.stdout
new file mode 100644 (file)
index 0000000..a66fd24
--- /dev/null
@@ -0,0 +1,10 @@
+
+running 5 tests
+test $DIR/test-type.rs - f (line 12) ... ignored
+test $DIR/test-type.rs - f (line 15) - compile ... ok
+test $DIR/test-type.rs - f (line 21) - compile fail ... ok
+test $DIR/test-type.rs - f (line 6) ... ok
+test $DIR/test-type.rs - f (line 9) ... ok
+
+test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
index 8b4e6edc69997f24261052e124e568267d2cdb20..d3c85326559304fc7eb838eedae9a2f0edbf40d9 100644 (file)
@@ -1,4 +1,4 @@
 # Cross-crate imported docs
 
-This file is to make sure `#[doc(include="file.md")]` works when you re-export an item with included
+This file is to make sure `#[doc = include_str!("file.md")]` works when you re-export an item with included
 docs.
index 473d4ec99f0371fb5f1c8f00d1bebd158c40c726..5de63cdabc6f982cfb6957a5338f9356c40673c6 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(external_doc)]
-#![deny(missing_doc)]
-
-#[doc(include="external-cross-doc.md")]
+#[deny(missing_docs)]
+#[doc = include_str!("external-cross-doc.md")]
 pub struct NeedMoreDocs;
index 38478c1635a178ce40850d5d8f002f2e0a991a80..babde0a05ad2fb558ab315606f2fc28f68bfc737 100644 (file)
@@ -1,3 +1,3 @@
 # External Docs
 
-This file is here to test the `#[doc(include="file")]` attribute.
+This file is here to test the `#[doc = include_str!("file")]` attribute.
index 0dadca551a9ff14a84f851a7de490a9b046d5187..fc29cb252e26c614df56ff48f886d8f265960e89 100644 (file)
@@ -1,12 +1,3 @@
-#![feature(external_doc)]
-
-// @has external_doc/struct.CanHasDocs.html
-// @has - '//h1' 'External Docs'
-// @has - '//h2' 'Inline Docs'
-#[doc(include = "auxiliary/external-doc.md")]
-/// ## Inline Docs
-pub struct CanHasDocs;
-
 // @has external_doc/struct.IncludeStrDocs.html
 // @has - '//h1' 'External Docs'
 // @has - '//h2' 'Inline Docs'
index 2757418bc64e5c4990885be015c95b3813c8771a..d9fed2d69518a11abb41bde4f1fc728cebd3fa61 100644 (file)
@@ -3,9 +3,9 @@
 /// [`std::collections::BTreeMap::into_iter`]
 /// [`String::from`] is ambiguous as to which `From` impl
 /// [Vec::into_iter()] uses a disambiguator
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/struct.String.html#method.from"]' 'String::from'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
 pub fn foo() {}
 
 /// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
index 74216a587e1da6f30129d22bcabc81e3cad1e49f..bbdbe246bbce22f9f4b42ed6c873314e16a0e15a 100644 (file)
@@ -1,3 +1,3 @@
 // @has builtin_macros/index.html
-// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html'
+// @has - '//a/@href' '{{channel}}/core/macro.cfg.html'
 //! [cfg]
diff --git a/src/test/rustdoc/intra-doc/field.rs b/src/test/rustdoc/intra-doc/field.rs
new file mode 100644 (file)
index 0000000..c67c40a
--- /dev/null
@@ -0,0 +1,4 @@
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/ops/range/struct.Range.html#structfield.start"]' 'start'
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
+//! [start][std::ops::Range::start]
+//! [not_found][std::io::ErrorKind::NotFound]
index 1de6410f10c430c2c4520d639349230a7f22112d..fbc9fc6a9bc213d3163d04b7a05217f80259d92d 100644 (file)
@@ -5,40 +5,40 @@
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html"]' 'Vec<T>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html"]' 'Vec<T>'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
+// @has foo/index.html '//a[@href="{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
 
 //! And what about a link to [just `Option`](Option) and, [with the generic, `Option<T>`](Option<T>)?
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'just Option'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option<T>'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'just Option'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'with the generic, Option<T>'
 
 //! We should also try linking to [`Result<T, E>`]; it has *two* generics!
 //! And [`Result<T, !>`] and [`Result<!, E>`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, E>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, !>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<!, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, !>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<!, E>'
 
 //! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
 //! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
 //! And what about something even harder? That would be [`Vec::<Box<T>>::new()`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
 
 //! This is also pretty tricky: [`TypeId::of::<String>()`].
 //! And this too: [`Vec::<std::error::Error>::len`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
+// @has foo/index.html '//a[@href="{{channel}}/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
 
 //! We unofficially and implicitly support things that aren't valid in the actual Rust syntax, like
 //! [`Box::<T>new()`]. We may not support them in the future!
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
 
 //! These will be resolved as regular links:
 //! - [`this is <invalid syntax> first`](https://www.rust-lang.org)
index ee71537d155319bfe8b3615a9017e0263ed5ea73..be4b44b314252686b206a16e43b08970ae69275d 100644 (file)
@@ -2,45 +2,45 @@
 #![feature(intra_doc_pointers)]
 #![deny(rustdoc::broken_intra_doc_links)]
 
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
+// @has foo/index.html '//a[@href="{{channel}}/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
 //! [slice::rotate_left]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map'
+// @has - '//a[@href="{{channel}}/std/primitive.array.html#method.map"]' 'array::map'
 //! [array::map]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'owned str'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str ref'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.len"]' '&str::len'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.len"]' '&str::len'
 //! [owned str][str]
 //! [str ref][&str]
 //! [str::is_empty]
 //! [&str::len]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
 //! [pointer::is_null]
 //! [*const::is_null]
 //! [*mut::is_null]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit'
+// @has - '//a[@href="{{channel}}/std/primitive.unit.html"]' 'unit'
 //! [unit]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.tuple.html"]' 'tuple'
+// @has - '//a[@href="{{channel}}/std/primitive.tuple.html"]' 'tuple'
 //! [tuple]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' 'reference'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&mut'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' 'reference'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&mut'
 //! [reference]
 //! [&]
 //! [&mut]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.fn.html"]' 'fn'
+// @has - '//a[@href="{{channel}}/std/primitive.fn.html"]' 'fn'
 //! [fn]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' 'never'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' '!'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' 'never'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' '!'
 //! [never]
 //! [!]
index 4099ececfaf7ccff3d4a308dcd8493947a27ade8..c73140420ff1f858a0d5c0e7c2f4915d371ab02f 100644 (file)
@@ -1,4 +1,4 @@
 #![deny(broken_intra_doc_links)]
 
 //! [i32::MAX]
-// @has prim_assoc/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
+// @has prim_assoc/index.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
index 695a7fbfb534812c257a6d6d1d4e81e98c8b6a2e..9347d7bb42819fed336d62de936f83f16a62276d 100644 (file)
@@ -9,8 +9,8 @@
 #![crate_type = "rlib"]
 
 // @has prim_methods_external_core/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
index f0b939a468c0339f3ef351c0824d4e6eaf5dc1e5..124faa9a636ffb9d3b3e979c3a21689b2a5f7b16 100644 (file)
@@ -5,8 +5,8 @@
 
 
 // @has prim_methods_local/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
index 6de15e76d15cfa6ce610d4da5d6586886e4c0c67..076117359d26416bc52e08e858e8d32d236a79d4 100644 (file)
@@ -2,7 +2,7 @@
 
 
 // @has prim_methods/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
index 478b40b0b516fb9c3b19bfbbb78312019f16eed1..fcd86a99f1d6bf402125cab94bb84fc76b1360a5 100644 (file)
@@ -2,12 +2,12 @@
 
 pub mod char {
     /// [char]
-    // @has prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+    // @has prim_precedence/char/struct.Inner.html '//a/@href' '{{channel}}/std/primitive.char.html'
     pub struct Inner;
 }
 
 /// See [prim@char]
-// @has prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+// @has prim_precedence/struct.MyString.html '//a/@href' '{{channel}}/std/primitive.char.html'
 pub struct MyString;
 
 /// See also [crate::char] and [mod@char]
index acdd07566c94d145540b0a4d19152916841ff535..9b3b698324096e03ec38ae7f982ba3a449f76d95 100644 (file)
@@ -1,4 +1,4 @@
 #![deny(broken_intra_doc_links)]
 // @has primitive_disambiguators/index.html
-// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim'
+// @has - '//a/@href' '{{channel}}/std/primitive.str.html#method.trim'
 //! [str::trim()]
index cf83ead4db72c09172343575f98b2a41492c595b..f8a824bd08f421c81dde5878eee247b25b1907dc 100644 (file)
@@ -3,29 +3,29 @@
 
 // @has primitive_non_default_impl/fn.str_methods.html
 /// [`str::trim`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.trim"]' 'str::trim'
 /// [`str::to_lowercase`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
 /// [`str::into_boxed_bytes`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
 /// [`str::replace`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.replace"]' 'str::replace'
 pub fn str_methods() {}
 
 // @has primitive_non_default_impl/fn.f32_methods.html
 /// [f32::powi]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.powi"]' 'f32::powi'
 /// [f32::sqrt]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
 /// [f32::mul_add]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
 pub fn f32_methods() {}
 
 // @has primitive_non_default_impl/fn.f64_methods.html
 /// [`f64::powi`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.powi"]' 'f64::powi'
 /// [`f64::sqrt`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
 /// [`f64::mul_add`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
 pub fn f64_methods() {}
index 579fa68cee8be37d1ff4e5b2a5516e77e4f0a682..b4f2d6b0617fa914e885eaa8b73582c5e4081b54 100644 (file)
@@ -12,7 +12,7 @@
 // documenting the re-export.
 
 // @has outer/index.html
-// @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/fn.var.html"]' "std::env"
+// @ has - '//a[@href="{{channel}}/std/env/fn.var.html"]' "std::env"
 // @ has - '//a[@href="fn.f.html"]' "g"
 pub use f as g;
 
@@ -23,5 +23,5 @@
 // Make sure the documentation is actually correct by documenting an inlined re-export
 /// [mod@std::env]
 // @has outer/fn.f.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/index.html"]' "std::env"
+// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env"
 pub use inner::f;
index 7602aced56416ba9a002a87b3ac142238c28edaf..0be368d051ee6e509c00bf78aad5a4c2cb3b75e5 100644 (file)
@@ -3,7 +3,7 @@
 /// Link to [S::assoc_fn()]
 /// Link to [Default::default()]
 // @has trait_item/struct.S.html '//*[@href="struct.S.html#method.assoc_fn"]' 'S::assoc_fn()'
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
+// @has - '//*[@href="{{channel}}/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
 pub struct S;
 
 impl S {
index db637ece369951770d12063d679713023ecd98ee..44aac68841373842844058351f77ca209fc2a788 100644 (file)
@@ -3,7 +3,7 @@
 
 
 // @has foo/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'true'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'false'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'true'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'false'
 
 //! A `bool` is either [`true`] or [`false`].
index 1189d266c536e72edade4540b15896af7a79d1c8..4744c84b6226db03b33a6b890fdb3e128878d34e 100644 (file)
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![deny(broken_intra_doc_links)]
 #![feature(lang_items)]
 #![feature(no_core)]
@@ -8,8 +7,8 @@
 /// [Self::f]
 /// [Self::MAX]
 // @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
 impl usize {
     /// Some docs
     pub fn f() {}
@@ -18,7 +17,7 @@ pub fn f() {}
     pub const MAX: usize = 10;
 
     // FIXME(#8995) uncomment this when associated types in inherent impls are supported
-    // @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
+    // @ has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
     // / [Self::ME]
     //pub type ME = usize;
 }
index dd455e45bfc2a5556352c56849c3cbd6cba3399f..125e0c849731a6ed8b3948b8b9f3702502a6990d 100644 (file)
@@ -1,12 +1,12 @@
 #![crate_name = "foo"]
 
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i64.html"]' 'i64'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html"]' 'std::primitive::i32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.str.html"]' 'std::primitive::str'
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
 
 /// It contains [`u32`] and [i64].
 /// It also links to [std::primitive::i32], [std::primitive::str],
index de18360d4077c2615a47a5081ee0b0cd647ccf56..10a8a47db52489637ac934e9f42e15537852faea 100644 (file)
@@ -5,24 +5,24 @@
 
 // @has bar/p/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub mod p {
     pub use foo::bar::*;
 }
 
 // @has bar/baz/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub use foo::bar as baz;
 
 // @has bar/index.html
 // @has - '//code' 'pub use str;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str'
+// @has - '//code/a[@href="{{channel}}/std/primitive.str.html"]' 'str'
 // @has - '//code' 'pub use i32 as my_i32;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'i32'
+// @has - '//code/a[@href="{{channel}}/std/primitive.i32.html"]' 'i32'
 pub use str;
 pub use i32 as my_i32;
index d10e1ec89c59ea19f85bbe9869fe446407e6c434..372af5f4672a7c2e699a474a7eb2cc48ba776dce 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(external_doc)]
-
 #![crate_name = "foo"]
 
 // @has foo/struct.Example.html
@@ -51,7 +49,7 @@
 // @matches - '//div[@class="docblock"]/p' '(?m)a\nno whitespace\nJust some text.\Z'
 ///a
 ///no whitespace
-#[doc(include = "unindent.md")]
+#[doc = include_str!("unindent.md")]
 pub struct J;
 
 // @has foo/struct.K.html
@@ -60,5 +58,5 @@
 ///
 ///    4 whitespaces!
 ///
-#[doc(include = "unindent.md")]
+#[doc = include_str!("unindent.md")]
 pub struct K;
index dd67514d02aa43f617248d24f69717524cc6ba7b..cf73403bbae0755606200b12da834029deec0cf7 100644 (file)
@@ -64,6 +64,10 @@ LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut
    |                                               has type `&mut VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
    |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of a mutable reference to VaListImpl<'_>
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/variadic-ffi-4.rs:28:5
@@ -74,6 +78,10 @@ LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut
    |                                               has type `&mut VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
    |     ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
+   |
+   = note: requirement occurs because of a mutable reference to VaListImpl<'_>
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error[E0597]: `ap1` does not live long enough
   --> $DIR/variadic-ffi-4.rs:28:11
index 6ba1b2813a177e4ad2ca3e9bfe6ff34ab55c6066..457e5ae60494a264e03a64c8948982f7922352ca 100644 (file)
@@ -9,31 +9,31 @@
 };
 
 pub fn yes_iterator() -> impl Iterator<Item = i32> {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_fused_iterator() -> impl FusedIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_trusted_len() -> impl TrustedLen {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_clone() -> impl Clone {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_debug() -> impl Debug {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 
index deafde2912bb722e2949706a358cf9db1674f30b..4f343f3f97ea478420fc368a6a1a18828be9b1a0 100644 (file)
@@ -9,31 +9,31 @@
 };
 
 pub fn yes_iterator() -> impl Iterator<Item = i32> {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_fused_iterator() -> impl FusedIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_trusted_len() -> impl TrustedLen {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_clone() -> impl Clone {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_debug() -> impl Debug {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 
index 30309da499f644cdcfe7d3a05b794de66f508c14..62e2dc71210978a882020eb1c8d8f40543b64d90 100644 (file)
@@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:12:25
    |
 LL |     unsafe { let _val = A; }
-   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
+   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:19:26
    |
 LL |     unsafe { let _val = &A; }
-   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
+   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
 
 warning: skipping const checks
    |
index b6c791c15fd20ce1b56e33c0d386445340eb1462..35e42a6857f320cfa429c639e4ae9d6069f538d2 100644 (file)
@@ -430,6 +430,24 @@ pub fn foo() {
             // the patterns are all fine:
             (..) = x;
     }
+
+    #[derive(Debug)]
+    #[deprecated(note = "Use something else instead")]
+    enum DeprecatedDebugEnum {
+        Variant1 { value: Option<String> },
+    }
+
+    #[allow(deprecated)]
+    impl DeprecatedDebugEnum {
+        fn new() -> Self {
+            DeprecatedDebugEnum::Variant1 { value: None }
+        }
+    }
+
+    #[allow(deprecated)]
+    pub fn allow_dep() {
+        let _ = DeprecatedDebugEnum::new();
+    }
 }
 
 fn main() {}
index 20af4f62e6502cc78af28a3b2bf97afcd8878bd6..3699a939e27882e21e5a0a5363b9461f21cff183 100644 (file)
@@ -11,16 +11,16 @@ LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:21:16
+  --> $DIR/deprecation-lint.rs:21:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:23:25
+  --> $DIR/deprecation-lint.rs:23:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:25:9
@@ -29,16 +29,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:30:16
+  --> $DIR/deprecation-lint.rs:30:9
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:32:25
+  --> $DIR/deprecation-lint.rs:32:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::DeprecatedStruct`: text
   --> $DIR/deprecation-lint.rs:34:17
@@ -53,10 +53,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated variant `deprecation_lint::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:40:23
+  --> $DIR/deprecation-lint.rs:40:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                       ^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:42:17
@@ -65,28 +65,28 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedStruct`: text
-  --> $DIR/deprecation-lint.rs:44:25
+  --> $DIR/deprecation-lint.rs:44:17
    |
 LL |         let _ = nested::DeprecatedStruct {
-   |                         ^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:48:25
+  --> $DIR/deprecation-lint.rs:48:17
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
-   |                         ^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated variant `deprecation_lint::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:50:31
+  --> $DIR/deprecation-lint.rs:50:17
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
-   |                             ^^^^^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:52:25
+  --> $DIR/deprecation-lint.rs:52:17
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:59:25
@@ -101,28 +101,28 @@ LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:65:16
+  --> $DIR/deprecation-lint.rs:65:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:67:25
+  --> $DIR/deprecation-lint.rs:67:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:69:16
+  --> $DIR/deprecation-lint.rs:69:9
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `deprecation_lint::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:71:25
+  --> $DIR/deprecation-lint.rs:71:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated trait `deprecation_lint::DeprecatedTrait`: text
   --> $DIR/deprecation-lint.rs:81:10
@@ -173,10 +173,10 @@ LL |         let Deprecated2
    |             ^^^^^^^^^^^
 
 error: use of deprecated function `deprecation_lint::deprecated_mod::deprecated`: text
-  --> $DIR/deprecation-lint.rs:162:25
+  --> $DIR/deprecation-lint.rs:162:9
    |
 LL |         deprecated_mod::deprecated();
-   |                         ^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/deprecation-lint.rs:245:9
@@ -185,16 +185,16 @@ LL |         deprecated();
    |         ^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:250:16
+  --> $DIR/deprecation-lint.rs:250:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:252:25
+  --> $DIR/deprecation-lint.rs:252:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/deprecation-lint.rs:254:9
@@ -203,16 +203,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:259:16
+  --> $DIR/deprecation-lint.rs:259:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |                ^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:261:25
+  --> $DIR/deprecation-lint.rs:261:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::deprecated_future`: text
   --> $DIR/deprecation-lint.rs:264:9
@@ -239,10 +239,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:274:23
+  --> $DIR/deprecation-lint.rs:274:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                       ^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/deprecation-lint.rs:276:17
@@ -251,52 +251,52 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated struct `this_crate::nested::DeprecatedStruct`: text
-  --> $DIR/deprecation-lint.rs:278:25
+  --> $DIR/deprecation-lint.rs:278:17
    |
 LL |         let _ = nested::DeprecatedStruct {
-   |                         ^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit struct `this_crate::nested::DeprecatedUnitStruct`: text
-  --> $DIR/deprecation-lint.rs:283:25
+  --> $DIR/deprecation-lint.rs:283:17
    |
 LL |         let _ = nested::DeprecatedUnitStruct;
-   |                         ^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated unit variant `this_crate::nested::Enum::DeprecatedVariant`: text
-  --> $DIR/deprecation-lint.rs:285:31
+  --> $DIR/deprecation-lint.rs:285:17
    |
 LL | ...   let _ = nested::Enum::DeprecatedVariant;
-   |                             ^^^^^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated tuple struct `this_crate::nested::DeprecatedTupleStruct`: text
-  --> $DIR/deprecation-lint.rs:287:25
+  --> $DIR/deprecation-lint.rs:287:17
    |
 LL | ...   let _ = nested::DeprecatedTupleStruct (1);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:292:16
+  --> $DIR/deprecation-lint.rs:292:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/deprecation-lint.rs:294:25
+  --> $DIR/deprecation-lint.rs:294:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:296:16
+  --> $DIR/deprecation-lint.rs:296:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |                ^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/deprecation-lint.rs:298:25
+  --> $DIR/deprecation-lint.rs:298:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: use of deprecated function `this_crate::test_fn_closure_body::{closure#0}::bar`
   --> $DIR/deprecation-lint.rs:316:13
index 1ba1821e6c18b1f8bf202f42b3745ba71a56f393..eba72f88a89115cefd1c018221477a124d41d7f4 100644 (file)
@@ -1,7 +1,9 @@
 // run-rustfix
 
 #![feature(staged_api)]
+
 #![stable(since = "1.0.0", feature = "test")]
+
 #![deny(deprecated)]
 #![allow(dead_code)]
 
@@ -19,21 +21,8 @@ impl Foo {
     fn replacement(&self) {}
 }
 
-mod bar {
-    #[rustc_deprecated(
-    since = "1.0.0",
-    reason = "replaced by `replacement`",
-    suggestion = "replacement",
-    )]
-    #[stable(since = "1.0.0", feature = "test")]
-    pub fn deprecated() {}
-
-    pub fn replacement() {}
-}
-
 fn main() {
     let foo = Foo;
-    foo.replacement(); //~ ERROR use of deprecated
 
-    bar::replacement(); //~ ERROR use of deprecated
+    foo.replacement(); //~ ERROR use of deprecated
 }
index e40737d19575aea45b8d5604e4678ae2e14257d6..8f9791c13e8563651988f115e89a17c5fdc3ff16 100644 (file)
@@ -1,7 +1,9 @@
 // run-rustfix
 
 #![feature(staged_api)]
+
 #![stable(since = "1.0.0", feature = "test")]
+
 #![deny(deprecated)]
 #![allow(dead_code)]
 
@@ -19,21 +21,8 @@ fn deprecated(&self) {}
     fn replacement(&self) {}
 }
 
-mod bar {
-    #[rustc_deprecated(
-    since = "1.0.0",
-    reason = "replaced by `replacement`",
-    suggestion = "replacement",
-    )]
-    #[stable(since = "1.0.0", feature = "test")]
-    pub fn deprecated() {}
-
-    pub fn replacement() {}
-}
-
 fn main() {
     let foo = Foo;
-    foo.deprecated(); //~ ERROR use of deprecated
 
-    bar::deprecated(); //~ ERROR use of deprecated
+    foo.deprecated(); //~ ERROR use of deprecated
 }
index b95ca3a75e46d1cef72e922544aca44ea041c54f..8a7cb1def909e3a818d6d2ca588e3dc018456dc9 100644 (file)
@@ -1,20 +1,14 @@
-error: use of deprecated function `bar::deprecated`: replaced by `replacement`
-  --> $DIR/suggestion.rs:38:10
+error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
+  --> $DIR/suggestion.rs:27:9
    |
-LL |     bar::deprecated();
-   |          ^^^^^^^^^^ help: replace the use of the deprecated function: `replacement`
+LL |     foo.deprecated();
+   |         ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
    |
 note: the lint level is defined here
-  --> $DIR/suggestion.rs:5:9
+  --> $DIR/suggestion.rs:7:9
    |
 LL | #![deny(deprecated)]
    |         ^^^^^^^^^^
 
-error: use of deprecated associated function `Foo::deprecated`: replaced by `replacement`
-  --> $DIR/suggestion.rs:36:9
-   |
-LL |     foo.deprecated();
-   |         ^^^^^^^^^^ help: replace the use of the deprecated associated function: `replacement`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index ad854837ae5bd678985e7f483a2fd97019929755..246f69558ff0d46224d4061c3ba903d496545ad9 100644 (file)
@@ -14,7 +14,7 @@ LL | static BAR: _ = "test";
    |             ^
    |             |
    |             not allowed in type signatures
-   |             help: replace `_` with the correct type: `&str`
+   |             help: replace with the correct type: `&str`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
deleted file mode 100644 (file)
index 4e89f74..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// normalize-stderr-test: "not-a-file.md:.*\(" -> "not-a-file.md: $$FILE_NOT_FOUND_MSG ("
-
-#![feature(external_doc)]
-
-#[doc(include = "not-a-file.md")]
-pub struct SomeStruct; //~^ ERROR couldn't read
-
-#[doc(include = "auxiliary/invalid-utf8.txt")]
-pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
-
-#[doc(include)]
-pub struct MissingPath; //~^ ERROR expected path
-                        //~| HELP provide a file path with `=`
-                        //~| SUGGESTION include = "<path>"
-
-#[doc(include("../README.md"))]
-pub struct InvalidPathSyntax; //~^ ERROR expected path
-                              //~| HELP provide a file path with `=`
-                              //~| SUGGESTION include = "../README.md"
-
-#[doc(include = 123)]
-pub struct InvalidPathType; //~^ ERROR expected path
-                            //~| HELP provide a file path with `=`
-                            //~| SUGGESTION include = "<path>"
-
-#[doc(include(123))]
-pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
-                                     //~| HELP provide a file path with `=`
-                                     //~| SUGGESTION include = "<path>"
-
-fn main() {}
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
deleted file mode 100644 (file)
index b180cd6..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/external-doc-error.rs:5:17
-   |
-LL | #[doc(include = "not-a-file.md")]
-   |                 ^^^^^^^^^^^^^^^ couldn't read file
-
-error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
-  --> $DIR/external-doc-error.rs:8:17
-   |
-LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:11:7
-   |
-LL | #[doc(include)]
-   |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:16:7
-   |
-LL | #[doc(include("../README.md"))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:21:7
-   |
-LL | #[doc(include = 123)]
-   |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:26:7
-   |
-LL | #[doc(include(123))]
-   |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs
deleted file mode 100644 (file)
index 4e6e293..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental
-                          //~| ERROR: `#[doc(include)]` is experimental
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
deleted file mode 100644 (file)
index bd2aefe..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: `#[doc(include)]` is experimental
-  --> $DIR/feature-gate-external_doc.rs:1:1
-   |
-LL | #[doc(include="asdf.md")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #44732 <https://github.com/rust-lang/rust/issues/44732> for more information
-   = help: add `#![feature(external_doc)]` to the crate attributes to enable
-
-error[E0658]: `#[doc(include)]` is experimental
-  --> $DIR/feature-gate-external_doc.rs:1:1
-   |
-LL | #[doc(include="asdf.md")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #44732 <https://github.com/rust-lang/rust/issues/44732> for more information
-   = help: add `#![feature(external_doc)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs
new file mode 100644 (file)
index 0000000..518aa20
--- /dev/null
@@ -0,0 +1,8 @@
+#[link(name = "foo")]
+extern "C" {
+    #[link_ordinal(42)]
+    //~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature
+    fn foo();
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr
new file mode 100644 (file)
index 0000000..dbee5f3
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: the `#[link_ordinal]` attribute is an experimental feature
+  --> $DIR/feature-gate-raw-dylib-2.rs:3:5
+   |
+LL |     #[link_ordinal(42)]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs
new file mode 100644 (file)
index 0000000..33f9c53
--- /dev/null
@@ -0,0 +1,8 @@
+// gate-test-raw_dylib
+// only-windows-gnu
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: kind="raw-dylib" is unstable
+//~| WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+extern "C" {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr
new file mode 100644 (file)
index 0000000..14dfadf
--- /dev/null
@@ -0,0 +1,18 @@
+warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0658]: kind="raw-dylib" is unstable
+  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs
new file mode 100644 (file)
index 0000000..49de24e
--- /dev/null
@@ -0,0 +1,7 @@
+// gate-test-raw_dylib
+// only-windows-msvc
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: kind="raw-dylib" is unstable
+extern "C" {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr
new file mode 100644 (file)
index 0000000..1198808
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0658]: kind="raw-dylib" is unstable
+  --> $DIR/feature-gate-raw-dylib-windows-msvc.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index bd0d27ff3e9ac50c2a6a9b1bbc9e05f0d27b9ac4..78100318dc33ad1fdf640f0bd8b04e9d53448fda 100644 (file)
@@ -12,7 +12,7 @@ note: generator is not `Send` as this value is used across a yield
   --> $DIR/generator-print-verbose-1.rs:35:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[70c9]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 LL |     };
@@ -30,10 +30,10 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
-   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[70c9]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
-   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), [])`
-   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}`
-   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}]`
+   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])`
+   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}`
+   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]`
 
 error: aborting due to 2 previous errors
 
index 6a744812e41d15929ae4f84da3978997d308b9c7..a84c048fab967dd72ce6fcaa40523a652c123dae 100644 (file)
@@ -37,7 +37,7 @@ LL |               const A = "A".$fn();
    |                     ^
    |                     |
    |                     not allowed in type signatures
-   |                     help: replace `_` with the correct type: `bool`
+   |                     help: replace with the correct type: `bool`
 ...
 LL | / suite! {
 LL | |     len;
diff --git a/src/test/ui/layout/issue-84108.rs b/src/test/ui/layout/issue-84108.rs
new file mode 100644 (file)
index 0000000..dd025c9
--- /dev/null
@@ -0,0 +1,14 @@
+// See issue #84108 -- this is a test to ensure we do not ICE
+// on this invalid code.
+
+#![crate_type = "lib"]
+
+static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
+//~^ ERROR cannot find type `OsStr` in this scope
+
+const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+//~^ ERROR cannot find type `Path` in this scope
+//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
+
+static BAZ: ([u8], usize) = ([], 0);
+//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/src/test/ui/layout/issue-84108.stderr b/src/test/ui/layout/issue-84108.stderr
new file mode 100644 (file)
index 0000000..36be642
--- /dev/null
@@ -0,0 +1,44 @@
+error[E0412]: cannot find type `OsStr` in this scope
+  --> $DIR/issue-84108.rs:6:24
+   |
+LL | static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
+   |                        ^^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::ffi::OsStr;
+   |
+
+error[E0412]: cannot find type `Path` in this scope
+  --> $DIR/issue-84108.rs:9:14
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |              ^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::path::Path;
+   |
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:9:12
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |            ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:13:13
+   |
+LL | static BAZ: ([u8], usize) = ([], 0);
+   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs
new file mode 100644 (file)
index 0000000..d4a5056
--- /dev/null
@@ -0,0 +1,11 @@
+// compile-flags: --force-warns elided_lifetimes_in_paths
+// check-pass
+
+struct Foo<'a> {
+    x: &'a u32,
+}
+
+fn foo(x: &Foo) {}
+//~^ WARN hidden lifetime parameters in types are deprecated
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr
new file mode 100644 (file)
index 0000000..0e0e934
--- /dev/null
@@ -0,0 +1,10 @@
+warning: hidden lifetime parameters in types are deprecated
+  --> $DIR/force-allowed-by-default-lint.rs:8:12
+   |
+LL | fn foo(x: &Foo) {}
+   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs
new file mode 100644 (file)
index 0000000..afd2d6e
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns const_err
+// check-pass
+
+#![allow(const_err)]
+const C: i32 = 1 / 0;
+//~^ WARN any use of this value will cause an error
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr
new file mode 100644 (file)
index 0000000..bad12f9
--- /dev/null
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/force-allowed-deny-by-default-lint.rs:5:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.rs b/src/test/ui/lint/force-warn/force-allowed-warning.rs
new file mode 100644 (file)
index 0000000..5c83c52
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(dead_code)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.stderr b/src/test/ui/lint/force-warn/force-allowed-warning.stderr
new file mode 100644 (file)
index 0000000..145798a
--- /dev/null
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-allowed-warning.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs
new file mode 100644 (file)
index 0000000..4f267f0
--- /dev/null
@@ -0,0 +1,8 @@
+// compile-flags: --force-warns const_err
+// check-pass
+
+const C: i32 = 1 / 0;
+//~^ WARN any use of this value will cause an error
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr
new file mode 100644 (file)
index 0000000..4b004cf
--- /dev/null
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/force-deny-by-default-lint.rs:4:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs
new file mode 100644 (file)
index 0000000..5501faa
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(warnings)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr
new file mode 100644 (file)
index 0000000..577dbe1
--- /dev/null
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-lint-allow-all-warnings.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs
new file mode 100644 (file)
index 0000000..9009971
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns nonstandard_style
+// check-pass
+
+#![allow(warnings)]
+
+pub fn FUNCTION() {}
+//~^ WARN function `FUNCTION` should have a snake case name
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr
new file mode 100644 (file)
index 0000000..8665fa2
--- /dev/null
@@ -0,0 +1,10 @@
+warning: function `FUNCTION` should have a snake case name
+  --> $DIR/force-lint-group-allow-all-warnings.rs:6:8
+   |
+LL | pub fn FUNCTION() {}
+   |        ^^^^^^^^ help: convert the identifier to snake case: `function`
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs
new file mode 100644 (file)
index 0000000..b68b979
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns bare_trait_objects
+// check-pass
+
+#![allow(rust_2018_idioms)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
new file mode 100644 (file)
index 0000000..40750ff
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-lint-in-allowed-group.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs
new file mode 100644 (file)
index 0000000..357a79b
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns rust_2018_idioms
+// check-pass
+
+#![allow(bare_trait_objects)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
new file mode 100644 (file)
index 0000000..88ae846
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-group-allow-warning.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warn-group.rs b/src/test/ui/lint/force-warn/force-warn-group.rs
new file mode 100644 (file)
index 0000000..a4615df
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns rust_2018_idioms
+// check-pass
+
+#![allow(rust_2018_idioms)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-group.stderr b/src/test/ui/lint/force-warn/force-warn-group.stderr
new file mode 100644 (file)
index 0000000..f808727
--- /dev/null
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-group.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
index e69d0dab49642267dc7e8a87f600cf4221081ed3..c18cb881032a6d6dfa09ac7f50566d3ba7d022ff 100644 (file)
@@ -8,6 +8,8 @@
 use std::default::Default;
 use std::marker::PhantomData;
 
+trait Trait {}
+
 trait Mirror { type It: ?Sized; }
 
 impl<T: ?Sized> Mirror for T { type It = Self; }
@@ -74,6 +76,15 @@ pub extern "C" fn box_type(p: Box<u32>) { }
 
 pub extern "C" fn opt_box_type(p: Option<Box<u32>>) { }
 
+pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+//~^ ERROR: uses type `Box<[u8]>`
+
+pub extern "C" fn boxed_string(p: Box<str>) { }
+//~^ ERROR: uses type `Box<str>`
+
+pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+//~^ ERROR: uses type `Box<dyn Trait>`
+
 pub extern "C" fn char_type(p: char) { }
 //~^ ERROR uses type `char`
 
index e6a0778ddb25d54368610d1dd182af3b036285c7..d591d4ad292dd51fc972812052f9411ada5f7e77 100644 (file)
@@ -1,5 +1,5 @@
 error: `extern` fn uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:67:33
+  --> $DIR/lint-ctypes-fn.rs:69:33
    |
 LL | pub extern "C" fn slice_type(p: &[u32]) { }
    |                                 ^^^^^^ not FFI-safe
@@ -13,7 +13,7 @@ LL | #![deny(improper_ctypes_definitions)]
    = note: slices have no C equivalent
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:70:31
+  --> $DIR/lint-ctypes-fn.rs:72:31
    |
 LL | pub extern "C" fn str_type(p: &str) { }
    |                               ^^^^ not FFI-safe
@@ -21,8 +21,32 @@ LL | pub extern "C" fn str_type(p: &str) { }
    = help: consider using `*const u8` and a length instead
    = note: string slices have no C equivalent
 
+error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:79:34
+   |
+LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+   |                                  ^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<str>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:82:35
+   |
+LL | pub extern "C" fn boxed_string(p: Box<str>) { }
+   |                                   ^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:85:34
+   |
+LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+   |                                  ^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
 error: `extern` fn uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:77:32
+  --> $DIR/lint-ctypes-fn.rs:88:32
    |
 LL | pub extern "C" fn char_type(p: char) { }
    |                                ^^^^ not FFI-safe
@@ -31,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { }
    = note: the `char` type has no C equivalent
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:80:32
+  --> $DIR/lint-ctypes-fn.rs:91:32
    |
 LL | pub extern "C" fn i128_type(p: i128) { }
    |                                ^^^^ not FFI-safe
@@ -39,7 +63,7 @@ LL | pub extern "C" fn i128_type(p: i128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:83:32
+  --> $DIR/lint-ctypes-fn.rs:94:32
    |
 LL | pub extern "C" fn u128_type(p: u128) { }
    |                                ^^^^ not FFI-safe
@@ -47,7 +71,7 @@ LL | pub extern "C" fn u128_type(p: u128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:86:33
+  --> $DIR/lint-ctypes-fn.rs:97:33
    |
 LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    |                                 ^^^^^^^^^^ not FFI-safe
@@ -56,7 +80,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:89:34
+  --> $DIR/lint-ctypes-fn.rs:100:34
    |
 LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    |                                  ^^^^^^^ not FFI-safe
@@ -65,7 +89,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:92:32
+  --> $DIR/lint-ctypes-fn.rs:103:32
    |
 LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    |                                ^^^^^^^^ not FFI-safe
@@ -73,26 +97,26 @@ LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:26:1
+  --> $DIR/lint-ctypes-fn.rs:28:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:95:40
+  --> $DIR/lint-ctypes-fn.rs:106:40
    |
 LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:61:1
+  --> $DIR/lint-ctypes-fn.rs:63:1
    |
 LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:98:51
+  --> $DIR/lint-ctypes-fn.rs:109:51
    |
 LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    |                                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -100,7 +124,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:103:30
+  --> $DIR/lint-ctypes-fn.rs:114:30
    |
 LL | pub extern "C" fn fn_type(p: RustFn) { }
    |                              ^^^^^^ not FFI-safe
@@ -109,7 +133,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:106:31
+  --> $DIR/lint-ctypes-fn.rs:117:31
    |
 LL | pub extern "C" fn fn_type2(p: fn()) { }
    |                               ^^^^ not FFI-safe
@@ -118,7 +142,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:111:39
+  --> $DIR/lint-ctypes-fn.rs:122:39
    |
 LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    |                                       ^^^^^^^^^^^^^^^ not FFI-safe
@@ -126,7 +150,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:114:38
+  --> $DIR/lint-ctypes-fn.rs:125:38
    |
 LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    |                                      ^^^^^^^^^^^^^^ not FFI-safe
@@ -135,7 +159,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    = note: string slices have no C equivalent
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:160:43
+  --> $DIR/lint-ctypes-fn.rs:171:43
    |
 LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    |                                           ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -143,7 +167,7 @@ LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:173:39
+  --> $DIR/lint-ctypes-fn.rs:184:39
    |
 LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    |                                       ^^^^^^ not FFI-safe
@@ -152,7 +176,7 @@ LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    = note: this struct has unspecified layout
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:176:41
+  --> $DIR/lint-ctypes-fn.rs:187:41
    |
 LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    |                                         ^^^^^^ not FFI-safe
@@ -160,5 +184,5 @@ LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 
-error: aborting due to 17 previous errors
+error: aborting due to 20 previous errors
 
index 4b082fcd35951147a71aa9e01b9bb94c9590fd8a..94fc1a7b46dbaf85e1234f8e109091572ad66541 100644 (file)
@@ -11,16 +11,16 @@ LL | #![warn(deprecated)]
    |         ^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:29:16
+  --> $DIR/lint-stability-deprecated.rs:29:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:31:25
+  --> $DIR/lint-stability-deprecated.rs:31:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:33:9
@@ -29,16 +29,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:38:16
+  --> $DIR/lint-stability-deprecated.rs:38:9
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:40:25
+  --> $DIR/lint-stability-deprecated.rs:40:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_unstable`: text
   --> $DIR/lint-stability-deprecated.rs:42:9
@@ -47,16 +47,16 @@ LL |         deprecated_unstable();
    |         ^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:47:16
+  --> $DIR/lint-stability-deprecated.rs:47:9
    |
 LL | ...   Trait::trait_deprecated_unstable(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:49:25
+  --> $DIR/lint-stability-deprecated.rs:49:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text
   --> $DIR/lint-stability-deprecated.rs:51:9
@@ -65,16 +65,16 @@ LL |         deprecated_unstable_text();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:56:16
+  --> $DIR/lint-stability-deprecated.rs:56:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:58:25
+  --> $DIR/lint-stability-deprecated.rs:58:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:108:17
@@ -101,16 +101,16 @@ LL |         let _ = DeprecatedUnstableUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated variant `lint_stability::Enum::DeprecatedVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:123:23
+  --> $DIR/lint-stability-deprecated.rs:123:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                       ^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated variant `lint_stability::Enum::DeprecatedUnstableVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:124:23
+  --> $DIR/lint-stability-deprecated.rs:124:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `lint_stability::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:128:17
@@ -143,52 +143,52 @@ LL |         macro_test_arg!(macro_test_arg!(deprecated_text()));
    |                                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:145:16
+  --> $DIR/lint-stability-deprecated.rs:145:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:147:25
+  --> $DIR/lint-stability-deprecated.rs:147:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:149:16
+  --> $DIR/lint-stability-deprecated.rs:149:9
    |
 LL | ...   Trait::trait_deprecated_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:151:25
+  --> $DIR/lint-stability-deprecated.rs:151:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:153:16
+  --> $DIR/lint-stability-deprecated.rs:153:9
    |
 LL | ...   Trait::trait_deprecated_unstable(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable`: text
-  --> $DIR/lint-stability-deprecated.rs:155:25
+  --> $DIR/lint-stability-deprecated.rs:155:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:157:16
+  --> $DIR/lint-stability-deprecated.rs:157:9
    |
 LL | ...   Trait::trait_deprecated_unstable_text(&foo);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `lint_stability::Trait::trait_deprecated_unstable_text`: text
-  --> $DIR/lint-stability-deprecated.rs:159:25
+  --> $DIR/lint-stability-deprecated.rs:159:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_unstable_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text
   --> $DIR/lint-stability-deprecated.rs:187:10
@@ -203,10 +203,10 @@ LL |     trait LocalTrait2 : DeprecatedTrait { }
    |                         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:208:23
+  --> $DIR/lint-stability-deprecated.rs:208:9
    |
 LL |         unstable_mod::deprecated();
-   |                       ^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::deprecated`: text
   --> $DIR/lint-stability-deprecated.rs:330:9
@@ -215,16 +215,16 @@ LL |         deprecated();
    |         ^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:335:16
+  --> $DIR/lint-stability-deprecated.rs:335:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:337:25
+  --> $DIR/lint-stability-deprecated.rs:337:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::deprecated_text`: text
   --> $DIR/lint-stability-deprecated.rs:339:9
@@ -233,16 +233,16 @@ LL |         deprecated_text();
    |         ^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:344:16
+  --> $DIR/lint-stability-deprecated.rs:344:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |                ^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:346:25
+  --> $DIR/lint-stability-deprecated.rs:346:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated struct `this_crate::DeprecatedStruct`: text
   --> $DIR/lint-stability-deprecated.rs:384:17
@@ -257,10 +257,10 @@ LL |         let _ = DeprecatedUnitStruct;
    |                 ^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text
-  --> $DIR/lint-stability-deprecated.rs:395:23
+  --> $DIR/lint-stability-deprecated.rs:395:17
    |
 LL |         let _ = Enum::DeprecatedVariant;
-   |                       ^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text
   --> $DIR/lint-stability-deprecated.rs:399:17
@@ -269,28 +269,28 @@ LL |         let _ = DeprecatedTupleStruct (1);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:406:16
+  --> $DIR/lint-stability-deprecated.rs:406:9
    |
 LL |         Trait::trait_deprecated(&foo);
-   |                ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated`: text
-  --> $DIR/lint-stability-deprecated.rs:408:25
+  --> $DIR/lint-stability-deprecated.rs:408:9
    |
 LL |         <Foo as Trait>::trait_deprecated(&foo);
-   |                         ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:410:16
+  --> $DIR/lint-stability-deprecated.rs:410:9
    |
 LL |         Trait::trait_deprecated_text(&foo);
-   |                ^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated associated function `this_crate::Trait::trait_deprecated_text`: text
-  --> $DIR/lint-stability-deprecated.rs:412:25
+  --> $DIR/lint-stability-deprecated.rs:412:9
    |
 LL | ...   <Foo as Trait>::trait_deprecated_text(&foo);
-   |                       ^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text
   --> $DIR/lint-stability-deprecated.rs:439:9
index 891cda8016c30752aa9e7d6d590829f275c6898c..713b79bae32e625a3cbdbffdedda6795557fc537 100644 (file)
@@ -1,6 +1,6 @@
 warning: Linking globals named 'foo': symbol multiply defined!
 
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.288b404e693a75b4-cgu.0.rcgu.o": 
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o": 
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.rs b/src/test/ui/manual/manual-link-unsupported-kind.rs
new file mode 100644 (file)
index 0000000..34814db
--- /dev/null
@@ -0,0 +1,5 @@
+// compile-flags:-l raw-dylib=foo
+// error-pattern: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.stderr b/src/test/ui/manual/manual-link-unsupported-kind.stderr
new file mode 100644 (file)
index 0000000..acb4463
--- /dev/null
@@ -0,0 +1,2 @@
+error: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+
index 1658efa28bf307ff7661cbe1bd1df807758a8035..1dc29d2088cea353ac262aaff3062ab176cc63fc 100644 (file)
@@ -9,6 +9,9 @@ LL |         match self.0 { ref mut x => x }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to previous error
 
index dc227a36566e6d68345cddd6c5340a2156704822..8b87c3da28b02f946a700dc55b004a272b0a26b1 100644 (file)
@@ -10,6 +10,9 @@ LL |         x
    |         ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to previous error
 
index 39fd98f7151a000eb5f8490a71a63ad2d38ba2ef..ccb3d33ac40647fe14f45cbfcf3a6fe4e85aa11f 100644 (file)
@@ -34,6 +34,9 @@ LL |     x
    |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:13:5
@@ -47,6 +50,9 @@ LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'b` and `'a` must be the same: replace one with the other
 
index f350b861eb6d2447c690d0852f9d4df910fc75ba..b488af820b86d78344fff37d05dab2357098cd1b 100644 (file)
@@ -9,6 +9,9 @@ LL |     x == y;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:6:10
@@ -21,6 +24,9 @@ LL |     x == y;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
@@ -35,6 +41,9 @@ LL |     x == y;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:12:10
@@ -47,6 +56,9 @@ LL |     x == y;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
@@ -61,6 +73,9 @@ LL |     f == g;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:18:10
@@ -73,6 +88,9 @@ LL |     f == g;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
diff --git a/src/test/ui/parser/issue-84104.rs b/src/test/ui/parser/issue-84104.rs
new file mode 100644 (file)
index 0000000..998949b
--- /dev/null
@@ -0,0 +1,3 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected one of
+#[i=i::<ښܖ<
diff --git a/src/test/ui/parser/issue-84104.stderr b/src/test/ui/parser/issue-84104.stderr
new file mode 100644 (file)
index 0000000..aff31f2
--- /dev/null
@@ -0,0 +1,16 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-84104.rs:3:13
+   |
+LL | #[i=i::<ښܖ<
+   |  -          ^
+   |  |
+   |  unclosed delimiter
+
+error: expected one of `>`, a const expression, lifetime, or type, found `]`
+  --> $DIR/issue-84104.rs:3:13
+   |
+LL | #[i=i::<ښܖ<
+   |             ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-84148-1.rs b/src/test/ui/parser/issue-84148-1.rs
new file mode 100644 (file)
index 0000000..25f7ba4
--- /dev/null
@@ -0,0 +1,4 @@
+fn f(t:for<>t?)
+//~^ ERROR: expected parameter name
+//~| ERROR: expected one of
+//~| ERROR: expected one of
diff --git a/src/test/ui/parser/issue-84148-1.stderr b/src/test/ui/parser/issue-84148-1.stderr
new file mode 100644 (file)
index 0000000..9850656
--- /dev/null
@@ -0,0 +1,23 @@
+error: expected parameter name, found `?`
+  --> $DIR/issue-84148-1.rs:1:14
+   |
+LL | fn f(t:for<>t?)
+   |              ^ expected parameter name
+
+error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
+  --> $DIR/issue-84148-1.rs:1:14
+   |
+LL | fn f(t:for<>t?)
+   |              ^
+   |              |
+   |              expected one of `(`, `)`, `+`, `,`, `::`, or `<`
+   |              help: missing `,`
+
+error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
+  --> $DIR/issue-84148-1.rs:1:15
+   |
+LL | fn f(t:for<>t?)
+   |               ^ expected one of `->`, `;`, `where`, or `{`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/issue-84148-2.rs b/src/test/ui/parser/issue-84148-2.rs
new file mode 100644 (file)
index 0000000..257a3fd
--- /dev/null
@@ -0,0 +1,4 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected parameter name
+// error-pattern: expected one of
+fn f(t:for<>t?
diff --git a/src/test/ui/parser/issue-84148-2.stderr b/src/test/ui/parser/issue-84148-2.stderr
new file mode 100644 (file)
index 0000000..6f314da
--- /dev/null
@@ -0,0 +1,31 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-84148-2.rs:4:16
+   |
+LL | fn f(t:for<>t?
+   |     -          ^
+   |     |
+   |     unclosed delimiter
+
+error: expected parameter name, found `?`
+  --> $DIR/issue-84148-2.rs:4:14
+   |
+LL | fn f(t:for<>t?
+   |              ^ expected parameter name
+
+error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
+  --> $DIR/issue-84148-2.rs:4:14
+   |
+LL | fn f(t:for<>t?
+   |              ^
+   |              |
+   |              expected one of `(`, `)`, `+`, `,`, `::`, or `<`
+   |              help: missing `,`
+
+error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
+  --> $DIR/issue-84148-2.rs:4:16
+   |
+LL | fn f(t:for<>t?
+   |                ^ expected one of `->`, `;`, `where`, or `{`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/unmatched-langle-1.rs b/src/test/ui/parser/unmatched-langle-1.rs
new file mode 100644 (file)
index 0000000..fdf2ae3
--- /dev/null
@@ -0,0 +1,9 @@
+// Check that a suggestion is issued if there are too many `<`s in a
+// generic argument list, and that the parser recovers properly.
+
+fn main() {
+    foo::<<<<Ty<i32>>();
+    //~^ ERROR: unmatched angle brackets
+    //~| ERROR: cannot find function `foo` in this scope [E0425]
+    //~| ERROR: cannot find type `Ty` in this scope [E0412]
+}
diff --git a/src/test/ui/parser/unmatched-langle-1.stderr b/src/test/ui/parser/unmatched-langle-1.stderr
new file mode 100644 (file)
index 0000000..c8072b4
--- /dev/null
@@ -0,0 +1,22 @@
+error: unmatched angle brackets
+  --> $DIR/unmatched-langle-1.rs:5:10
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |          ^^^ help: remove extra angle brackets
+
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/unmatched-langle-1.rs:5:5
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |     ^^^ not found in this scope
+
+error[E0412]: cannot find type `Ty` in this scope
+  --> $DIR/unmatched-langle-1.rs:5:14
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |              ^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/parser/unmatched-langle-2.rs b/src/test/ui/parser/unmatched-langle-2.rs
new file mode 100644 (file)
index 0000000..8de0d7d
--- /dev/null
@@ -0,0 +1,15 @@
+// When there are too many opening `<`s, the compiler would previously
+// suggest nonsense if the `<`s were interspersed with other tokens:
+//
+//   error: unmatched angle brackets
+//    --> unmatched-langle.rs:2:10
+//     |
+//   2 |     foo::<Ty<<<i32>();
+//     |          ^^^ help: remove extra angle brackets
+//
+// This test makes sure that this is no longer happening.
+
+fn main() {
+    foo::<Ty<<<i32>();
+    //~^ ERROR: expected `::`, found `(`
+}
diff --git a/src/test/ui/parser/unmatched-langle-2.stderr b/src/test/ui/parser/unmatched-langle-2.stderr
new file mode 100644 (file)
index 0000000..773bb33
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected `::`, found `(`
+  --> $DIR/unmatched-langle-2.rs:13:20
+   |
+LL |     foo::<Ty<<<i32>();
+   |                    ^ expected `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs
new file mode 100644 (file)
index 0000000..d4067a3
--- /dev/null
@@ -0,0 +1,37 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#![feature(decl_macro)]
+#![feature(stmt_expr_attributes)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro mac {
+    (expr $expr:expr) => {
+        #[derive(Print)]
+        enum E {
+            V = { let _ = $expr; 0 },
+        }
+    },
+    (stmt $stmt:stmt) => {
+        #[derive(Print)]
+        enum E {
+            V = { let _ = { $stmt }; 0 },
+        }
+    },
+}
+
+const PATH: u8 = 2;
+
+fn main() {
+    mac!(expr #[allow(warnings)] 0);
+    mac!(stmt 0);
+    mac!(stmt {});
+    mac!(stmt PATH);
+    mac!(stmt 0 + 1);
+    mac!(stmt PATH + 1);
+}
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
new file mode 100644 (file)
index 0000000..e37a483
--- /dev/null
@@ -0,0 +1,540 @@
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #4 bytes(299..303),
+    },
+    Ident {
+        ident: "E",
+        span: #4 bytes(304..305),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #4 bytes(320..321),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #4 bytes(322..323),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #4 bytes(326..329),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #4 bytes(330..331),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #4 bytes(332..333),
+                    },
+                    Group {
+                        delimiter: None,
+                        stream: TokenStream [
+                            Punct {
+                                ch: '#',
+                                spacing: Alone,
+                                span: #0 bytes(541..542),
+                            },
+                            Group {
+                                delimiter: Bracket,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "allow",
+                                        span: #0 bytes(543..548),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "warnings",
+                                                span: #0 bytes(549..557),
+                                            },
+                                        ],
+                                        span: #0 bytes(548..558),
+                                    },
+                                ],
+                                span: #0 bytes(542..559),
+                            },
+                            Punct {
+                                ch: '#',
+                                spacing: Alone,
+                                span: #0 bytes(541..542),
+                            },
+                            Group {
+                                delimiter: Bracket,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "allow",
+                                        span: #0 bytes(543..548),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "warnings",
+                                                span: #0 bytes(549..557),
+                                            },
+                                        ],
+                                        span: #0 bytes(548..558),
+                                    },
+                                ],
+                                span: #0 bytes(542..559),
+                            },
+                            Literal {
+                                kind: Integer,
+                                symbol: "0",
+                                suffix: None,
+                                span: #0 bytes(560..561),
+                            },
+                        ],
+                        span: #4 bytes(334..339),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #4 bytes(339..340),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #4 bytes(341..342),
+                    },
+                ],
+                span: #4 bytes(324..344),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #4 bytes(344..345),
+            },
+        ],
+        span: #4 bytes(306..355),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #8 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #8 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #8 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #8 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #8 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #8 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #8 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "0",
+                                        suffix: None,
+                                        span: #0 bytes(578..579),
+                                    },
+                                ],
+                                span: #8 bytes(460..465),
+                            },
+                        ],
+                        span: #8 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #8 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #8 bytes(469..470),
+                    },
+                ],
+                span: #8 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #8 bytes(472..473),
+            },
+        ],
+        span: #8 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { { } } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #12 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #12 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #12 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #12 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #12 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #12 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #12 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Group {
+                                        delimiter: Brace,
+                                        stream: TokenStream [],
+                                        span: #0 bytes(596..598),
+                                    },
+                                ],
+                                span: #12 bytes(460..465),
+                            },
+                        ],
+                        span: #12 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #12 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #12 bytes(469..470),
+                    },
+                ],
+                span: #12 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #12 bytes(472..473),
+            },
+        ],
+        span: #12 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #16 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #16 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #16 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #16 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #16 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #16 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #16 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "PATH",
+                                        span: #0 bytes(615..619),
+                                    },
+                                ],
+                                span: #16 bytes(460..465),
+                            },
+                        ],
+                        span: #16 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #16 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #16 bytes(469..470),
+                    },
+                ],
+                span: #16 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #16 bytes(472..473),
+            },
+        ],
+        span: #16 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #20 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #20 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #20 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #20 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #20 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #20 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #20 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "0",
+                                        suffix: None,
+                                        span: #0 bytes(636..637),
+                                    },
+                                    Punct {
+                                        ch: '+',
+                                        spacing: Alone,
+                                        span: #0 bytes(638..639),
+                                    },
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "1",
+                                        suffix: None,
+                                        span: #0 bytes(640..641),
+                                    },
+                                ],
+                                span: #20 bytes(460..465),
+                            },
+                        ],
+                        span: #20 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #20 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #20 bytes(469..470),
+                    },
+                ],
+                span: #20 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #20 bytes(472..473),
+            },
+        ],
+        span: #20 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #24 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #24 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #24 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #24 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #24 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #24 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #24 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "PATH",
+                                        span: #0 bytes(658..662),
+                                    },
+                                    Punct {
+                                        ch: '+',
+                                        spacing: Alone,
+                                        span: #0 bytes(663..664),
+                                    },
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "1",
+                                        suffix: None,
+                                        span: #0 bytes(665..666),
+                                    },
+                                ],
+                                span: #24 bytes(460..465),
+                            },
+                        ],
+                        span: #24 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #24 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #24 bytes(469..470),
+                    },
+                ],
+                span: #24 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #24 bytes(472..473),
+            },
+        ],
+        span: #24 bytes(430..483),
+    },
+]
index 695f5506d5e38aadb36977a37f8e02c128ef450d..4ddea2c27b2a634263b583da8368661d2d09a78b 100644 (file)
@@ -23,6 +23,9 @@ LL |     a(x, y);
    |     ^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12
index a28f7aa3e08ca73b14f95ae8b84d032875f333cd..a9cf128bb621a4bdec7167e1dee1573b058c6597 100644 (file)
@@ -23,6 +23,9 @@ LL |     a(x, y, z);
    |     ^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
index 37f7fcf2e331a882e5a4e2594f7c14a5d1454f50..db86572f1cf73a4c1ddde1973abfd164a76976c0 100644 (file)
@@ -23,6 +23,9 @@ LL |     a(x, y);
    |     ^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12
index f92923a112584138fcfd35dd36c0da70356438b5..bf325d5601348697cdedd2dffb7e52b1ac020544 100644 (file)
@@ -10,6 +10,9 @@ LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to dyn Dummy
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/regions-trait-object-subtyping.rs:22:5
@@ -23,6 +26,9 @@ LL |     x
    |     ^ returning this value requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to dyn Dummy
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs
deleted file mode 100644 (file)
index 518aa20..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#[link(name = "foo")]
-extern "C" {
-    #[link_ordinal(42)]
-    //~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature
-    fn foo();
-}
-
-fn main() {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr
deleted file mode 100644 (file)
index dbee5f3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[link_ordinal]` attribute is an experimental feature
-  --> $DIR/feature-gate-raw-dylib-2.rs:3:5
-   |
-LL |     #[link_ordinal(42)]
-   |     ^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs
deleted file mode 100644 (file)
index 29edd0f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#[link(name = "foo", kind = "raw-dylib")]
-//~^ ERROR: kind="raw-dylib" is unstable
-extern "C" {}
-
-fn main() {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr
deleted file mode 100644 (file)
index a670b6c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: kind="raw-dylib" is unstable
-  --> $DIR/feature-gate-raw-dylib.rs:1:1
-   |
-LL | #[link(name = "foo", kind = "raw-dylib")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
-   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs
new file mode 100644 (file)
index 0000000..e9690f0
--- /dev/null
@@ -0,0 +1,8 @@
+// only-windows-gnu
+// check-pass
+// compile-flags: --crate-type lib
+#![feature(raw_dylib)]
+//~^ WARNING: the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr
new file mode 100644 (file)
index 0000000..6e24112
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/raw-dylib-msvc-only.rs:4:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+  --> $DIR/raw-dylib-msvc-only.rs:6:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
new file mode 100644 (file)
index 0000000..7a5d7ac
--- /dev/null
@@ -0,0 +1,7 @@
+// ignore-windows
+// compile-flags: --crate-type lib
+#![feature(raw_dylib)]
+//~^ WARNING: the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
+extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
new file mode 100644 (file)
index 0000000..f3879b6
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/raw-dylib-windows-only.rs:3:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+error: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
+  --> $DIR/raw-dylib-windows-only.rs:5:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/rustdoc/deny-invalid-doc-attrs.rs b/src/test/ui/rustdoc/deny-invalid-doc-attrs.rs
new file mode 100644 (file)
index 0000000..02e9c67
--- /dev/null
@@ -0,0 +1,7 @@
+#![deny(invalid_doc_attributes)]
+//~^ NOTE defined here
+#![doc(x)]
+//~^ ERROR unknown `doc` attribute `x`
+//~| WARNING will become a hard error
+//~| NOTE see issue #82730
+fn main() {}
diff --git a/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr b/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
new file mode 100644 (file)
index 0000000..a14ab8f
--- /dev/null
@@ -0,0 +1,16 @@
+error: unknown `doc` attribute `x`
+  --> $DIR/deny-invalid-doc-attrs.rs:3:8
+   |
+LL | #![doc(x)]
+   |        ^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-invalid-doc-attrs.rs:1:9
+   |
+LL | #![deny(invalid_doc_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rustdoc/doc-inline-extern-crate.rs b/src/test/ui/rustdoc/doc-inline-extern-crate.rs
new file mode 100644 (file)
index 0000000..0eb4c14
--- /dev/null
@@ -0,0 +1,9 @@
+#[doc(inline)]
+//~^ ERROR conflicting
+#[doc(no_inline)]
+pub extern crate core;
+
+// no warning
+pub extern crate alloc;
+
+fn main() {}
diff --git a/src/test/ui/rustdoc/doc-inline-extern-crate.stderr b/src/test/ui/rustdoc/doc-inline-extern-crate.stderr
new file mode 100644 (file)
index 0000000..4151829
--- /dev/null
@@ -0,0 +1,13 @@
+error: conflicting doc inlining attributes
+  --> $DIR/doc-inline-extern-crate.rs:1:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^ this attribute...
+LL |
+LL | #[doc(no_inline)]
+   |       ^^^^^^^^^ ...conflicts with this attribute
+   |
+   = help: remove one of the conflicting attributes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/issue-85915-simd-ptrs.rs b/src/test/ui/simd/issue-85915-simd-ptrs.rs
new file mode 100644 (file)
index 0000000..6fe4155
--- /dev/null
@@ -0,0 +1,67 @@
+// run-pass
+// ignore-emscripten
+
+// Short form of the generic gather/scatter tests,
+// verifying simd([*const T; N]) and simd([*mut T; N]) pass typeck and work.
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct cptrx4<T>([*const T; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct mptrx4<T>([*mut T; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4([f32; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct i32x4([i32; 4]);
+
+extern "platform-intrinsic" {
+    fn simd_gather<T, U, V>(x: T, y: U, z: V) -> T;
+    fn simd_scatter<T, U, V>(x: T, y: U, z: V) -> ();
+}
+
+fn main() {
+    let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
+
+    let default = f32x4([-3_f32, -3., -3., -3.]);
+    let s_strided = f32x4([0_f32, 2., -3., 6.]);
+    let mask = i32x4([-1_i32, -1, 0, -1]);
+
+    // reading from *const
+    unsafe {
+        let pointer = &x as *const f32;
+        let pointers =  cptrx4([
+            pointer.offset(0) as *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        ]);
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // writing to *mut
+    unsafe {
+        let pointer = &mut x as *mut f32;
+        let pointers = mptrx4([
+            pointer.offset(0) as *mut f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        ]);
+
+        let values = f32x4([42_f32, 43_f32, 44_f32, 45_f32]);
+        simd_scatter(values, pointers, mask);
+
+        assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
+    }
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs b/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs
new file mode 100644 (file)
index 0000000..ae321c9
--- /dev/null
@@ -0,0 +1,23 @@
+// run-pass
+// ignore-emscripten
+
+#![feature(extern_types)]
+#![feature(repr_simd)]
+
+use std::ptr::NonNull;
+
+extern {
+    type Extern;
+}
+
+#[repr(simd)]
+struct S<T>(T);
+
+#[inline(never)]
+fn identity<T>(v: T) -> T {
+    v
+}
+
+fn main() {
+    let _v: S<[Option<NonNull<Extern>>; 4]> = identity(S([None; 4]));
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs
new file mode 100644 (file)
index 0000000..3e02b08
--- /dev/null
@@ -0,0 +1,12 @@
+// build-fail
+
+#![feature(repr_simd)]
+
+// error-pattern:monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+#[repr(simd)]
+struct S<T>(T);
+
+fn main() {
+    let _v: Option<S<[*mut [u8]; 4]>> = None;
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr
new file mode 100644 (file)
index 0000000..3888e7a
--- /dev/null
@@ -0,0 +1,4 @@
+error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/simd-type-wide-ptr.rs b/src/test/ui/simd/simd-type-wide-ptr.rs
new file mode 100644 (file)
index 0000000..88f62a0
--- /dev/null
@@ -0,0 +1,12 @@
+// build-fail
+
+#![feature(repr_simd)]
+
+// error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+#[repr(simd)]
+struct S([*mut [u8]; 4]);
+
+fn main() {
+    let _v: Option<S> = None;
+}
diff --git a/src/test/ui/simd/simd-type-wide-ptr.stderr b/src/test/ui/simd/simd-type-wide-ptr.stderr
new file mode 100644 (file)
index 0000000..51d3c00
--- /dev/null
@@ -0,0 +1,4 @@
+error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/wasm-simd-indirect.rs b/src/test/ui/simd/wasm-simd-indirect.rs
new file mode 100644 (file)
index 0000000..deac593
--- /dev/null
@@ -0,0 +1,33 @@
+// build-pass
+
+#![cfg_attr(target_arch = "wasm32", feature(wasm_simd, wasm_target_feature))]
+
+#[cfg(target_arch = "wasm32")]
+fn main() {
+    unsafe {
+        a::api_with_simd_feature();
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod a {
+    use std::arch::wasm32::*;
+
+    #[target_feature(enable = "simd128")]
+    pub unsafe fn api_with_simd_feature() {
+        crate::b::api_takes_v128(u64x2(0, 1));
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod b {
+    use std::arch::wasm32::*;
+
+    #[inline(never)]
+    pub fn api_takes_v128(a: v128) -> v128 {
+        a
+    }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn main() {}
index b251e8a438ac1c79fda0763694e425e3c3e11f2a..723c4a7a1fbf0672233b6d440ce2b21d3418fe9c 100644 (file)
@@ -1,11 +1,11 @@
-error: lifetime parameter `'a` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
+error: lifetime parameter `'b` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |          ^^-
-   |          |
-   |          this lifetime is only used here
-   |          help: elide the single-use lifetime
+   |                      ^^-
+   |                      |
+   |                      this lifetime is only used here
+   |                      help: elide the single-use lifetime
    |
 note: the lint level is defined here
   --> $DIR/one-use-in-fn-argument-in-band.rs:4:9
@@ -13,14 +13,14 @@ note: the lint level is defined here
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: lifetime parameter `'b` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |                      ^^-
-   |                      |
-   |                      this lifetime is only used here
-   |                      help: elide the single-use lifetime
+   |          ^^-
+   |          |
+   |          this lifetime is only used here
+   |          help: elide the single-use lifetime
 
 error: aborting due to 2 previous errors
 
index d2eea15f3988619895f9d6c0bed32a0f2d24cc76..fa59d7a031397530d9114219be96e3c8097302f9 100644 (file)
@@ -1,4 +1,4 @@
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[b09c]::Id::This) }, (I,)), [])`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
index c3e3f543d7998b2f688fc298b253245a554af366..99523f8eb645d5877260abc8b62f03ee0215f949 100644 (file)
@@ -169,10 +169,10 @@ LL |     let _: Alias5<isize> = Alias5::Some(0);
    |            ^^^^^^^^^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
-  --> $DIR/generics-default-stability.rs:231:34
+  --> $DIR/generics-default-stability.rs:231:27
    |
 LL |     let _: Enum4<isize> = Enum4::Some(1);
-   |                                  ^^^^
+   |                           ^^^^^^^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:231:12
@@ -193,10 +193,10 @@ LL |     let _: Enum4<usize> = ENUM4;
    |            ^^^^^^^^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum4::Some`: test
-  --> $DIR/generics-default-stability.rs:237:34
+  --> $DIR/generics-default-stability.rs:237:27
    |
 LL |     let _: Enum4<isize> = Enum4::Some(0);
-   |                                  ^^^^
+   |                           ^^^^^^^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum4`: test
   --> $DIR/generics-default-stability.rs:237:12
@@ -205,10 +205,10 @@ LL |     let _: Enum4<isize> = Enum4::Some(0);
    |            ^^^^^^^^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
-  --> $DIR/generics-default-stability.rs:242:34
+  --> $DIR/generics-default-stability.rs:242:27
    |
 LL |     let _: Enum5<isize> = Enum5::Some(1);
-   |                                  ^^^^
+   |                           ^^^^^^^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:242:12
@@ -229,10 +229,10 @@ LL |     let _: Enum5<usize> = ENUM5;
    |            ^^^^^^^^^^^^
 
 warning: use of deprecated variant `unstable_generic_param::Enum5::Some`: test
-  --> $DIR/generics-default-stability.rs:249:34
+  --> $DIR/generics-default-stability.rs:249:27
    |
 LL |     let _: Enum5<isize> = Enum5::Some(0);
-   |                                  ^^^^
+   |                           ^^^^^^^^^^^
 
 warning: use of deprecated enum `unstable_generic_param::Enum5`: test
   --> $DIR/generics-default-stability.rs:249:12
index 63930e7f787fd3f6d11abb3ee0d87c2f8c9b232f..599a79fc08af46d9922128d10f5e24a08c3d1b90 100644 (file)
@@ -3,4 +3,8 @@ fn main() {
     //~^ ERROR mismatched types
     let b: String = &format!("b");
     //~^ ERROR mismatched types
+    let c: String = &mut format!("c");
+    //~^ ERROR mismatched types
+    let d: String = &mut (format!("d"));
+    //~^ ERROR mismatched types
 }
index 05d8fcd3ed64b97b134958facd55091acbd79558..0881b024712c5daa1c75b39100f5e4a420d6cbba 100644 (file)
@@ -18,6 +18,26 @@ LL |     let b: String = &format!("b");
    |            |        help: consider removing the borrow: `format!("b")`
    |            expected due to this
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:6:21
+   |
+LL |     let c: String = &mut format!("c");
+   |            ------   ^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("c")`
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:8:21
+   |
+LL |     let d: String = &mut (format!("d"));
+   |            ------   ^^^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("d")`
+   |            expected due to this
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
new file mode 100644 (file)
index 0000000..390d8bb
--- /dev/null
@@ -0,0 +1,9 @@
+// Regression test for #85943: should not emit suggestions for adding
+// indirection to type parameters in where-clauses when suggesting
+// adding `?Sized`.
+struct A<T>(T) where T: Send;
+struct B(A<[u8]>);
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
new file mode 100644 (file)
index 0000000..735aeb0
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          - required by this bound in `A`
+LL | struct B(A<[u8]>);
+   |          ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          ^  - ...if indirection were used here: `Box<T>`
+   |          |
+   |          this could be changed to `T: ?Sized`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index de4d35e261ca7aea1f5660538916a03991ea5104..3dd2b19fbf987f9cc290979b09f0988ac9c06fd5 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17hd75b915511563828E)
+error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::hd75b915511563828)
+error: demangling(basic::main::h6c535bbea2051f85)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
index d871a4ee829f0ee05c07aeca5826f5e0b3e93cf8..bd107c10207078d8b8b39559267a962648f066bd 100644 (file)
@@ -9,8 +9,8 @@
 //[legacy]~^ ERROR symbol-name(_ZN5basic4main
 //[legacy]~| ERROR demangling(basic::main
 //[legacy]~| ERROR demangling-alt(basic::main)
- //[v0]~^^^^ ERROR symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
-    //[v0]~| ERROR demangling(basic[de7d5b6b69c71f37]::main)
+ //[v0]~^^^^ ERROR symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
+    //[v0]~| ERROR demangling(basic[17891616a171812d]::main)
     //[v0]~| ERROR demangling-alt(basic::main)
 #[rustc_def_path]
 //[legacy]~^ ERROR def-path(main)
index e30fa6f66d5143b09c42ba5e2ab13c06c2920d2e..519efc9d7b4b9725a9016ab8461b3465bc841f60 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
+error: symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic[de7d5b6b69c71f37]::main)
+error: demangling(basic[17891616a171812d]::main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
index 05c6b8352de63634f9a95f8507518befb69de33a..bd7e1c0f336983d4aba2b65a50fb974be5889bf0 100644 (file)
@@ -5,32 +5,32 @@
 pub struct Unsigned<const F: u8>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
+//~^ ERROR symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
 impl Unsigned<11> {}
 
 pub struct Signed<const F: i16>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
+//~^ ERROR symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
 impl Signed<-152> {}
 
 pub struct Bool<const F: bool>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
+//~^ ERROR symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
 impl Bool<true> {}
 
 pub struct Char<const F: char>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
+//~^ ERROR symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
 impl Char<'∂'> {}
 
index 05c485d001f03dab9b9b6aa18c8cd25fe72528c0..13995403f7791ee4a1d2371a3f75f360e1fc608b 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+error: symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
@@ -16,13 +16,13 @@ error: demangling-alt(<const_generics_demangling::Unsigned<11>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
+error: symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
@@ -34,13 +34,13 @@ error: demangling-alt(<const_generics_demangling::Signed<-152>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
+error: symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
@@ -52,13 +52,13 @@ error: demangling-alt(<const_generics_demangling::Bool<true>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
+error: symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
index 960049be7936f032248a61d60a608564ec3f08c7..b0b31a57d0692db4359d0019a4fed440466a7519 100644 (file)
@@ -15,8 +15,8 @@ impl Foo {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar
         //[legacy]~| ERROR demangling(impl1::foo::Foo::bar
         //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
-            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
+            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::bar)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(foo::Foo::bar)
@@ -33,8 +33,8 @@ impl Foo {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
         //[legacy]~| ERROR demangling(impl1::bar::<impl impl1::foo::Foo>::baz
         //[legacy]~| ERROR demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
-            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
+            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::baz)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(bar::<impl foo::Foo>::baz)
@@ -63,8 +63,8 @@ fn method(&self) {}
             //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
             //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
             //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
-             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-                //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+                //[v0]~| ERROR demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
                 //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
             //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
index a7c3a389909a4f75eb72f329f21258c07b64eb3a..e5b0deee36e3c0bb72112610a2cda0348b32a924 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
+error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
@@ -22,13 +22,13 @@ error: def-path(foo::Foo::bar)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
+error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
@@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
index 52d0c66639835ec7b9925d03cbb0b52a1feff85b..8357678399235c3f303d5ed8b37f436dd227683e 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h18eaa05e22e59176E)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h18eaa05e22e59176)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
index a313c1ef3832679ed500ee1c8d18bde70e93eeae..3238eb1e579f079c736cb18b631421890887d697 100644 (file)
@@ -22,8 +22,8 @@ impl Foo<::llvm::Foo> {
         //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
         //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo
         //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
-            //[v0]~| ERROR demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+            //[v0]~| ERROR demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
         pub(crate) fn foo() {
             for _ in 0..0 {
index 5d99abff59ab5a0151eddecd9f6de6919b9e028f..6a5885e1ea32b08149fdd6cf06598f5ba986eab8 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
+error: demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
index 0f721fc1f89c8e4f8f17bc7a91b4a7c3464e1ba2..4d061cafef3b2d99a125b57220c50d18a269dcfc 100644 (file)
@@ -42,8 +42,8 @@ impl<I, T, E> Iterator2 for Foo<I, E>
     //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next
     //[legacy]~| ERROR demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next
     //[legacy]~| ERROR demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
-    //[v0]~^^^^  ERROR symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
-    //[v0]~|     ERROR demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
+    //[v0]~^^^^  ERROR symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+    //[v0]~|     ERROR demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
     //[v0]~|     ERROR demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
     fn next(&mut self) -> Option<Self::Item> {
         self.find(|_| true)
index 093ba8c857685969558a729809c5c14f3cbd5d69..98844aafb65528ac8f7210198a7c52537282a2bd 100644 (file)
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
+error: demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
index 5ada82dfb2df61e79551b564418ee05bc8cc0824..2b09318f06c74806386f6f668cc805dfd1a74c2f 100644 (file)
@@ -4,7 +4,7 @@ error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3f8b57f879016e18]::Bar>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
   --> $DIR/trait-objects.rs:16:5
    |
 LL |     #[rustc_symbol_name]
@@ -22,7 +22,7 @@ error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3op
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Foo>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
   --> $DIR/trait-objects.rs:28:5
    |
 LL |     #[rustc_symbol_name]
@@ -40,7 +40,7 @@ error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3o
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Baz>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
   --> $DIR/trait-objects.rs:40:5
    |
 LL |     #[rustc_symbol_name]
index 164830fecee578fe159df2edd8010f4151cdf3d5..7cdf404242d5e41cc98e3325953a822293c2bb70 100644 (file)
@@ -27,6 +27,7 @@
 // gate-test-f16c_target_feature
 // gate-test-riscv_target_feature
 // gate-test-ermsb_target_feature
+// gate-test-bpf_target_feature
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
index 2d6abcc0a0150d46aabe57d95d84834d1424f043..ee542b60a26344b7984ab4aa9d1938a4b48b10d6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:31:18
+  --> $DIR/gate.rs:32:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/test-attrs/test-type.rs b/src/test/ui/test-attrs/test-type.rs
new file mode 100644 (file)
index 0000000..3f0fa81
--- /dev/null
@@ -0,0 +1,28 @@
+// compile-flags: --test
+// run-flags: --test-threads=1
+// check-run-results
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// ignore-emscripten no threads support
+// run-pass
+
+
+#[test]
+fn test_ok() {
+    let _a = true;
+}
+
+#[test]
+#[should_panic]
+fn test_panic() {
+    panic!();
+}
+
+#[test]
+#[ignore]
+fn test_no_run() {
+    loop{
+        println!("Hello, world");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/test-attrs/test-type.run.stdout b/src/test/ui/test-attrs/test-type.run.stdout
new file mode 100644 (file)
index 0000000..be2fd8a
--- /dev/null
@@ -0,0 +1,8 @@
+
+running 3 tests
+test test_no_run ... ignored
+test test_ok ... ok
+test test_panic - should panic ... ok
+
+test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
index 15b19676a7c2d21846fbda6f1dc164578e40213c..8a91732a754ac56a4b837fe09d1599155ce3d34f 100644 (file)
@@ -2,7 +2,7 @@
 running 4 tests
 test it_fails ... about to fail
 FAILED
-test it_panics ... about to panic
+test it_panics - should panic ... about to panic
 ok
 test it_works ... about to succeed
 ok
index 467f834afecbf81fd361fec6c5ccd32af2dd4ecd..f608a8cdc55692fe6904f4471f16d9eb67633bd9 100644 (file)
@@ -2,7 +2,7 @@
 running 5 tests
 test it_exits ... FAILED
 test it_fails ... FAILED
-test it_panics ... ok
+test it_panics - should panic ... ok
 test it_works ... ok
 test no_residual_environment ... ok
 
index 75e4cb3e2d819436dc17c742a3ac991c07d76e86..bd7cbd444d70409e6f75db1332a4452fd206de87 100644 (file)
@@ -79,7 +79,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&str`
+   |               help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:19:15
@@ -88,7 +88,7 @@ LL | static TEST4: _ = 145;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:22:15
@@ -210,7 +210,7 @@ LL |     static B: _ = 42;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:80:15
@@ -244,7 +244,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&str`
+   |                      help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:92:22
@@ -253,7 +253,7 @@ LL |     static FN_TEST4: _ = 145;
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `i32`
+   |                      help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:95:22
@@ -435,7 +435,7 @@ LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
    |          |
    |          not allowed in type signatures
-   |          help: replace `_` with the correct type: `Option<u8>`
+   |          help: replace with the correct type: `Option<u8>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:144:31
@@ -526,7 +526,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:201:26
@@ -639,7 +639,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error: aborting due to 69 previous errors; 1 warning emitted
 
index c6758c52a914ed39394aa8c1e6240af5e6b51845..afd6aaf4e55ab6b81a3036fe4093a931e065f931 100644 (file)
@@ -70,7 +70,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&str`
+   |               help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:19:15
@@ -79,7 +79,7 @@ LL | static TEST4: _ = 145;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:22:15
@@ -201,7 +201,7 @@ LL |     static B: _ = 42;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:80:15
@@ -235,7 +235,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&str`
+   |                      help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:92:22
@@ -244,7 +244,7 @@ LL |     static FN_TEST4: _ = 145;
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `i32`
+   |                      help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:95:22
@@ -426,7 +426,7 @@ LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
    |          |
    |          not allowed in type signatures
-   |          help: replace `_` with the correct type: `Option<u8>`
+   |          help: replace with the correct type: `Option<u8>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:144:31
@@ -517,7 +517,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:201:26
@@ -630,7 +630,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error: aborting due to 69 previous errors
 
index f868c8d483486f30f267bf540fbeda84688e8f5a..2b64df774b08f2f6b23b6060240ab994ffee1cc4 100644 (file)
@@ -14,7 +14,7 @@ LL | const TEST2: _ = 42u32;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `u32`
+   |              help: replace with the correct type: `u32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:10:14
@@ -23,7 +23,7 @@ LL | const TEST3: _ = Some(42);
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `Option<i32>`
+   |              help: replace with the correct type: `Option<i32>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:13:22
@@ -38,7 +38,7 @@ LL |     const TEST5: _ = 42;
    |                  ^
    |                  |
    |                  not allowed in type signatures
-   |                  help: replace `_` with the correct type: `i32`
+   |                  help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:24:18
@@ -47,7 +47,7 @@ LL |     const TEST6: _ = 13;
    |                  ^
    |                  |
    |                  not allowed in type signatures
-   |                  help: replace `_` with the correct type: `i32`
+   |                  help: replace with the correct type: `i32`
 
 error: aborting due to 6 previous errors
 
index 4e605caafe22e95cd74118f629c43b9ba23f9bad..1e19b7b21d8bf0fe387029852b8afa4d6df12add 100644 (file)
@@ -85,6 +85,8 @@
     "armv7r-none-eabihf",
     "armv7s-apple-ios",
     "asmjs-unknown-emscripten",
+    "bpfeb-unknown-none",
+    "bpfel-unknown-none",
     "i386-apple-ios",
     "i586-pc-windows-msvc",
     "i586-unknown-linux-gnu",
index ec1572c26c262acc21ace9b4e95479828d4d86cd..a46a7407df0ceba21331d46cf938be5a0c8c2bc6 100644 (file)
@@ -7,8 +7,7 @@
 
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
-use rustc_ast::ast::{self, MetaItem, MetaItemKind};
+use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
@@ -56,20 +55,6 @@ fn doc_hidden(&self) -> bool {
         *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
     }
 
-    fn has_include(meta: Option<MetaItem>) -> bool {
-        if_chain! {
-            if let Some(meta) = meta;
-            if let MetaItemKind::List(list) = meta.kind;
-            if let Some(meta) = list.get(0);
-            if let Some(name) = meta.ident();
-            then {
-                name.name == sym::include
-            } else {
-                false
-            }
-        }
-    }
-
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_>,
@@ -95,7 +80,7 @@ fn check_missing_docs_attrs(
 
         let has_doc = attrs
             .iter()
-            .any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
+            .any(|a| a.doc_str().is_some());
         if !has_doc {
             span_lint(
                 cx,
index 04711f864886b06aab41b07bef741e9a2e84271d..e00c7fbfed15745932a1929049ef96f943ae5fd2 100644 (file)
@@ -1,5 +1,4 @@
 #![warn(clippy::missing_docs_in_private_items)]
-#![feature(external_doc)]
-#![doc(include = "../../README.md")]
+#![doc = include_str!("../../README.md")]
 
 fn main() {}
index d53e19f2908e4ad85681ca6cc34b47e0bd329f1a..08ee8fc984ddf3f3b1fa45abd761a21db8e64ac3 100644 (file)
@@ -664,6 +664,10 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
                     ignore,
                     should_panic,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: test::TestType::Unknown,
                 },
                 testfn: make_test_closure(config, testpaths, revision),
index 54b079a3e861057422fe1e075d786b2c10517385..931c822ffe265b63f68eb3a08d4a60642aaf7b1e 100644 (file)
@@ -1835,6 +1835,7 @@ fn build_auxiliary(&self, source_path: &str, aux_dir: &Path) -> bool {
             || self.config.target.contains("nvptx")
             || self.is_vxworks_pure_static()
             || self.config.target.contains("sgx")
+            || self.config.target.contains("bpf")
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -2675,12 +2676,11 @@ fn check_rustdoc_test_option(&self, res: ProcRes) {
 
         let mut tested = 0;
         for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| {
-            let tmp: Vec<&str> = s.split(" - ").collect();
-            if tmp.len() == 2 {
-                let path = tmp[0].rsplit("test ").next().unwrap();
+            if let Some((left, right)) = s.split_once(" - ") {
+                let path = left.rsplit("test ").next().unwrap();
                 if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) {
                     tested += 1;
-                    let mut iter = tmp[1].split("(line ");
+                    let mut iter = right.split("(line ");
                     iter.next();
                     let line = iter
                         .next()
index 7dbd70948b84d87a1b834ed10b3dee992153760a..37164c4e5752a26aeb2e837a95a74c077d1b9bed 100644 (file)
@@ -48,6 +48,8 @@
     ("armv7s", "arm"),
     ("asmjs", "asmjs"),
     ("avr", "avr"),
+    ("bpfeb", "bpf"),
+    ("bpfel", "bpf"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),