]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #75485 - RalfJung:pin, r=nagisa
authorTyler Mandry <tmandry@gmail.com>
Sun, 16 Aug 2020 21:59:32 +0000 (14:59 -0700)
committerGitHub <noreply@github.com>
Sun, 16 Aug 2020 21:59:32 +0000 (14:59 -0700)
pin docs: add some forward references

@nagisa had some questions about pinning that were answered in the docs, which they did not realize because that discussion is below the examples. I still think it makes sense to introduce the examples before that discussion, since it give the discussion something concrete to refer to, but this PR adds some forward references so people don't think the examples conclude the docs.

@nagisa do you think this would have helped?

616 files changed:
Cargo.lock
config.toml.example
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/tests.rs [new file with mode: 0644]
library/alloc/src/collections/btree/mod.rs
library/alloc/src/collections/btree/node.rs
library/alloc/src/collections/btree/node/tests.rs [new file with mode: 0644]
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/btree/set/tests.rs [new file with mode: 0644]
library/alloc/src/lib.rs
library/alloc/src/vec.rs
library/alloc/tests/btree/map.rs [deleted file]
library/alloc/tests/btree/mod.rs [deleted file]
library/alloc/tests/btree/set.rs [deleted file]
library/alloc/tests/btree_set_hash.rs [new file with mode: 0644]
library/alloc/tests/lib.rs
library/core/src/array/mod.rs
library/core/src/char/convert.rs
library/core/src/hint.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/mem/manually_drop.rs
library/core/src/mem/maybe_uninit.rs
library/core/src/option.rs
library/core/src/str/mod.rs
library/core/tests/array.rs
library/core/tests/lib.rs
library/std/Cargo.toml
library/std/build.rs
library/std/src/ffi/c_str.rs
library/std/src/ffi/mod.rs
library/std/src/ffi/os_str.rs
library/std/src/keyword_docs.rs
library/std/src/net/addr.rs
library/std/src/net/ip.rs
library/std/src/net/mod.rs
library/std/src/net/parser.rs
library/std/src/net/tcp.rs
library/std/src/net/udp.rs
library/std/src/os/freebsd/fs.rs
library/std/src/os/raw/char.md
library/std/src/os/raw/double.md
library/std/src/os/raw/float.md
library/std/src/os/raw/int.md
library/std/src/os/raw/long.md
library/std/src/os/raw/longlong.md
library/std/src/os/raw/schar.md
library/std/src/os/raw/short.md
library/std/src/os/raw/uchar.md
library/std/src/os/raw/uint.md
library/std/src/os/raw/ulong.md
library/std/src/os/raw/ulonglong.md
library/std/src/os/raw/ushort.md
library/std/src/path.rs
library/std/src/primitive_docs.rs
library/std/src/process.rs
library/std/src/sys/unix/time.rs
library/std/src/sys/vxworks/ext/fs.rs
library/std/src/sys/vxworks/ext/process.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/builder.rs
src/bootstrap/config.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
src/librustc_arena/lib.rs
src/librustc_ast/Cargo.toml
src/librustc_ast/ast.rs
src/librustc_ast/ast/tests.rs
src/librustc_ast/crate_disambiguator.rs
src/librustc_ast/lib.rs
src/librustc_ast/node_id.rs
src/librustc_ast/ptr.rs
src/librustc_ast/token.rs
src/librustc_ast/tokenstream.rs
src/librustc_ast/util/literal.rs
src/librustc_ast/util/parser.rs
src/librustc_ast/visit.rs
src/librustc_ast_lowering/item.rs
src/librustc_attr/builtin.rs
src/librustc_attr/lib.rs
src/librustc_builtin_macros/format.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/coverageinfo/mod.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_ssa/Cargo.toml
src/librustc_codegen_ssa/back/link.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/lib.rs
src/librustc_codegen_ssa/mir/debuginfo.rs
src/librustc_codegen_ssa/traits/coverageinfo.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/fingerprint.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/sorted_map.rs
src/librustc_data_structures/svh.rs
src/librustc_data_structures/thin_vec.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/lib.rs
src/librustc_error_codes/error_codes/E0477.md
src/librustc_error_codes/error_codes/E0752.md
src/librustc_errors/Cargo.toml
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/json.rs
src/librustc_errors/json/tests.rs
src/librustc_errors/lib.rs
src/librustc_errors/snippet.rs
src/librustc_expand/Cargo.toml
src/librustc_expand/lib.rs
src/librustc_expand/mbe.rs
src/librustc_expand/mbe/macro_rules.rs
src/librustc_hir/Cargo.toml
src/librustc_hir/arena.rs
src/librustc_hir/def.rs
src/librustc_hir/definitions.rs
src/librustc_hir/hir.rs
src/librustc_hir/hir_id.rs
src/librustc_hir/lang_items.rs
src/librustc_hir/lib.rs
src/librustc_incremental/Cargo.toml
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/data.rs
src/librustc_index/Cargo.toml
src/librustc_index/bit_set.rs
src/librustc_index/vec.rs
src/librustc_infer/Cargo.toml
src/librustc_infer/infer/error_reporting/mod.rs
src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs
src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
src/librustc_infer/infer/free_regions.rs
src/librustc_infer/lib.rs
src/librustc_interface/Cargo.toml
src/librustc_interface/interface.rs
src/librustc_interface/passes.rs
src/librustc_interface/queries.rs
src/librustc_interface/util.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/builtin.rs
src/librustc_lint/early.rs
src/librustc_lint/late.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_macros/src/lib.rs
src/librustc_macros/src/serialize.rs [new file with mode: 0644]
src/librustc_macros/src/symbols.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/dependency_format.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/rmeta/decoder.rs
src/librustc_metadata/rmeta/encoder.rs
src/librustc_metadata/rmeta/mod.rs
src/librustc_metadata/rmeta/table.rs
src/librustc_middle/Cargo.toml
src/librustc_middle/arena.rs
src/librustc_middle/dep_graph/dep_node.rs
src/librustc_middle/dep_graph/mod.rs
src/librustc_middle/hir/exports.rs
src/librustc_middle/hir/map/mod.rs
src/librustc_middle/hir/mod.rs
src/librustc_middle/hir/place.rs
src/librustc_middle/infer/canonical.rs
src/librustc_middle/lib.rs
src/librustc_middle/middle/codegen_fn_attrs.rs
src/librustc_middle/middle/cstore.rs
src/librustc_middle/middle/dependency_format.rs
src/librustc_middle/middle/exported_symbols.rs
src/librustc_middle/middle/region.rs
src/librustc_middle/middle/resolve_lifetime.rs
src/librustc_middle/mir/interpret/allocation.rs
src/librustc_middle/mir/interpret/error.rs
src/librustc_middle/mir/interpret/mod.rs
src/librustc_middle/mir/interpret/pointer.rs
src/librustc_middle/mir/interpret/value.rs
src/librustc_middle/mir/mod.rs
src/librustc_middle/mir/mono.rs
src/librustc_middle/mir/predecessors.rs
src/librustc_middle/mir/query.rs
src/librustc_middle/mir/terminator/mod.rs
src/librustc_middle/query/mod.rs
src/librustc_middle/traits/mod.rs
src/librustc_middle/traits/specialization_graph.rs
src/librustc_middle/ty/adjustment.rs
src/librustc_middle/ty/binding.rs
src/librustc_middle/ty/cast.rs
src/librustc_middle/ty/codec.rs
src/librustc_middle/ty/consts.rs
src/librustc_middle/ty/consts/kind.rs
src/librustc_middle/ty/context.rs
src/librustc_middle/ty/error.rs
src/librustc_middle/ty/fast_reject.rs
src/librustc_middle/ty/instance.rs
src/librustc_middle/ty/layout.rs
src/librustc_middle/ty/list.rs
src/librustc_middle/ty/mod.rs
src/librustc_middle/ty/print/pretty.rs
src/librustc_middle/ty/query/mod.rs
src/librustc_middle/ty/query/on_disk_cache.rs
src/librustc_middle/ty/query/profiling_support.rs
src/librustc_middle/ty/sty.rs
src/librustc_middle/ty/subst.rs
src/librustc_middle/ty/trait_def.rs
src/librustc_middle/ty/util.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
src/librustc_mir/borrow_check/diagnostics/mod.rs
src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
src/librustc_mir/borrow_check/diagnostics/region_name.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/universal_regions.rs
src/librustc_mir/const_eval/eval_queries.rs
src/librustc_mir/const_eval/fn_queries.rs
src/librustc_mir/interpret/intern.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/polymorphize.rs
src/librustc_mir/transform/add_retag.rs
src/librustc_mir/transform/check_consts/validation.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/deaggregator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/instrument_coverage.rs
src/librustc_mir/transform/match_branches.rs [new file with mode: 0644]
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/transform/simplify_try.rs
src/librustc_mir/transform/uninhabited_enum_branching.rs
src/librustc_mir/transform/unreachable_prop.rs
src/librustc_mir_build/Cargo.toml
src/librustc_mir_build/build/mod.rs
src/librustc_mir_build/lib.rs
src/librustc_mir_build/lints.rs
src/librustc_mir_build/thir/cx/expr.rs
src/librustc_mir_build/thir/pattern/check_match.rs
src/librustc_parse/Cargo.toml
src/librustc_parse/lexer/mod.rs
src/librustc_parse/lexer/unescape_error_reporting.rs
src/librustc_parse/lib.rs
src/librustc_parse/parser/attr.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/item.rs
src/librustc_parse/parser/mod.rs
src/librustc_parse/parser/path.rs
src/librustc_passes/Cargo.toml
src/librustc_passes/dead.rs
src/librustc_passes/lib.rs
src/librustc_passes/reachable.rs
src/librustc_passes/region.rs
src/librustc_passes/upvars.rs
src/librustc_privacy/Cargo.toml
src/librustc_privacy/lib.rs
src/librustc_query_system/Cargo.toml
src/librustc_query_system/dep_graph/dep_node.rs
src/librustc_query_system/dep_graph/graph.rs
src/librustc_query_system/dep_graph/prev.rs
src/librustc_query_system/dep_graph/serialized.rs
src/librustc_query_system/lib.rs
src/librustc_query_system/query/caches.rs
src/librustc_query_system/query/plumbing.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/def_collector.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/imports.rs
src/librustc_resolve/late.rs
src/librustc_resolve/late/diagnostics.rs
src/librustc_resolve/late/lifetimes.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_serialize/Cargo.toml
src/librustc_serialize/collection_impls.rs
src/librustc_serialize/json.rs
src/librustc_serialize/lib.rs
src/librustc_serialize/serialize.rs
src/librustc_serialize/tests/json.rs
src/librustc_serialize/tests/opaque.rs
src/librustc_session/Cargo.toml
src/librustc_session/cgu_reuse_tracker.rs
src/librustc_session/config.rs
src/librustc_session/filesearch.rs
src/librustc_session/lib.rs
src/librustc_session/search_paths.rs
src/librustc_session/session.rs
src/librustc_session/utils.rs
src/librustc_span/Cargo.toml
src/librustc_span/def_id.rs
src/librustc_span/edition.rs
src/librustc_span/hygiene.rs
src/librustc_span/lib.rs
src/librustc_span/source_map.rs
src/librustc_span/symbol.rs
src/librustc_symbol_mangling/Cargo.toml
src/librustc_symbol_mangling/legacy.rs
src/librustc_symbol_mangling/lib.rs
src/librustc_target/Cargo.toml
src/librustc_target/abi/mod.rs
src/librustc_target/asm/mod.rs
src/librustc_target/lib.rs
src/librustc_target/spec/abi.rs
src/librustc_target/spec/i686_pc_windows_gnu.rs
src/librustc_target/spec/i686_uwp_windows_gnu.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/windows_gnu_base.rs
src/librustc_target/spec/windows_uwp_gnu_base.rs
src/librustc_target/spec/x86_64_pc_windows_gnu.rs
src/librustc_target/spec/x86_64_uwp_windows_gnu.rs
src/librustc_trait_selection/Cargo.toml
src/librustc_trait_selection/lib.rs
src/librustc_trait_selection/opaque_types.rs
src/librustc_trait_selection/traits/chalk_fulfill.rs
src/librustc_trait_selection/traits/error_reporting/mod.rs
src/librustc_trait_selection/traits/error_reporting/suggestions.rs
src/librustc_trait_selection/traits/project.rs
src/librustc_trait_selection/traits/query/normalize.rs
src/librustc_trait_selection/traits/specialize/mod.rs
src/librustc_trait_selection/traits/util.rs
src/librustc_traits/Cargo.toml
src/librustc_traits/lib.rs
src/librustc_ty/Cargo.toml
src/librustc_ty/instance.rs
src/librustc_ty/lib.rs
src/librustc_ty/ty.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/collect/type_of.rs
src/librustc_typeck/impl_wf_check/min_specialization.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/outlives/implicit_infer.rs
src/librustc_typeck/outlives/mod.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/utils.rs
src/librustdoc/core.rs
src/librustdoc/html/markdown.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_trait_impls.rs
src/librustdoc/visit_ast.rs
src/rustllvm/CoverageMappingWrapper.cpp
src/test/codegen/naked-functions.rs
src/test/debuginfo/function-arguments-naked.rs [deleted file]
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit [new file with mode: 0644]
src/test/mir-opt/matches_reduce_branches.rs [new file with mode: 0644]
src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit [new file with mode: 0644]
src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit [new file with mode: 0644]
src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit [new file with mode: 0644]
src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit [new file with mode: 0644]
src/test/mir-opt/matches_u8.rs [new file with mode: 0644]
src/test/run-make-fulldeps/instrument-coverage/Makefile
src/test/run-make-fulldeps/instrument-coverage/expected_export_coverage.json
src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt [new file with mode: 0644]
src/test/run-make-fulldeps/instrument-coverage/main.rs [deleted file]
src/test/run-make-fulldeps/instrument-coverage/testprog.rs [new file with mode: 0644]
src/test/run-make-fulldeps/instrument-coverage/typical_show_coverage.txt
src/test/run-make-fulldeps/sanitizer-cdylib-link/Makefile
src/test/run-make-fulldeps/sanitizer-dylib-link/Makefile
src/test/run-make-fulldeps/sanitizer-staticlib-link/Makefile
src/test/run-make-fulldeps/save-analysis/foo.rs
src/test/ui-fulldeps/derive-no-std-not-supported.rs [deleted file]
src/test/ui-fulldeps/deriving-encodable-decodable-box.rs
src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
src/test/ui-fulldeps/deriving-global.rs
src/test/ui-fulldeps/deriving-hygiene.rs
src/test/ui-fulldeps/empty-struct-braces-derive.rs
src/test/ui-fulldeps/issue-11881.rs
src/test/ui-fulldeps/issue-14021.rs
src/test/ui-fulldeps/issue-15924.rs
src/test/ui-fulldeps/issue-24972.rs
src/test/ui-fulldeps/issue-4016.rs
src/test/ui-fulldeps/rustc_encodable_hygiene.rs
src/test/ui/associated-types/missing-associated-types.stderr
src/test/ui/ast-json/ast-json-noexpand-output.stdout
src/test/ui/ast-json/ast-json-output.stdout
src/test/ui/bad/bad-sized.stderr
src/test/ui/const-generics/apit-with-const-param.rs
src/test/ui/const-generics/apit-with-const-param.stderr [deleted file]
src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/array-size-in-generic-struct-param.rs
src/test/ui/const-generics/array-size-in-generic-struct-param.stderr [deleted file]
src/test/ui/const-generics/broken-mir-1.rs
src/test/ui/const-generics/broken-mir-1.stderr [deleted file]
src/test/ui/const-generics/broken-mir-2.rs
src/test/ui/const-generics/broken-mir-2.stderr [deleted file]
src/test/ui/const-generics/cannot-infer-const-args.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/cannot-infer-const-args.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/cannot-infer-const-args.rs
src/test/ui/const-generics/cannot-infer-const-args.stderr [deleted file]
src/test/ui/const-generics/coerce_unsized_array.rs
src/test/ui/const-generics/concrete-const-as-fn-arg.rs
src/test/ui/const-generics/concrete-const-as-fn-arg.stderr [deleted file]
src/test/ui/const-generics/concrete-const-impl-method.rs
src/test/ui/const-generics/concrete-const-impl-method.stderr [deleted file]
src/test/ui/const-generics/condition-in-trait-const-arg.rs
src/test/ui/const-generics/condition-in-trait-const-arg.stderr [deleted file]
src/test/ui/const-generics/const-arg-in-fn.rs
src/test/ui/const-generics/const-arg-in-fn.stderr [deleted file]
src/test/ui/const-generics/const-argument-non-static-lifetime.rs
src/test/ui/const-generics/const-argument-non-static-lifetime.stderr [deleted file]
src/test/ui/const-generics/const-expression-parameter.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-expression-parameter.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-expression-parameter.rs
src/test/ui/const-generics/const-expression-parameter.stderr [deleted file]
src/test/ui/const-generics/const-fn-with-const-param.rs
src/test/ui/const-generics/const-fn-with-const-param.stderr [deleted file]
src/test/ui/const-generics/const-generic-array-wrapper.rs
src/test/ui/const-generics/const-generic-array-wrapper.stderr [deleted file]
src/test/ui/const-generics/const-generic-type_name.rs
src/test/ui/const-generics/const-generic-type_name.stderr [deleted file]
src/test/ui/const-generics/const-param-after-const-literal-arg.rs
src/test/ui/const-generics/const-param-elided-lifetime.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-elided-lifetime.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-elided-lifetime.rs
src/test/ui/const-generics/const-param-elided-lifetime.stderr [deleted file]
src/test/ui/const-generics/const-param-from-outer-fn.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-from-outer-fn.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-from-outer-fn.rs
src/test/ui/const-generics/const-param-from-outer-fn.stderr [deleted file]
src/test/ui/const-generics/const-param-in-trait.rs
src/test/ui/const-generics/const-param-in-trait.stderr [deleted file]
src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr [deleted file]
src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr [deleted file]
src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-parameter-uppercase-lint.rs
src/test/ui/const-generics/const-parameter-uppercase-lint.stderr [deleted file]
src/test/ui/const-generics/const-types.rs
src/test/ui/const-generics/const-types.stderr [deleted file]
src/test/ui/const-generics/derive-debug-array-wrapper.rs
src/test/ui/const-generics/derive-debug-array-wrapper.stderr [deleted file]
src/test/ui/const-generics/different_byref.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_byref.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_byref.rs
src/test/ui/const-generics/different_byref.stderr [deleted file]
src/test/ui/const-generics/different_byref_simple.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_byref_simple.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_byref_simple.rs [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-call.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-call.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-call.rs
src/test/ui/const-generics/fn-const-param-call.stderr [deleted file]
src/test/ui/const-generics/fn-const-param-infer.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-infer.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-infer.rs
src/test/ui/const-generics/fn-const-param-infer.stderr [deleted file]
src/test/ui/const-generics/fn-taking-const-generic-array.rs
src/test/ui/const-generics/fn-taking-const-generic-array.stderr [deleted file]
src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/forbid-non-structural_match-types.rs
src/test/ui/const-generics/forbid-non-structural_match-types.stderr [deleted file]
src/test/ui/const-generics/foreign-item-const-parameter.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/foreign-item-const-parameter.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/foreign-item-const-parameter.rs
src/test/ui/const-generics/foreign-item-const-parameter.stderr [deleted file]
src/test/ui/const-generics/impl-const-generic-struct.rs
src/test/ui/const-generics/impl-const-generic-struct.stderr [deleted file]
src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/incorrect-number-of-const-args.rs
src/test/ui/const-generics/incorrect-number-of-const-args.stderr [deleted file]
src/test/ui/const-generics/infer_arg_from_pat.rs
src/test/ui/const-generics/infer_arg_from_pat.stderr [deleted file]
src/test/ui/const-generics/infer_arr_len_from_pat.rs
src/test/ui/const-generics/infer_arr_len_from_pat.stderr [deleted file]
src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs
src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr [deleted file]
src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-61522-array-len-succ.rs
src/test/ui/const-generics/issue-61522-array-len-succ.stderr [deleted file]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs
src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr [deleted file]
src/test/ui/const-generics/issue-68104-print-stack-overflow.rs
src/test/ui/const-generics/issue-70180-1-stalled_on.rs
src/test/ui/const-generics/issue-70180-2-stalled_on.rs
src/test/ui/const-generics/issue-71986.rs
src/test/ui/const-generics/mut-ref-const-param-array.rs
src/test/ui/const-generics/mut-ref-const-param-array.stderr [deleted file]
src/test/ui/const-generics/nested-type.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/nested-type.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/nested-type.rs
src/test/ui/const-generics/nested-type.stderr [deleted file]
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr [deleted file]
src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param-deref.rs
src/test/ui/const-generics/raw-ptr-const-param-deref.stderr [deleted file]
src/test/ui/const-generics/raw-ptr-const-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/raw-ptr-const-param.rs
src/test/ui/const-generics/raw-ptr-const-param.stderr [deleted file]
src/test/ui/const-generics/slice-const-param-mismatch.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/slice-const-param-mismatch.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/slice-const-param-mismatch.rs
src/test/ui/const-generics/slice-const-param-mismatch.stderr [deleted file]
src/test/ui/const-generics/slice-const-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/slice-const-param.rs
src/test/ui/const-generics/slice-const-param.stderr [deleted file]
src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/struct-with-invalid-const-param.rs
src/test/ui/const-generics/trait-const-args.rs
src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs
src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr [deleted file]
src/test/ui/const-generics/type_of_anon_const.rs
src/test/ui/const-generics/type_of_anon_const.stderr [deleted file]
src/test/ui/const-generics/uninferred-consts.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/uninferred-consts.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/uninferred-consts.rs
src/test/ui/const-generics/uninferred-consts.stderr [deleted file]
src/test/ui/const-generics/unknown_adt.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/unknown_adt.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/unknown_adt.rs
src/test/ui/const-generics/unknown_adt.stderr [deleted file]
src/test/ui/const-generics/unused-const-param.rs
src/test/ui/const-generics/unused-const-param.stderr [deleted file]
src/test/ui/const-generics/unused_braces.full.fixed [new file with mode: 0644]
src/test/ui/const-generics/unused_braces.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/unused_braces.min.fixed [new file with mode: 0644]
src/test/ui/const-generics/unused_braces.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/unused_braces.rs
src/test/ui/const-generics/unused_braces.stderr [deleted file]
src/test/ui/const-generics/wf-misc.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/wf-misc.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/wf-misc.rs
src/test/ui/const-generics/wf-misc.stderr [deleted file]
src/test/ui/error-codes/E0225.stderr
src/test/ui/error-codes/E0424.rs
src/test/ui/error-codes/E0424.stderr
src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs [new file with mode: 0644]
src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr [new file with mode: 0644]
src/test/ui/issues/issue-22560.stderr
src/test/ui/issues/issue-32963.stderr
src/test/ui/issues/issue-5099.rs
src/test/ui/issues/issue-5099.stderr
src/test/ui/issues/issue-66768.rs [new file with mode: 0644]
src/test/ui/issues/issue-75307.rs [new file with mode: 0644]
src/test/ui/issues/issue-75307.stderr [new file with mode: 0644]
src/test/ui/mir/issue-75419-validation-impl-trait.rs [new file with mode: 0644]
src/test/ui/parser/expr-as-stmt-2.rs [new file with mode: 0644]
src/test/ui/parser/expr-as-stmt-2.stderr [new file with mode: 0644]
src/test/ui/parser/expr-as-stmt.fixed
src/test/ui/parser/expr-as-stmt.rs
src/test/ui/parser/expr-as-stmt.stderr
src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
src/test/ui/parser/removed-syntax-field-let.rs
src/test/ui/parser/removed-syntax-field-let.stderr
src/test/ui/parser/trait-object-trait-parens.stderr
src/test/ui/polymorphization/predicates.rs
src/test/ui/polymorphization/symbol-ambiguity.rs [new file with mode: 0644]
src/test/ui/resolve/issue-2356.stderr
src/test/ui/suggestions/missing-lifetime-specifier.rs
src/test/ui/suggestions/missing-lifetime-specifier.stderr
src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr
src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr
src/test/ui/traits/wf-trait-object-no-duplicates.stderr
src/test/ui/unknown-llvm-arg.rs [new file with mode: 0644]
src/test/ui/unknown-llvm-arg.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/clippy/clippy_lints/src/derive.rs
src/tools/clippy/clippy_lints/src/new_without_default.rs
src/tools/compiletest/Cargo.toml
src/tools/compiletest/src/errors.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/util.rs
triagebot.toml

index f6b5b317646c363daf2d4954297d3fee77abcf5d..c1fa3bef07c7ef294074f36ac1f5cefe0f620eda 100644 (file)
@@ -3334,6 +3334,7 @@ dependencies = [
  "rustc_hir",
  "rustc_incremental",
  "rustc_index",
+ "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
  "rustc_session",
@@ -3364,6 +3365,7 @@ dependencies = [
  "rustc-rayon-core",
  "rustc_graphviz",
  "rustc_index",
+ "rustc_macros",
  "rustc_serialize",
  "smallvec 1.4.0",
  "stable_deref_trait",
@@ -3416,6 +3418,7 @@ dependencies = [
  "annotate-snippets 0.8.0",
  "atty",
  "rustc_data_structures",
+ "rustc_macros",
  "rustc_serialize",
  "rustc_span",
  "termcolor",
@@ -3437,6 +3440,7 @@ dependencies = [
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
+ "rustc_macros",
  "rustc_parse",
  "rustc_serialize",
  "rustc_session",
@@ -3499,6 +3503,7 @@ dependencies = [
  "rustc_fs_util",
  "rustc_graphviz",
  "rustc_hir",
+ "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
  "rustc_session",
@@ -3511,6 +3516,7 @@ name = "rustc_index"
 version = "0.0.0"
 dependencies = [
  "arrayvec 0.5.1",
+ "rustc_macros",
  "rustc_serialize",
 ]
 
@@ -3640,6 +3646,7 @@ dependencies = [
  "rustc_hir",
  "rustc_hir_pretty",
  "rustc_index",
+ "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
  "rustc_session",
@@ -3815,6 +3822,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_index",
+ "rustc_macros",
  "rustc_serialize",
  "rustc_span",
  "smallvec 1.4.0",
@@ -3869,6 +3877,7 @@ name = "rustc_serialize"
 version = "0.0.0"
 dependencies = [
  "indexmap",
+ "rustc_macros",
  "smallvec 1.4.0",
 ]
 
@@ -3884,6 +3893,7 @@ dependencies = [
  "rustc_errors",
  "rustc_feature",
  "rustc_fs_util",
+ "rustc_macros",
  "rustc_serialize",
  "rustc_span",
  "rustc_target",
index a9835ad12ad5a6f93e468e84b7b16e4de514f70b..36587cc07844147be96b41801e9f6961fc7d5398 100644 (file)
 # This only applies from stage 1 onwards, and only for Windows targets.
 #control-flow-guard = false
 
+# Enable symbol-mangling-version v0. This can be helpful when profiling rustc,
+# as generics will be preserved in symbols (rather than erased into opaque T).
+#new-symbol-mangling = false
+
 # =============================================================================
 # Options for specific targets
 #
index e7d243bfcb0f75d00c6c246026b3b508f0b86737..c6b55840db99369ffad7f0a28f054a13e6276a01 100644 (file)
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 use core::borrow::Borrow;
 use core::cmp::Ordering;
 use core::fmt::{self, Debug};
@@ -245,7 +243,7 @@ fn take(&mut self, key: &Q) -> Option<K> {
     fn replace(&mut self, key: K) -> Option<K> {
         let root = Self::ensure_is_owned(&mut self.root);
         match search::search_tree::<marker::Mut<'_>, K, (), K>(root.node_as_mut(), &key) {
-            Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
+            Found(handle) => Some(mem::replace(handle.into_key_mut(), key)),
             GoDown(handle) => {
                 VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
                     .insert(());
@@ -811,7 +809,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
     {
         let root_node = self.root.as_mut()?.node_as_mut();
         match search::search_tree(root_node, key) {
-            Found(handle) => Some(handle.into_kv_mut().1),
+            Found(handle) => Some(handle.into_val_mut()),
             GoDown(_) => None,
         }
     }
@@ -1288,11 +1286,7 @@ pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
     pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
         let root_node = self.root.as_mut().map(|r| r.node_as_mut());
         let front = root_node.map(|rn| rn.first_leaf_edge());
-        DrainFilterInner {
-            length: &mut self.length,
-            cur_leaf_edge: front,
-            emptied_internal_root: false,
-        }
+        DrainFilterInner { length: &mut self.length, cur_leaf_edge: front }
     }
 
     /// Calculates the number of elements if it is incorrect.
@@ -1708,7 +1702,6 @@ pub struct DrainFilter<'a, K, V, F>
 pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
     length: &'a mut usize,
     cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
-    emptied_internal_root: bool,
 }
 
 #[unstable(feature = "btree_drain_filter", issue = "70530")]
@@ -1749,17 +1742,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-impl<K, V> Drop for DrainFilterInner<'_, K, V> {
-    fn drop(&mut self) {
-        if self.emptied_internal_root {
-            if let Some(handle) = self.cur_leaf_edge.take() {
-                let root = handle.into_node().into_root_mut();
-                root.pop_internal_level();
-            }
-        }
-    }
-}
-
 impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
     /// Allow Debug implementations to predict the next element.
     pub(super) fn peek(&self) -> Option<(&K, &V)> {
@@ -1776,7 +1758,7 @@ pub(super) fn next<F>(&mut self, pred: &mut F) -> Option<(K, V)>
             let (k, v) = kv.kv_mut();
             if pred(k, v) {
                 *self.length -= 1;
-                let (kv, pos) = kv.remove_kv_tracking(|_| self.emptied_internal_root = true);
+                let (kv, pos) = kv.remove_kv_tracking();
                 self.cur_leaf_edge = Some(pos);
                 return Some(kv);
             }
@@ -2748,7 +2730,7 @@ pub fn get_mut(&mut self) -> &mut V {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_mut(self) -> &'a mut V {
-        self.handle.into_kv_mut().1
+        self.handle.into_val_mut()
     }
 
     /// Sets the value of the entry with the `OccupiedEntry`'s key,
@@ -2799,39 +2781,32 @@ pub fn remove(self) -> V {
     fn remove_kv(self) -> (K, V) {
         *self.length -= 1;
 
-        let (old_kv, _) =
-            self.handle.remove_kv_tracking(|root| root.into_root_mut().pop_internal_level());
+        let (old_kv, _) = self.handle.remove_kv_tracking();
         old_kv
     }
 }
 
 impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
-    /// Removes a key/value-pair from the tree, and returns that pair, as well as
-    /// the leaf edge corresponding to that former pair. It's possible this leaves
-    /// an empty internal root node, which the caller should subsequently pop from
-    /// the map holding the tree. The caller should also decrement the map's length.
-    fn remove_kv_tracking<F>(
+    /// Removes a key/value-pair from the map, and returns that pair, as well as
+    /// the leaf edge corresponding to that former pair.
+    fn remove_kv_tracking(
         self,
-        handle_emptied_internal_root: F,
-    ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>)
-    where
-        F: FnOnce(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
-    {
+    ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
         let (old_kv, mut pos, was_internal) = match self.force() {
             Leaf(leaf) => {
                 let (old_kv, pos) = leaf.remove();
                 (old_kv, pos, false)
             }
             Internal(mut internal) => {
-                // Replace the location freed in the internal node with the next KV,
-                // and remove that next KV from its leaf.
+                // Replace the location freed in the internal node with an
+                // adjacent KV, and remove that adjacent KV from its leaf.
+                // Always choose the adjacent KV on the left side because
+                // it is typically faster to pop an element from the end
+                // of the KV arrays without needing to shift other elements.
 
                 let key_loc = internal.kv_mut().0 as *mut K;
                 let val_loc = internal.kv_mut().1 as *mut V;
 
-                // Deleting from the left side is typically faster since we can
-                // just pop an element from the end of the KV array without
-                // needing to shift the other values.
                 let to_remove = internal.left_edge().descend().last_leaf_edge().left_kv().ok();
                 let to_remove = unsafe { unwrap_unchecked(to_remove) };
 
@@ -2867,8 +2842,8 @@ fn remove_kv_tracking<F>(
                     if parent.len() == 0 {
                         // The parent that was just emptied must be the root,
                         // because nodes on a lower level would not have been
-                        // left underfull. It has to be popped off the tree soon.
-                        handle_emptied_internal_root(parent);
+                        // left with a single child.
+                        parent.into_root_mut().pop_internal_level();
                         break;
                     } else {
                         cur_node = parent.forget_type();
@@ -2972,19 +2947,15 @@ fn handle_underfull_node<K, V>(
         Err(_) => return AtRoot,
     };
 
+    // Prefer the left KV if it exists. Merging with the left side is faster,
+    // since merging happens towards the left and `node` has fewer elements.
+    // Stealing from the left side is faster, since we can pop from the end of
+    // the KV arrays.
     let (is_left, mut handle) = match parent.left_kv() {
         Ok(left) => (true, left),
         Err(parent) => {
-            match parent.right_kv() {
-                Ok(right) => (false, right),
-                Err(_) => {
-                    // The underfull node has an empty parent, so it is the only child
-                    // of an empty root. It is destined to become the new root, thus
-                    // allowed to be underfull. The empty parent should be removed later
-                    // by `pop_internal_level`.
-                    return AtRoot;
-                }
-            }
+            let right = unsafe { unwrap_unchecked(parent.right_kv().ok()) };
+            (false, right)
         }
     };
 
@@ -3024,3 +2995,6 @@ fn next(&mut self) -> Option<(K, V)> {
         }
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
new file mode 100644 (file)
index 0000000..910e704
--- /dev/null
@@ -0,0 +1,1491 @@
+use crate::boxed::Box;
+use crate::collections::btree_map::Entry::{Occupied, Vacant};
+use crate::collections::BTreeMap;
+use crate::fmt::Debug;
+use crate::rc::Rc;
+use crate::string::String;
+use crate::string::ToString;
+use crate::vec::Vec;
+use std::convert::TryFrom;
+use std::iter::FromIterator;
+use std::mem;
+use std::ops::Bound::{self, Excluded, Included, Unbounded};
+use std::ops::RangeBounds;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use super::super::DeterministicRng;
+
+// Value of node::CAPACITY, thus capacity of a tree with a single level,
+// i.e. a tree who's root is a leaf node at height 0.
+const NODE_CAPACITY: usize = 11;
+
+// Minimum number of elements to insert in order to guarantee a tree with 2 levels,
+// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes.
+// It's not the minimum size: removing an element from such a tree does not always reduce height.
+const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
+
+// Minimum number of elements to insert in order to guarantee a tree with 3 levels,
+// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes.
+// It's not the minimum size: removing an element from such a tree does not always reduce height.
+const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1;
+
+// Gather all references from a mutable iterator and make sure Miri notices if
+// using them is dangerous.
+fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
+    // Gather all those references.
+    let mut refs: Vec<&mut T> = iter.collect();
+    // Use them all. Twice, to be sure we got all interleavings.
+    for r in refs.iter_mut() {
+        mem::swap(dummy, r);
+    }
+    for r in refs {
+        mem::swap(dummy, r);
+    }
+}
+
+#[test]
+fn test_basic_large() {
+    let mut map = BTreeMap::new();
+    // Miri is too slow
+    let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 };
+    assert_eq!(map.len(), 0);
+
+    for i in 0..size {
+        assert_eq!(map.insert(i, 10 * i), None);
+        assert_eq!(map.len(), i + 1);
+    }
+
+    assert_eq!(map.first_key_value(), Some((&0, &0)));
+    assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1)))));
+    assert_eq!(map.first_entry().unwrap().key(), &0);
+    assert_eq!(map.last_entry().unwrap().key(), &(size - 1));
+
+    for i in 0..size {
+        assert_eq!(map.get(&i).unwrap(), &(i * 10));
+    }
+
+    for i in size..size * 2 {
+        assert_eq!(map.get(&i), None);
+    }
+
+    for i in 0..size {
+        assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+        assert_eq!(map.len(), size);
+    }
+
+    for i in 0..size {
+        assert_eq!(map.get(&i).unwrap(), &(i * 100));
+    }
+
+    for i in 0..size / 2 {
+        assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+        assert_eq!(map.len(), size - i - 1);
+    }
+
+    for i in 0..size / 2 {
+        assert_eq!(map.get(&(2 * i)), None);
+        assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
+    }
+
+    for i in 0..size / 2 {
+        assert_eq!(map.remove(&(2 * i)), None);
+        assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+        assert_eq!(map.len(), size / 2 - i - 1);
+    }
+}
+
+#[test]
+fn test_basic_small() {
+    let mut map = BTreeMap::new();
+    // Empty, root is absent (None):
+    assert_eq!(map.remove(&1), None);
+    assert_eq!(map.len(), 0);
+    assert_eq!(map.get(&1), None);
+    assert_eq!(map.get_mut(&1), None);
+    assert_eq!(map.first_key_value(), None);
+    assert_eq!(map.last_key_value(), None);
+    assert_eq!(map.keys().count(), 0);
+    assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
+    assert_eq!(map.insert(1, 1), None);
+
+    // 1 key-value pair:
+    assert_eq!(map.len(), 1);
+    assert_eq!(map.get(&1), Some(&1));
+    assert_eq!(map.get_mut(&1), Some(&mut 1));
+    assert_eq!(map.first_key_value(), Some((&1, &1)));
+    assert_eq!(map.last_key_value(), Some((&1, &1)));
+    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
+    assert_eq!(map.values().collect::<Vec<_>>(), vec![&1]);
+    assert_eq!(map.insert(1, 2), Some(1));
+    assert_eq!(map.len(), 1);
+    assert_eq!(map.get(&1), Some(&2));
+    assert_eq!(map.get_mut(&1), Some(&mut 2));
+    assert_eq!(map.first_key_value(), Some((&1, &2)));
+    assert_eq!(map.last_key_value(), Some((&1, &2)));
+    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
+    assert_eq!(map.values().collect::<Vec<_>>(), vec![&2]);
+    assert_eq!(map.insert(2, 4), None);
+
+    // 2 key-value pairs:
+    assert_eq!(map.len(), 2);
+    assert_eq!(map.get(&2), Some(&4));
+    assert_eq!(map.get_mut(&2), Some(&mut 4));
+    assert_eq!(map.first_key_value(), Some((&1, &2)));
+    assert_eq!(map.last_key_value(), Some((&2, &4)));
+    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1, &2]);
+    assert_eq!(map.values().collect::<Vec<_>>(), vec![&2, &4]);
+    assert_eq!(map.remove(&1), Some(2));
+
+    // 1 key-value pair:
+    assert_eq!(map.len(), 1);
+    assert_eq!(map.get(&1), None);
+    assert_eq!(map.get_mut(&1), None);
+    assert_eq!(map.get(&2), Some(&4));
+    assert_eq!(map.get_mut(&2), Some(&mut 4));
+    assert_eq!(map.first_key_value(), Some((&2, &4)));
+    assert_eq!(map.last_key_value(), Some((&2, &4)));
+    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&2]);
+    assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
+    assert_eq!(map.remove(&2), Some(4));
+
+    // Empty but root is owned (Some(...)):
+    assert_eq!(map.len(), 0);
+    assert_eq!(map.get(&1), None);
+    assert_eq!(map.get_mut(&1), None);
+    assert_eq!(map.first_key_value(), None);
+    assert_eq!(map.last_key_value(), None);
+    assert_eq!(map.keys().count(), 0);
+    assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
+    assert_eq!(map.remove(&1), None);
+}
+
+#[test]
+fn test_iter() {
+    // Miri is too slow
+    let size = if cfg!(miri) { 200 } else { 10000 };
+
+    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    fn test<T>(size: usize, mut iter: T)
+    where
+        T: Iterator<Item = (usize, usize)>,
+    {
+        for i in 0..size {
+            assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+            assert_eq!(iter.next().unwrap(), (i, i));
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+    }
+    test(size, map.iter().map(|(&k, &v)| (k, v)));
+    test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+    test(size, map.into_iter());
+}
+
+#[test]
+fn test_iter_rev() {
+    // Miri is too slow
+    let size = if cfg!(miri) { 200 } else { 10000 };
+
+    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    fn test<T>(size: usize, mut iter: T)
+    where
+        T: Iterator<Item = (usize, usize)>,
+    {
+        for i in 0..size {
+            assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+            assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+    }
+    test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
+    test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
+    test(size, map.into_iter().rev());
+}
+
+/// Specifically tests iter_mut's ability to mutate the value of pairs in-line
+fn do_test_iter_mut_mutation<T>(size: usize)
+where
+    T: Copy + Debug + Ord + TryFrom<usize>,
+    <T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
+{
+    let zero = T::try_from(0).unwrap();
+    let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
+
+    // Forward and backward iteration sees enough pairs (also tested elsewhere)
+    assert_eq!(map.iter_mut().count(), size);
+    assert_eq!(map.iter_mut().rev().count(), size);
+
+    // Iterate forwards, trying to mutate to unique values
+    for (i, (k, v)) in map.iter_mut().enumerate() {
+        assert_eq!(*k, T::try_from(i).unwrap());
+        assert_eq!(*v, zero);
+        *v = T::try_from(i + 1).unwrap();
+    }
+
+    // Iterate backwards, checking that mutations succeeded and trying to mutate again
+    for (i, (k, v)) in map.iter_mut().rev().enumerate() {
+        assert_eq!(*k, T::try_from(size - i - 1).unwrap());
+        assert_eq!(*v, T::try_from(size - i).unwrap());
+        *v = T::try_from(2 * size - i).unwrap();
+    }
+
+    // Check that backward mutations succeeded
+    for (i, (k, v)) in map.iter_mut().enumerate() {
+        assert_eq!(*k, T::try_from(i).unwrap());
+        assert_eq!(*v, T::try_from(size + i + 1).unwrap());
+    }
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(align(32))]
+struct Align32(usize);
+
+impl TryFrom<usize> for Align32 {
+    type Error = ();
+
+    fn try_from(s: usize) -> Result<Align32, ()> {
+        Ok(Align32(s))
+    }
+}
+
+#[test]
+fn test_iter_mut_mutation() {
+    // Check many alignments and trees with roots at various heights.
+    do_test_iter_mut_mutation::<u8>(0);
+    do_test_iter_mut_mutation::<u8>(1);
+    do_test_iter_mut_mutation::<u8>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<u8>(127); // not enough unique values to test MIN_INSERTS_HEIGHT_2
+    do_test_iter_mut_mutation::<u16>(1);
+    do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_2);
+    do_test_iter_mut_mutation::<u32>(1);
+    do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_2);
+    do_test_iter_mut_mutation::<u64>(1);
+    do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_2);
+    do_test_iter_mut_mutation::<u128>(1);
+    do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_2);
+    do_test_iter_mut_mutation::<Align32>(1);
+    do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_1);
+    do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_2);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_values_mut() {
+    let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
+    test_all_refs(&mut 13, a.values_mut());
+}
+
+#[test]
+fn test_values_mut_mutation() {
+    let mut a = BTreeMap::new();
+    a.insert(1, String::from("hello"));
+    a.insert(2, String::from("goodbye"));
+
+    for value in a.values_mut() {
+        value.push_str("!");
+    }
+
+    let values: Vec<String> = a.values().cloned().collect();
+    assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_entering_root_twice() {
+    let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect();
+    let mut it = map.iter_mut();
+    let front = it.next().unwrap();
+    let back = it.next_back().unwrap();
+    assert_eq!(front, (&0, &mut 0));
+    assert_eq!(back, (&1, &mut 1));
+    *front.1 = 24;
+    *back.1 = 42;
+    assert_eq!(front, (&0, &mut 24));
+    assert_eq!(back, (&1, &mut 42));
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_descending_to_same_node_twice() {
+    let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect();
+    let mut it = map.iter_mut();
+    // Descend into first child.
+    let front = it.next().unwrap();
+    // Descend into first child again, after running through second child.
+    while it.next_back().is_some() {}
+    // Check immutable access.
+    assert_eq!(front, (&0, &mut 0));
+    // Perform mutable access.
+    *front.1 = 42;
+}
+
+#[test]
+fn test_iter_mixed() {
+    // Miri is too slow
+    let size = if cfg!(miri) { 200 } else { 10000 };
+
+    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    fn test<T>(size: usize, mut iter: T)
+    where
+        T: Iterator<Item = (usize, usize)> + DoubleEndedIterator,
+    {
+        for i in 0..size / 4 {
+            assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
+            assert_eq!(iter.next().unwrap(), (i, i));
+            assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
+        }
+        for i in size / 4..size * 3 / 4 {
+            assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
+            assert_eq!(iter.next().unwrap(), (i, i));
+        }
+        assert_eq!(iter.size_hint(), (0, Some(0)));
+        assert_eq!(iter.next(), None);
+    }
+    test(size, map.iter().map(|(&k, &v)| (k, v)));
+    test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+    test(size, map.into_iter());
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_min_max() {
+    let mut a = BTreeMap::new();
+    assert_eq!(a.iter().min(), None);
+    assert_eq!(a.iter().max(), None);
+    assert_eq!(a.iter_mut().min(), None);
+    assert_eq!(a.iter_mut().max(), None);
+    assert_eq!(a.range(..).min(), None);
+    assert_eq!(a.range(..).max(), None);
+    assert_eq!(a.range_mut(..).min(), None);
+    assert_eq!(a.range_mut(..).max(), None);
+    assert_eq!(a.keys().min(), None);
+    assert_eq!(a.keys().max(), None);
+    assert_eq!(a.values().min(), None);
+    assert_eq!(a.values().max(), None);
+    assert_eq!(a.values_mut().min(), None);
+    assert_eq!(a.values_mut().max(), None);
+    a.insert(1, 42);
+    a.insert(2, 24);
+    assert_eq!(a.iter().min(), Some((&1, &42)));
+    assert_eq!(a.iter().max(), Some((&2, &24)));
+    assert_eq!(a.iter_mut().min(), Some((&1, &mut 42)));
+    assert_eq!(a.iter_mut().max(), Some((&2, &mut 24)));
+    assert_eq!(a.range(..).min(), Some((&1, &42)));
+    assert_eq!(a.range(..).max(), Some((&2, &24)));
+    assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42)));
+    assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24)));
+    assert_eq!(a.keys().min(), Some(&1));
+    assert_eq!(a.keys().max(), Some(&2));
+    assert_eq!(a.values().min(), Some(&24));
+    assert_eq!(a.values().max(), Some(&42));
+    assert_eq!(a.values_mut().min(), Some(&mut 24));
+    assert_eq!(a.values_mut().max(), Some(&mut 42));
+}
+
+fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
+    map.range(range)
+        .map(|(&k, &v)| {
+            assert_eq!(k, v);
+            k
+        })
+        .collect()
+}
+
+#[test]
+fn test_range_small() {
+    let size = 4;
+
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+    assert_eq!(range_keys(&map, ..3), vec![1, 2]);
+    assert_eq!(range_keys(&map, 3..), vec![3, 4]);
+    assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
+}
+
+#[test]
+fn test_range_height_1() {
+    // Tests tree with a root and 2 leaves. Depending on details we don't want or need
+    // to rely upon, the single key at the root will be 6 or 7.
+
+    let map: BTreeMap<_, _> = (1..=MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect();
+    for &root in &[6, 7] {
+        assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
+        assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
+        assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
+
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
+    }
+}
+
+#[test]
+fn test_range_large() {
+    let size = 200;
+
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+    fn check<'a, L, R>(lhs: L, rhs: R)
+    where
+        L: IntoIterator<Item = (&'a i32, &'a i32)>,
+        R: IntoIterator<Item = (&'a i32, &'a i32)>,
+    {
+        let lhs: Vec<_> = lhs.into_iter().collect();
+        let rhs: Vec<_> = rhs.into_iter().collect();
+        assert_eq!(lhs, rhs);
+    }
+
+    check(map.range(..=100), map.range(..101));
+    check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
+    check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
+}
+
+#[test]
+fn test_range_inclusive_max_value() {
+    let max = usize::MAX;
+    let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
+
+    assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
+}
+
+#[test]
+fn test_range_equal_empty_cases() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
+    assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
+}
+
+#[test]
+#[should_panic]
+fn test_range_equal_excluded() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    map.range((Excluded(2), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_1() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    map.range((Included(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_2() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    map.range((Included(3), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_3() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    map.range((Excluded(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_4() {
+    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+    map.range((Excluded(3), Excluded(2)));
+}
+
+#[test]
+fn test_range_1000() {
+    // Miri is too slow
+    let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 };
+    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
+        let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
+        let mut pairs = (0..size).map(|i| (i, i));
+
+        for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+            assert_eq!(kv, pair);
+        }
+        assert_eq!(kvs.next(), None);
+        assert_eq!(pairs.next(), None);
+    }
+    test(&map, size, Included(&0), Excluded(&size));
+    test(&map, size, Unbounded, Excluded(&size));
+    test(&map, size, Included(&0), Included(&(size - 1)));
+    test(&map, size, Unbounded, Included(&(size - 1)));
+    test(&map, size, Included(&0), Unbounded);
+    test(&map, size, Unbounded, Unbounded);
+}
+
+#[test]
+fn test_range_borrowed_key() {
+    let mut map = BTreeMap::new();
+    map.insert("aardvark".to_string(), 1);
+    map.insert("baboon".to_string(), 2);
+    map.insert("coyote".to_string(), 3);
+    map.insert("dingo".to_string(), 4);
+    // NOTE: would like to use simply "b".."d" here...
+    let mut iter = map.range::<str, _>((Included("b"), Excluded("d")));
+    assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
+    assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
+    assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_range() {
+    let size = 200;
+    // Miri is too slow
+    let step = if cfg!(miri) { 66 } else { 1 };
+    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    for i in (0..size).step_by(step) {
+        for j in (i..size).step_by(step) {
+            let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
+            let mut pairs = (i..=j).map(|i| (i, i));
+
+            for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+                assert_eq!(kv, pair);
+            }
+            assert_eq!(kvs.next(), None);
+            assert_eq!(pairs.next(), None);
+        }
+    }
+}
+
+#[test]
+fn test_range_mut() {
+    let size = 200;
+    // Miri is too slow
+    let step = if cfg!(miri) { 66 } else { 1 };
+    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+    for i in (0..size).step_by(step) {
+        for j in (i..size).step_by(step) {
+            let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
+            let mut pairs = (i..=j).map(|i| (i, i));
+
+            for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+                assert_eq!(kv, pair);
+            }
+            assert_eq!(kvs.next(), None);
+            assert_eq!(pairs.next(), None);
+        }
+    }
+}
+
+mod test_drain_filter {
+    use super::*;
+
+    #[test]
+    fn empty() {
+        let mut map: BTreeMap<i32, i32> = BTreeMap::new();
+        map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn consuming_nothing() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
+    }
+
+    #[test]
+    fn consuming_all() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.clone().collect();
+        assert!(map.drain_filter(|_, _| true).eq(pairs));
+    }
+
+    #[test]
+    fn mutating_and_keeping() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        assert!(
+            map.drain_filter(|_, v| {
+                *v += 6;
+                false
+            })
+            .eq(std::iter::empty())
+        );
+        assert!(map.keys().copied().eq(0..3));
+        assert!(map.values().copied().eq(6..9));
+    }
+
+    #[test]
+    fn mutating_and_removing() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        assert!(
+            map.drain_filter(|_, v| {
+                *v += 6;
+                true
+            })
+            .eq((0..3).map(|i| (i, i + 6)))
+        );
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn underfull_keeping_all() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| false);
+        assert!(map.keys().copied().eq(0..3));
+    }
+
+    #[test]
+    fn underfull_removing_one() {
+        let pairs = (0..3).map(|i| (i, i));
+        for doomed in 0..3 {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i == doomed);
+            assert_eq!(map.len(), 2);
+        }
+    }
+
+    #[test]
+    fn underfull_keeping_one() {
+        let pairs = (0..3).map(|i| (i, i));
+        for sacred in 0..3 {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i != sacred);
+            assert!(map.keys().copied().eq(sacred..=sacred));
+        }
+    }
+
+    #[test]
+    fn underfull_removing_all() {
+        let pairs = (0..3).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| true);
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn height_0_keeping_all() {
+        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| false);
+        assert!(map.keys().copied().eq(0..NODE_CAPACITY));
+    }
+
+    #[test]
+    fn height_0_removing_one() {
+        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+        for doomed in 0..NODE_CAPACITY {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i == doomed);
+            assert_eq!(map.len(), NODE_CAPACITY - 1);
+        }
+    }
+
+    #[test]
+    fn height_0_keeping_one() {
+        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+        for sacred in 0..NODE_CAPACITY {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i != sacred);
+            assert!(map.keys().copied().eq(sacred..=sacred));
+        }
+    }
+
+    #[test]
+    fn height_0_removing_all() {
+        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| true);
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn height_0_keeping_half() {
+        let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect();
+        assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8);
+        assert_eq!(map.len(), 8);
+    }
+
+    #[test]
+    fn height_1_removing_all() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| true);
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn height_1_removing_one() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+        for doomed in 0..MIN_INSERTS_HEIGHT_1 {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i == doomed);
+            assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
+        }
+    }
+
+    #[test]
+    fn height_1_keeping_one() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+        for sacred in 0..MIN_INSERTS_HEIGHT_1 {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i != sacred);
+            assert!(map.keys().copied().eq(sacred..=sacred));
+        }
+    }
+
+    #[cfg(not(miri))] // Miri is too slow
+    #[test]
+    fn height_2_removing_one() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+        for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i == doomed);
+            assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
+        }
+    }
+
+    #[cfg(not(miri))] // Miri is too slow
+    #[test]
+    fn height_2_keeping_one() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+        for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
+            let mut map: BTreeMap<_, _> = pairs.clone().collect();
+            map.drain_filter(|i, _| *i != sacred);
+            assert!(map.keys().copied().eq(sacred..=sacred));
+        }
+    }
+
+    #[test]
+    fn height_2_removing_all() {
+        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+        let mut map: BTreeMap<_, _> = pairs.collect();
+        map.drain_filter(|_, _| true);
+        assert!(map.is_empty());
+    }
+
+    #[test]
+    fn drop_panic_leak() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+                    panic!("panic in `drop`");
+                }
+            }
+        }
+
+        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+        catch_unwind(move || {
+            drop(map.drain_filter(|i, _| {
+                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                true
+            }))
+        })
+        .unwrap_err();
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+    }
+
+    #[test]
+    fn pred_panic_leak() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                DROPS.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+        catch_unwind(AssertUnwindSafe(|| {
+            drop(map.drain_filter(|i, _| {
+                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                match i {
+                    0 => true,
+                    _ => panic!(),
+                }
+            }))
+        }))
+        .unwrap_err();
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(map.len(), 2);
+        assert_eq!(map.first_entry().unwrap().key(), &4);
+        assert_eq!(map.last_entry().unwrap().key(), &8);
+    }
+
+    // Same as above, but attempt to use the iterator again after the panic in the predicate
+    #[test]
+    fn pred_panic_reuse() {
+        static PREDS: AtomicUsize = AtomicUsize::new(0);
+        static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+        struct D;
+        impl Drop for D {
+            fn drop(&mut self) {
+                DROPS.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+
+        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+        {
+            let mut it = map.drain_filter(|i, _| {
+                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+                match i {
+                    0 => true,
+                    _ => panic!(),
+                }
+            });
+            catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
+            // Iterator behaviour after a panic is explicitly unspecified,
+            // so this is just the current implementation:
+            let result = catch_unwind(AssertUnwindSafe(|| it.next()));
+            assert!(matches!(result, Ok(None)));
+        }
+
+        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+        assert_eq!(map.len(), 2);
+        assert_eq!(map.first_entry().unwrap().key(), &4);
+        assert_eq!(map.last_entry().unwrap().key(), &8);
+    }
+}
+
+#[test]
+fn test_borrow() {
+    // make sure these compile -- using the Borrow trait
+    {
+        let mut map = BTreeMap::new();
+        map.insert("0".to_string(), 1);
+        assert_eq!(map["0"], 1);
+    }
+
+    {
+        let mut map = BTreeMap::new();
+        map.insert(Box::new(0), 1);
+        assert_eq!(map[&0], 1);
+    }
+
+    {
+        let mut map = BTreeMap::new();
+        map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
+        assert_eq!(map[&[0, 1][..]], 1);
+    }
+
+    {
+        let mut map = BTreeMap::new();
+        map.insert(Rc::new(0), 1);
+        assert_eq!(map[&0], 1);
+    }
+}
+
+#[test]
+fn test_entry() {
+    let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
+
+    let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
+
+    // Existing key (insert)
+    match map.entry(1) {
+        Vacant(_) => unreachable!(),
+        Occupied(mut view) => {
+            assert_eq!(view.get(), &10);
+            assert_eq!(view.insert(100), 10);
+        }
+    }
+    assert_eq!(map.get(&1).unwrap(), &100);
+    assert_eq!(map.len(), 6);
+
+    // Existing key (update)
+    match map.entry(2) {
+        Vacant(_) => unreachable!(),
+        Occupied(mut view) => {
+            let v = view.get_mut();
+            *v *= 10;
+        }
+    }
+    assert_eq!(map.get(&2).unwrap(), &200);
+    assert_eq!(map.len(), 6);
+
+    // Existing key (take)
+    match map.entry(3) {
+        Vacant(_) => unreachable!(),
+        Occupied(view) => {
+            assert_eq!(view.remove(), 30);
+        }
+    }
+    assert_eq!(map.get(&3), None);
+    assert_eq!(map.len(), 5);
+
+    // Inexistent key (insert)
+    match map.entry(10) {
+        Occupied(_) => unreachable!(),
+        Vacant(view) => {
+            assert_eq!(*view.insert(1000), 1000);
+        }
+    }
+    assert_eq!(map.get(&10).unwrap(), &1000);
+    assert_eq!(map.len(), 6);
+}
+
+#[test]
+fn test_extend_ref() {
+    let mut a = BTreeMap::new();
+    a.insert(1, "one");
+    let mut b = BTreeMap::new();
+    b.insert(2, "two");
+    b.insert(3, "three");
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 3);
+    assert_eq!(a[&1], "one");
+    assert_eq!(a[&2], "two");
+    assert_eq!(a[&3], "three");
+}
+
+#[test]
+fn test_zst() {
+    let mut m = BTreeMap::new();
+    assert_eq!(m.len(), 0);
+
+    assert_eq!(m.insert((), ()), None);
+    assert_eq!(m.len(), 1);
+
+    assert_eq!(m.insert((), ()), Some(()));
+    assert_eq!(m.len(), 1);
+    assert_eq!(m.iter().count(), 1);
+
+    m.clear();
+    assert_eq!(m.len(), 0);
+
+    for _ in 0..100 {
+        m.insert((), ());
+    }
+
+    assert_eq!(m.len(), 1);
+    assert_eq!(m.iter().count(), 1);
+}
+
+// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
+// do not cause segfaults when used with zero-sized values. All other map behavior is
+// undefined.
+#[test]
+fn test_bad_zst() {
+    use std::cmp::Ordering;
+
+    struct Bad;
+
+    impl PartialEq for Bad {
+        fn eq(&self, _: &Self) -> bool {
+            false
+        }
+    }
+
+    impl Eq for Bad {}
+
+    impl PartialOrd for Bad {
+        fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
+            Some(Ordering::Less)
+        }
+    }
+
+    impl Ord for Bad {
+        fn cmp(&self, _: &Self) -> Ordering {
+            Ordering::Less
+        }
+    }
+
+    let mut m = BTreeMap::new();
+
+    for _ in 0..100 {
+        m.insert(Bad, Bad);
+    }
+}
+
+#[test]
+fn test_clone() {
+    let mut map = BTreeMap::new();
+    let size = MIN_INSERTS_HEIGHT_1;
+    assert_eq!(map.len(), 0);
+
+    for i in 0..size {
+        assert_eq!(map.insert(i, 10 * i), None);
+        assert_eq!(map.len(), i + 1);
+        assert_eq!(map, map.clone());
+    }
+
+    for i in 0..size {
+        assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+        assert_eq!(map.len(), size);
+        assert_eq!(map, map.clone());
+    }
+
+    for i in 0..size / 2 {
+        assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+        assert_eq!(map.len(), size - i - 1);
+        assert_eq!(map, map.clone());
+    }
+
+    for i in 0..size / 2 {
+        assert_eq!(map.remove(&(2 * i)), None);
+        assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+        assert_eq!(map.len(), size / 2 - i - 1);
+        assert_eq!(map, map.clone());
+    }
+
+    // Test a tree with 2 chock-full levels and a tree with 3 levels.
+    map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
+    assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
+    assert_eq!(map, map.clone());
+    map.insert(0, 0);
+    assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2);
+    assert_eq!(map, map.clone());
+}
+
+#[test]
+fn test_clone_from() {
+    let mut map1 = BTreeMap::new();
+    let max_size = MIN_INSERTS_HEIGHT_1;
+
+    // Range to max_size inclusive, because i is the size of map1 being tested.
+    for i in 0..=max_size {
+        let mut map2 = BTreeMap::new();
+        for j in 0..i {
+            let mut map1_copy = map2.clone();
+            map1_copy.clone_from(&map1); // small cloned from large
+            assert_eq!(map1_copy, map1);
+            let mut map2_copy = map1.clone();
+            map2_copy.clone_from(&map2); // large cloned from small
+            assert_eq!(map2_copy, map2);
+            map2.insert(100 * j + 1, 2 * j + 1);
+        }
+        map2.clone_from(&map1); // same length
+        assert_eq!(map2, map1);
+        map1.insert(i, 10 * i);
+    }
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+    use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
+
+    fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
+        v
+    }
+    fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
+        v
+    }
+    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
+        v
+    }
+    fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
+        v
+    }
+    fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
+        v
+    }
+    fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
+        v
+    }
+    fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
+        v
+    }
+    fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
+        v
+    }
+    fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
+        v
+    }
+    fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
+        v
+    }
+}
+
+#[test]
+fn test_occupied_entry_key() {
+    let mut a = BTreeMap::new();
+    let key = "hello there";
+    let value = "value goes here";
+    assert!(a.is_empty());
+    a.insert(key.clone(), value.clone());
+    assert_eq!(a.len(), 1);
+    assert_eq!(a[key], value);
+
+    match a.entry(key.clone()) {
+        Vacant(_) => panic!(),
+        Occupied(e) => assert_eq!(key, *e.key()),
+    }
+    assert_eq!(a.len(), 1);
+    assert_eq!(a[key], value);
+}
+
+#[test]
+fn test_vacant_entry_key() {
+    let mut a = BTreeMap::new();
+    let key = "hello there";
+    let value = "value goes here";
+
+    assert!(a.is_empty());
+    match a.entry(key.clone()) {
+        Occupied(_) => panic!(),
+        Vacant(e) => {
+            assert_eq!(key, *e.key());
+            e.insert(value.clone());
+        }
+    }
+    assert_eq!(a.len(), 1);
+    assert_eq!(a[key], value);
+}
+
+#[test]
+fn test_first_last_entry() {
+    let mut a = BTreeMap::new();
+    assert!(a.first_entry().is_none());
+    assert!(a.last_entry().is_none());
+    a.insert(1, 42);
+    assert_eq!(a.first_entry().unwrap().key(), &1);
+    assert_eq!(a.last_entry().unwrap().key(), &1);
+    a.insert(2, 24);
+    assert_eq!(a.first_entry().unwrap().key(), &1);
+    assert_eq!(a.last_entry().unwrap().key(), &2);
+    a.insert(0, 6);
+    assert_eq!(a.first_entry().unwrap().key(), &0);
+    assert_eq!(a.last_entry().unwrap().key(), &2);
+    let (k1, v1) = a.first_entry().unwrap().remove_entry();
+    assert_eq!(k1, 0);
+    assert_eq!(v1, 6);
+    let (k2, v2) = a.last_entry().unwrap().remove_entry();
+    assert_eq!(k2, 2);
+    assert_eq!(v2, 24);
+    assert_eq!(a.first_entry().unwrap().key(), &1);
+    assert_eq!(a.last_entry().unwrap().key(), &1);
+}
+
+macro_rules! create_append_test {
+    ($name:ident, $len:expr) => {
+        #[test]
+        fn $name() {
+            let mut a = BTreeMap::new();
+            for i in 0..8 {
+                a.insert(i, i);
+            }
+
+            let mut b = BTreeMap::new();
+            for i in 5..$len {
+                b.insert(i, 2 * i);
+            }
+
+            a.append(&mut b);
+
+            assert_eq!(a.len(), $len);
+            assert_eq!(b.len(), 0);
+
+            for i in 0..$len {
+                if i < 5 {
+                    assert_eq!(a[&i], i);
+                } else {
+                    assert_eq!(a[&i], 2 * i);
+                }
+            }
+
+            assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1)));
+            assert_eq!(a.insert($len - 1, 20), None);
+        }
+    };
+}
+
+// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
+// Single node.
+create_append_test!(test_append_9, 9);
+// Two leafs that don't need fixing.
+create_append_test!(test_append_17, 17);
+// Two leafs where the second one ends up underfull and needs stealing at the end.
+create_append_test!(test_append_14, 14);
+// Two leafs where the second one ends up empty because the insertion finished at the root.
+create_append_test!(test_append_12, 12);
+// Three levels; insertion finished at the root.
+create_append_test!(test_append_144, 144);
+// Three levels; insertion finished at leaf while there is an empty node on the second level.
+create_append_test!(test_append_145, 145);
+// Tests for several randomly chosen sizes.
+create_append_test!(test_append_170, 170);
+create_append_test!(test_append_181, 181);
+#[cfg(not(miri))] // Miri is too slow
+create_append_test!(test_append_239, 239);
+#[cfg(not(miri))] // Miri is too slow
+create_append_test!(test_append_1700, 1700);
+
+fn rand_data(len: usize) -> Vec<(u32, u32)> {
+    let mut rng = DeterministicRng::new();
+    Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+    let mut data = rand_data(173);
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
+
+    data.sort();
+    assert!(map.into_iter().eq(data));
+    assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+    let mut data = rand_data(314);
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let right = map.split_off(&data.iter().min().unwrap().0);
+
+    data.sort();
+    assert!(map.into_iter().eq(None));
+    assert!(right.into_iter().eq(data));
+}
+
+// In a tree with 3 levels, if all but a part of the first leaf node is split off,
+// make sure fix_top eliminates both top levels.
+#[test]
+fn test_split_off_tiny_left_height_2() {
+    let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+    let mut left: BTreeMap<_, _> = pairs.clone().collect();
+    let right = left.split_off(&1);
+    assert_eq!(left.len(), 1);
+    assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1);
+    assert_eq!(*left.first_key_value().unwrap().0, 0);
+    assert_eq!(*right.first_key_value().unwrap().0, 1);
+}
+
+// In a tree with 3 levels, if only part of the last leaf node is split off,
+// make sure fix_top eliminates both top levels.
+#[test]
+fn test_split_off_tiny_right_height_2() {
+    let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+    let last = MIN_INSERTS_HEIGHT_2 - 1;
+    let mut left: BTreeMap<_, _> = pairs.clone().collect();
+    assert_eq!(*left.last_key_value().unwrap().0, last);
+    let right = left.split_off(&last);
+    assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1);
+    assert_eq!(right.len(), 1);
+    assert_eq!(*left.last_key_value().unwrap().0, last - 1);
+    assert_eq!(*right.last_key_value().unwrap().0, last);
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+    // Miri is too slow
+    let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
+    // special case with maximum height.
+    data.sort();
+
+    let mut map = BTreeMap::from_iter(data.clone());
+    let key = data[data.len() / 2].0;
+    let right = map.split_off(&key);
+
+    assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
+    assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
+}
+
+#[test]
+fn test_into_iter_drop_leak_height_0() {
+    static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+    struct D;
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut map = BTreeMap::new();
+    map.insert("a", D);
+    map.insert("b", D);
+    map.insert("c", D);
+    map.insert("d", D);
+    map.insert("e", D);
+
+    catch_unwind(move || drop(map.into_iter())).unwrap_err();
+
+    assert_eq!(DROPS.load(Ordering::SeqCst), 5);
+}
+
+#[test]
+fn test_into_iter_drop_leak_height_1() {
+    let size = MIN_INSERTS_HEIGHT_1;
+    static DROPS: AtomicUsize = AtomicUsize::new(0);
+    static PANIC_POINT: AtomicUsize = AtomicUsize::new(0);
+
+    struct D;
+    impl Drop for D {
+        fn drop(&mut self) {
+            if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    for panic_point in vec![0, 1, size - 2, size - 1] {
+        DROPS.store(0, Ordering::SeqCst);
+        PANIC_POINT.store(panic_point, Ordering::SeqCst);
+        let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
+        catch_unwind(move || drop(map.into_iter())).unwrap_err();
+        assert_eq!(DROPS.load(Ordering::SeqCst), size);
+    }
+}
+
+#[test]
+fn test_into_keys() {
+    let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+    let map: BTreeMap<_, _> = vec.into_iter().collect();
+    let keys: Vec<_> = map.into_keys().collect();
+
+    assert_eq!(keys.len(), 3);
+    assert!(keys.contains(&1));
+    assert!(keys.contains(&2));
+    assert!(keys.contains(&3));
+}
+
+#[test]
+fn test_into_values() {
+    let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+    let map: BTreeMap<_, _> = vec.into_iter().collect();
+    let values: Vec<_> = map.into_values().collect();
+
+    assert_eq!(values.len(), 3);
+    assert!(values.contains(&'a'));
+    assert!(values.contains(&'b'));
+    assert!(values.contains(&'c'));
+}
index 543ff41a4d48d55fc2b4616f39a8a17cc69c2a87..6c8a588eb58f33db5d98c32d2f53f2cb7695d80a 100644 (file)
@@ -25,3 +25,30 @@ pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
         }
     })
 }
+
+#[cfg(test)]
+/// XorShiftRng
+struct DeterministicRng {
+    x: u32,
+    y: u32,
+    z: u32,
+    w: u32,
+}
+
+#[cfg(test)]
+impl DeterministicRng {
+    fn new() -> Self {
+        DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
+    }
+
+    fn next(&mut self) -> u32 {
+        let x = self.x;
+        let t = x ^ (x << 11);
+        self.x = self.y;
+        self.y = self.z;
+        self.z = self.w;
+        let w_ = self.w;
+        self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
+        self.w
+    }
+}
index f70869148d59f2f801d49d23db9c60a5d64df8e1..acc2ae73572ba757aa801bafde1ae2e376efc2b5 100644 (file)
@@ -43,6 +43,9 @@
 const B: usize = 6;
 pub const MIN_LEN: usize = B - 1;
 pub const CAPACITY: usize = 2 * B - 1;
+const KV_IDX_CENTER: usize = B - 1;
+const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
+const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
 
 /// The underlying representation of leaf nodes.
 #[repr(C)]
@@ -413,7 +416,7 @@ pub unsafe fn deallocate_and_ascend(
 impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
     /// Unsafely asserts to the compiler some static information about whether this
     /// node is a `Leaf` or an `Internal`.
-    unsafe fn cast_unchecked<NewType>(&mut self) -> NodeRef<marker::Mut<'_>, K, V, NewType> {
+    unsafe fn cast_unchecked<NewType>(self) -> NodeRef<marker::Mut<'a>, K, V, NewType> {
         NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
     }
 
@@ -721,7 +724,7 @@ fn clone(&self) -> Self {
 }
 
 impl<Node, Type> Handle<Node, Type> {
-    /// Retrieves the node that contains the edge of key/value pair this handle points to.
+    /// Retrieves the node that contains the edge or key/value pair this handle points to.
     pub fn into_node(self) -> Node {
         self.node
     }
@@ -821,6 +824,27 @@ pub fn right_kv(self) -> Result<Handle<NodeRef<BorrowType, K, V, NodeType>, mark
     }
 }
 
+enum InsertionPlace {
+    Left(usize),
+    Right(usize),
+}
+
+/// Given an edge index where we want to insert into a node filled to capacity,
+/// computes a sensible KV index of a split point and where to perform the insertion.
+/// The goal of the split point is for its key and value to end up in a parent node;
+/// the keys, values and edges to the left of the split point become the left child;
+/// the keys, values and edges to the right of the split point become the right child.
+fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) {
+    debug_assert!(edge_idx <= CAPACITY);
+    // Rust issue #74834 tries to explain these symmetric rules.
+    match edge_idx {
+        0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)),
+        EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)),
+        EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)),
+        _ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))),
+    }
+}
+
 impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge> {
     /// Helps implementations of `insert_fit` for a particular `NodeType`,
     /// by taking care of leaf data.
@@ -863,18 +887,20 @@ fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *m
             let kv = unsafe { Handle::new_kv(self.node, self.idx) };
             (InsertResult::Fit(kv), ptr)
         } else {
-            let middle = unsafe { Handle::new_kv(self.node, B) };
+            let (middle_kv_idx, insertion) = splitpoint(self.idx);
+            let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
             let (mut left, k, v, mut right) = middle.split();
-            let ptr = if self.idx <= B {
-                unsafe { Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val) }
-            } else {
-                unsafe {
+            let ptr = match insertion {
+                InsertionPlace::Left(insert_idx) => unsafe {
+                    Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val)
+                },
+                InsertionPlace::Right(insert_idx) => unsafe {
                     Handle::new_edge(
                         right.node_as_mut().cast_unchecked::<marker::Leaf>(),
-                        self.idx - (B + 1),
+                        insert_idx,
                     )
                     .insert_fit(key, val)
-                }
+                },
             };
             (InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), ptr)
         }
@@ -936,20 +962,20 @@ fn insert(
             let kv = unsafe { Handle::new_kv(self.node, self.idx) };
             InsertResult::Fit(kv)
         } else {
-            let middle = unsafe { Handle::new_kv(self.node, B) };
+            let (middle_kv_idx, insertion) = splitpoint(self.idx);
+            let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
             let (mut left, k, v, mut right) = middle.split();
-            if self.idx <= B {
-                unsafe {
-                    Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val, edge);
-                }
-            } else {
-                unsafe {
+            match insertion {
+                InsertionPlace::Left(insert_idx) => unsafe {
+                    Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val, edge);
+                },
+                InsertionPlace::Right(insert_idx) => unsafe {
                     Handle::new_edge(
                         right.node_as_mut().cast_unchecked::<marker::Internal>(),
-                        self.idx - (B + 1),
+                        insert_idx,
                     )
                     .insert_fit(key, val, edge);
-                }
+                },
             }
             InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right })
         }
@@ -1018,6 +1044,16 @@ pub fn into_kv(self) -> (&'a K, &'a V) {
 }
 
 impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
+    pub fn into_key_mut(self) -> &'a mut K {
+        let keys = self.node.into_key_slice_mut();
+        unsafe { keys.get_unchecked_mut(self.idx) }
+    }
+
+    pub fn into_val_mut(self) -> &'a mut V {
+        let vals = self.node.into_val_slice_mut();
+        unsafe { vals.get_unchecked_mut(self.idx) }
+    }
+
     pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
         unsafe {
             let (keys, vals) = self.node.into_slices_mut();
@@ -1082,7 +1118,7 @@ pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, R
     }
 
     /// Removes the key/value pair pointed to by this handle and returns it, along with the edge
-    /// between the now adjacent key/value pairs (if any) to the left and right of this handle.
+    /// that the key/value pair collapsed into.
     pub fn remove(
         mut self,
     ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
@@ -1140,7 +1176,7 @@ pub fn can_merge(&self) -> bool {
     /// to by this handle, and the node immediately to the right of this handle into one new
     /// child of the underlying node, returning an edge referencing that new child.
     ///
-    /// Assumes that this edge `.can_merge()`.
+    /// Panics unless this edge `.can_merge()`.
     pub fn merge(
         mut self,
     ) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
@@ -1148,10 +1184,9 @@ pub fn merge(
         let self2 = unsafe { ptr::read(&self) };
         let mut left_node = self1.left_edge().descend();
         let left_len = left_node.len();
-        let mut right_node = self2.right_edge().descend();
+        let right_node = self2.right_edge().descend();
         let right_len = right_node.len();
 
-        // necessary for correctness, but in a private module
         assert!(left_len + right_len < CAPACITY);
 
         unsafe {
@@ -1182,28 +1217,25 @@ pub fn merge(
 
             (*left_node.as_leaf_mut()).len += right_len as u16 + 1;
 
-            let layout = if self.node.height > 1 {
+            if self.node.height > 1 {
+                // SAFETY: the height of the nodes being merged is one below the height
+                // of the node of this edge, thus above zero, so they are internal.
+                let mut left_node = left_node.cast_unchecked();
+                let right_node = right_node.cast_unchecked();
                 ptr::copy_nonoverlapping(
-                    right_node.cast_unchecked().as_internal().edges.as_ptr(),
-                    left_node
-                        .cast_unchecked()
-                        .as_internal_mut()
-                        .edges
-                        .as_mut_ptr()
-                        .add(left_len + 1),
+                    right_node.reborrow().as_internal().edges.as_ptr(),
+                    left_node.reborrow_mut().as_internal_mut().edges.as_mut_ptr().add(left_len + 1),
                     right_len + 1,
                 );
 
                 for i in left_len + 1..left_len + right_len + 2 {
-                    Handle::new_edge(left_node.cast_unchecked().reborrow_mut(), i)
-                        .correct_parent_link();
+                    Handle::new_edge(left_node.reborrow_mut(), i).correct_parent_link();
                 }
 
-                Layout::new::<InternalNode<K, V>>()
+                Global.dealloc(right_node.node.cast(), Layout::new::<InternalNode<K, V>>());
             } else {
-                Layout::new::<LeafNode<K, V>>()
-            };
-            Global.dealloc(right_node.node.cast(), layout);
+                Global.dealloc(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
+            }
 
             Handle::new_edge(self.node, self.idx)
         }
@@ -1216,8 +1248,8 @@ pub fn steal_left(&mut self) {
         unsafe {
             let (k, v, edge) = self.reborrow_mut().left_edge().descend().pop();
 
-            let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
-            let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
+            let k = mem::replace(self.kv_mut().0, k);
+            let v = mem::replace(self.kv_mut().1, v);
 
             match self.reborrow_mut().right_edge().descend().force() {
                 ForceResult::Leaf(mut leaf) => leaf.push_front(k, v),
@@ -1233,8 +1265,8 @@ pub fn steal_right(&mut self) {
         unsafe {
             let (k, v, edge) = self.reborrow_mut().right_edge().descend().pop_front();
 
-            let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
-            let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
+            let k = mem::replace(self.kv_mut().0, k);
+            let v = mem::replace(self.kv_mut().1, v);
 
             match self.reborrow_mut().left_edge().descend().force() {
                 ForceResult::Leaf(mut leaf) => leaf.push(k, v),
@@ -1262,7 +1294,7 @@ pub fn bulk_steal_left(&mut self, count: usize) {
                 let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
                 let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
                 let parent_kv = {
-                    let kv = self.reborrow_mut().into_kv_mut();
+                    let kv = self.kv_mut();
                     (kv.0 as *mut K, kv.1 as *mut V)
                 };
 
@@ -1319,7 +1351,7 @@ pub fn bulk_steal_right(&mut self, count: usize) {
                 let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
                 let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
                 let parent_kv = {
-                    let kv = self.reborrow_mut().into_kv_mut();
+                    let kv = self.kv_mut();
                     (kv.0 as *mut K, kv.1 as *mut V)
                 };
 
@@ -1545,3 +1577,6 @@ unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T {
         ret
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
new file mode 100644 (file)
index 0000000..e241697
--- /dev/null
@@ -0,0 +1,25 @@
+use super::*;
+
+#[test]
+fn test_splitpoint() {
+    for idx in 0..=CAPACITY {
+        let (middle_kv_idx, insertion) = splitpoint(idx);
+
+        // Simulate performing the split:
+        let mut left_len = middle_kv_idx;
+        let mut right_len = CAPACITY - middle_kv_idx - 1;
+        match insertion {
+            InsertionPlace::Left(edge_idx) => {
+                assert!(edge_idx <= left_len);
+                left_len += 1;
+            }
+            InsertionPlace::Right(edge_idx) => {
+                assert!(edge_idx <= right_len);
+                right_len += 1;
+            }
+        }
+        assert!(left_len >= MIN_LEN);
+        assert!(right_len >= MIN_LEN);
+        assert!(left_len + right_len == CAPACITY);
+    }
+}
index 35f4ef1d9b4c7a3750e15cd76bfe714833b632a2..a559e87e4e29855956eb15258660871a45afb54b 100644 (file)
@@ -1572,3 +1572,6 @@ fn min(mut self) -> Option<&'a T> {
 
 #[stable(feature = "fused", since = "1.26.0")]
 impl<T: Ord> FusedIterator for Union<'_, T> {}
+
+#[cfg(test)]
+mod tests;
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
new file mode 100644 (file)
index 0000000..f4e957e
--- /dev/null
@@ -0,0 +1,649 @@
+use crate::collections::BTreeSet;
+use crate::vec::Vec;
+use std::iter::FromIterator;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::sync::atomic::{AtomicU32, Ordering};
+
+use super::super::DeterministicRng;
+
+#[test]
+fn test_clone_eq() {
+    let mut m = BTreeSet::new();
+
+    m.insert(1);
+    m.insert(2);
+
+    assert_eq!(m.clone(), m);
+}
+
+#[test]
+fn test_iter_min_max() {
+    let mut a = BTreeSet::new();
+    assert_eq!(a.iter().min(), None);
+    assert_eq!(a.iter().max(), None);
+    assert_eq!(a.range(..).min(), None);
+    assert_eq!(a.range(..).max(), None);
+    assert_eq!(a.difference(&BTreeSet::new()).min(), None);
+    assert_eq!(a.difference(&BTreeSet::new()).max(), None);
+    assert_eq!(a.intersection(&a).min(), None);
+    assert_eq!(a.intersection(&a).max(), None);
+    assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None);
+    assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None);
+    assert_eq!(a.union(&a).min(), None);
+    assert_eq!(a.union(&a).max(), None);
+    a.insert(1);
+    a.insert(2);
+    assert_eq!(a.iter().min(), Some(&1));
+    assert_eq!(a.iter().max(), Some(&2));
+    assert_eq!(a.range(..).min(), Some(&1));
+    assert_eq!(a.range(..).max(), Some(&2));
+    assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1));
+    assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2));
+    assert_eq!(a.intersection(&a).min(), Some(&1));
+    assert_eq!(a.intersection(&a).max(), Some(&2));
+    assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1));
+    assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2));
+    assert_eq!(a.union(&a).min(), Some(&1));
+    assert_eq!(a.union(&a).max(), Some(&2));
+}
+
+fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
+where
+    F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool,
+{
+    let mut set_a = BTreeSet::new();
+    let mut set_b = BTreeSet::new();
+
+    for x in a {
+        assert!(set_a.insert(*x))
+    }
+    for y in b {
+        assert!(set_b.insert(*y))
+    }
+
+    let mut i = 0;
+    f(&set_a, &set_b, &mut |&x| {
+        if i < expected.len() {
+            assert_eq!(x, expected[i]);
+        }
+        i += 1;
+        true
+    });
+    assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_intersection() {
+    fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
+        check(a, b, expected, |x, y, f| x.intersection(y).all(f))
+    }
+
+    check_intersection(&[], &[], &[]);
+    check_intersection(&[1, 2, 3], &[], &[]);
+    check_intersection(&[], &[1, 2, 3], &[]);
+    check_intersection(&[2], &[1, 2, 3], &[2]);
+    check_intersection(&[1, 2, 3], &[2], &[2]);
+    check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]);
+
+    if cfg!(miri) {
+        // Miri is too slow
+        return;
+    }
+
+    let large = (0..100).collect::<Vec<_>>();
+    check_intersection(&[], &large, &[]);
+    check_intersection(&large, &[], &[]);
+    check_intersection(&[-1], &large, &[]);
+    check_intersection(&large, &[-1], &[]);
+    check_intersection(&[0], &large, &[0]);
+    check_intersection(&large, &[0], &[0]);
+    check_intersection(&[99], &large, &[99]);
+    check_intersection(&large, &[99], &[99]);
+    check_intersection(&[100], &large, &[]);
+    check_intersection(&large, &[100], &[]);
+    check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]);
+}
+
+#[test]
+fn test_intersection_size_hint() {
+    let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
+    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+    let mut iter = x.intersection(&y);
+    assert_eq!(iter.size_hint(), (1, Some(1)));
+    assert_eq!(iter.next(), Some(&3));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+    assert_eq!(iter.next(), None);
+
+    iter = y.intersection(&y);
+    assert_eq!(iter.size_hint(), (0, Some(3)));
+    assert_eq!(iter.next(), Some(&1));
+    assert_eq!(iter.size_hint(), (0, Some(2)));
+}
+
+#[test]
+fn test_difference() {
+    fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+        check(a, b, expected, |x, y, f| x.difference(y).all(f))
+    }
+
+    check_difference(&[], &[], &[]);
+    check_difference(&[1, 12], &[], &[1, 12]);
+    check_difference(&[], &[1, 2, 3, 9], &[]);
+    check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
+    check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]);
+    check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]);
+    check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]);
+    check_difference(
+        &[-5, 11, 22, 33, 40, 42],
+        &[-12, -5, 14, 23, 34, 38, 39, 50],
+        &[11, 22, 33, 40, 42],
+    );
+
+    if cfg!(miri) {
+        // Miri is too slow
+        return;
+    }
+
+    let large = (0..100).collect::<Vec<_>>();
+    check_difference(&[], &large, &[]);
+    check_difference(&[-1], &large, &[-1]);
+    check_difference(&[0], &large, &[]);
+    check_difference(&[99], &large, &[]);
+    check_difference(&[100], &large, &[100]);
+    check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]);
+    check_difference(&large, &[], &large);
+    check_difference(&large, &[-1], &large);
+    check_difference(&large, &[100], &large);
+}
+
+#[test]
+fn test_difference_size_hint() {
+    let s246: BTreeSet<i32> = [2, 4, 6].iter().copied().collect();
+    let s23456: BTreeSet<i32> = (2..=6).collect();
+    let mut iter = s246.difference(&s23456);
+    assert_eq!(iter.size_hint(), (0, Some(3)));
+    assert_eq!(iter.next(), None);
+
+    let s12345: BTreeSet<i32> = (1..=5).collect();
+    iter = s246.difference(&s12345);
+    assert_eq!(iter.size_hint(), (0, Some(3)));
+    assert_eq!(iter.next(), Some(&6));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+    assert_eq!(iter.next(), None);
+
+    let s34567: BTreeSet<i32> = (3..=7).collect();
+    iter = s246.difference(&s34567);
+    assert_eq!(iter.size_hint(), (0, Some(3)));
+    assert_eq!(iter.next(), Some(&2));
+    assert_eq!(iter.size_hint(), (0, Some(2)));
+    assert_eq!(iter.next(), None);
+
+    let s1: BTreeSet<i32> = (-9..=1).collect();
+    iter = s246.difference(&s1);
+    assert_eq!(iter.size_hint(), (3, Some(3)));
+
+    let s2: BTreeSet<i32> = (-9..=2).collect();
+    iter = s246.difference(&s2);
+    assert_eq!(iter.size_hint(), (2, Some(2)));
+    assert_eq!(iter.next(), Some(&4));
+    assert_eq!(iter.size_hint(), (1, Some(1)));
+
+    let s23: BTreeSet<i32> = (2..=3).collect();
+    iter = s246.difference(&s23);
+    assert_eq!(iter.size_hint(), (1, Some(3)));
+    assert_eq!(iter.next(), Some(&4));
+    assert_eq!(iter.size_hint(), (1, Some(1)));
+
+    let s4: BTreeSet<i32> = (4..=4).collect();
+    iter = s246.difference(&s4);
+    assert_eq!(iter.size_hint(), (2, Some(3)));
+    assert_eq!(iter.next(), Some(&2));
+    assert_eq!(iter.size_hint(), (1, Some(2)));
+    assert_eq!(iter.next(), Some(&6));
+    assert_eq!(iter.size_hint(), (0, Some(0)));
+    assert_eq!(iter.next(), None);
+
+    let s56: BTreeSet<i32> = (5..=6).collect();
+    iter = s246.difference(&s56);
+    assert_eq!(iter.size_hint(), (1, Some(3)));
+    assert_eq!(iter.next(), Some(&2));
+    assert_eq!(iter.size_hint(), (0, Some(2)));
+
+    let s6: BTreeSet<i32> = (6..=19).collect();
+    iter = s246.difference(&s6);
+    assert_eq!(iter.size_hint(), (2, Some(2)));
+    assert_eq!(iter.next(), Some(&2));
+    assert_eq!(iter.size_hint(), (1, Some(1)));
+
+    let s7: BTreeSet<i32> = (7..=19).collect();
+    iter = s246.difference(&s7);
+    assert_eq!(iter.size_hint(), (3, Some(3)));
+}
+
+#[test]
+fn test_symmetric_difference() {
+    fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+        check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
+    }
+
+    check_symmetric_difference(&[], &[], &[]);
+    check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
+    check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
+    check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]);
+}
+
+#[test]
+fn test_symmetric_difference_size_hint() {
+    let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
+    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+    let mut iter = x.symmetric_difference(&y);
+    assert_eq!(iter.size_hint(), (0, Some(5)));
+    assert_eq!(iter.next(), Some(&1));
+    assert_eq!(iter.size_hint(), (0, Some(4)));
+    assert_eq!(iter.next(), Some(&3));
+    assert_eq!(iter.size_hint(), (0, Some(1)));
+}
+
+#[test]
+fn test_union() {
+    fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
+        check(a, b, expected, |x, y, f| x.union(y).all(f))
+    }
+
+    check_union(&[], &[], &[]);
+    check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
+    check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
+    check_union(
+        &[1, 3, 5, 9, 11, 16, 19, 24],
+        &[-2, 1, 5, 9, 13, 19],
+        &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24],
+    );
+}
+
+#[test]
+fn test_union_size_hint() {
+    let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
+    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+    let mut iter = x.union(&y);
+    assert_eq!(iter.size_hint(), (3, Some(5)));
+    assert_eq!(iter.next(), Some(&1));
+    assert_eq!(iter.size_hint(), (2, Some(4)));
+    assert_eq!(iter.next(), Some(&2));
+    assert_eq!(iter.size_hint(), (1, Some(2)));
+}
+
+#[test]
+// Only tests the simple function definition with respect to intersection
+fn test_is_disjoint() {
+    let one = [1].iter().collect::<BTreeSet<_>>();
+    let two = [2].iter().collect::<BTreeSet<_>>();
+    assert!(one.is_disjoint(&two));
+}
+
+#[test]
+// Also implicitly tests the trivial function definition of is_superset
+fn test_is_subset() {
+    fn is_subset(a: &[i32], b: &[i32]) -> bool {
+        let set_a = a.iter().collect::<BTreeSet<_>>();
+        let set_b = b.iter().collect::<BTreeSet<_>>();
+        set_a.is_subset(&set_b)
+    }
+
+    assert_eq!(is_subset(&[], &[]), true);
+    assert_eq!(is_subset(&[], &[1, 2]), true);
+    assert_eq!(is_subset(&[0], &[1, 2]), false);
+    assert_eq!(is_subset(&[1], &[1, 2]), true);
+    assert_eq!(is_subset(&[2], &[1, 2]), true);
+    assert_eq!(is_subset(&[3], &[1, 2]), false);
+    assert_eq!(is_subset(&[1, 2], &[1]), false);
+    assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
+    assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
+    assert_eq!(
+        is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
+        true
+    );
+    assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false);
+
+    if cfg!(miri) {
+        // Miri is too slow
+        return;
+    }
+
+    let large = (0..100).collect::<Vec<_>>();
+    assert_eq!(is_subset(&[], &large), true);
+    assert_eq!(is_subset(&large, &[]), false);
+    assert_eq!(is_subset(&[-1], &large), false);
+    assert_eq!(is_subset(&[0], &large), true);
+    assert_eq!(is_subset(&[1, 2], &large), true);
+    assert_eq!(is_subset(&[99, 100], &large), false);
+}
+
+#[test]
+fn test_drain_filter() {
+    let mut x: BTreeSet<_> = [1].iter().copied().collect();
+    let mut y: BTreeSet<_> = [1].iter().copied().collect();
+
+    x.drain_filter(|_| true);
+    y.drain_filter(|_| false);
+    assert_eq!(x.len(), 0);
+    assert_eq!(y.len(), 1);
+}
+
+#[test]
+fn test_drain_filter_drop_panic_leak() {
+    static PREDS: AtomicU32 = AtomicU32::new(0);
+    static DROPS: AtomicU32 = AtomicU32::new(0);
+
+    #[derive(PartialEq, Eq, PartialOrd, Ord)]
+    struct D(i32);
+    impl Drop for D {
+        fn drop(&mut self) {
+            if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut set = BTreeSet::new();
+    set.insert(D(0));
+    set.insert(D(4));
+    set.insert(D(8));
+
+    catch_unwind(move || {
+        drop(set.drain_filter(|d| {
+            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+            true
+        }))
+    })
+    .ok();
+
+    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+    assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+}
+
+#[test]
+fn test_drain_filter_pred_panic_leak() {
+    static PREDS: AtomicU32 = AtomicU32::new(0);
+    static DROPS: AtomicU32 = AtomicU32::new(0);
+
+    #[derive(PartialEq, Eq, PartialOrd, Ord)]
+    struct D(i32);
+    impl Drop for D {
+        fn drop(&mut self) {
+            DROPS.fetch_add(1, Ordering::SeqCst);
+        }
+    }
+
+    let mut set = BTreeSet::new();
+    set.insert(D(0));
+    set.insert(D(4));
+    set.insert(D(8));
+
+    catch_unwind(AssertUnwindSafe(|| {
+        drop(set.drain_filter(|d| {
+            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+            match d.0 {
+                0 => true,
+                _ => panic!(),
+            }
+        }))
+    }))
+    .ok();
+
+    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+    assert_eq!(set.len(), 2);
+    assert_eq!(set.first().unwrap().0, 4);
+    assert_eq!(set.last().unwrap().0, 8);
+}
+
+#[test]
+fn test_clear() {
+    let mut x = BTreeSet::new();
+    x.insert(1);
+
+    x.clear();
+    assert!(x.is_empty());
+}
+
+#[test]
+fn test_zip() {
+    let mut x = BTreeSet::new();
+    x.insert(5);
+    x.insert(12);
+    x.insert(11);
+
+    let mut y = BTreeSet::new();
+    y.insert("foo");
+    y.insert("bar");
+
+    let x = x;
+    let y = y;
+    let mut z = x.iter().zip(&y);
+
+    assert_eq!(z.next().unwrap(), (&5, &("bar")));
+    assert_eq!(z.next().unwrap(), (&11, &("foo")));
+    assert!(z.next().is_none());
+}
+
+#[test]
+fn test_from_iter() {
+    let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+    let set: BTreeSet<_> = xs.iter().cloned().collect();
+
+    for x in &xs {
+        assert!(set.contains(x));
+    }
+}
+
+#[test]
+fn test_show() {
+    let mut set = BTreeSet::new();
+    let empty = BTreeSet::<i32>::new();
+
+    set.insert(1);
+    set.insert(2);
+
+    let set_str = format!("{:?}", set);
+
+    assert_eq!(set_str, "{1, 2}");
+    assert_eq!(format!("{:?}", empty), "{}");
+}
+
+#[test]
+fn test_extend_ref() {
+    let mut a = BTreeSet::new();
+    a.insert(1);
+
+    a.extend(&[2, 3, 4]);
+
+    assert_eq!(a.len(), 4);
+    assert!(a.contains(&1));
+    assert!(a.contains(&2));
+    assert!(a.contains(&3));
+    assert!(a.contains(&4));
+
+    let mut b = BTreeSet::new();
+    b.insert(5);
+    b.insert(6);
+
+    a.extend(&b);
+
+    assert_eq!(a.len(), 6);
+    assert!(a.contains(&1));
+    assert!(a.contains(&2));
+    assert!(a.contains(&3));
+    assert!(a.contains(&4));
+    assert!(a.contains(&5));
+    assert!(a.contains(&6));
+}
+
+#[test]
+fn test_recovery() {
+    use std::cmp::Ordering;
+
+    #[derive(Debug)]
+    struct Foo(&'static str, i32);
+
+    impl PartialEq for Foo {
+        fn eq(&self, other: &Self) -> bool {
+            self.0 == other.0
+        }
+    }
+
+    impl Eq for Foo {}
+
+    impl PartialOrd for Foo {
+        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+            self.0.partial_cmp(&other.0)
+        }
+    }
+
+    impl Ord for Foo {
+        fn cmp(&self, other: &Self) -> Ordering {
+            self.0.cmp(&other.0)
+        }
+    }
+
+    let mut s = BTreeSet::new();
+    assert_eq!(s.replace(Foo("a", 1)), None);
+    assert_eq!(s.len(), 1);
+    assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
+    assert_eq!(s.len(), 1);
+
+    {
+        let mut it = s.iter();
+        assert_eq!(it.next(), Some(&Foo("a", 2)));
+        assert_eq!(it.next(), None);
+    }
+
+    assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
+    assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
+    assert_eq!(s.len(), 0);
+
+    assert_eq!(s.get(&Foo("a", 1)), None);
+    assert_eq!(s.take(&Foo("a", 1)), None);
+
+    assert_eq!(s.iter().next(), None);
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+    use std::collections::btree_set::{IntoIter, Iter, Range};
+
+    fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
+        v
+    }
+    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
+        v
+    }
+    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
+        v
+    }
+    fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
+        v
+    }
+}
+
+#[test]
+fn test_append() {
+    let mut a = BTreeSet::new();
+    a.insert(1);
+    a.insert(2);
+    a.insert(3);
+
+    let mut b = BTreeSet::new();
+    b.insert(3);
+    b.insert(4);
+    b.insert(5);
+
+    a.append(&mut b);
+
+    assert_eq!(a.len(), 5);
+    assert_eq!(b.len(), 0);
+
+    assert_eq!(a.contains(&1), true);
+    assert_eq!(a.contains(&2), true);
+    assert_eq!(a.contains(&3), true);
+    assert_eq!(a.contains(&4), true);
+    assert_eq!(a.contains(&5), true);
+}
+
+#[test]
+fn test_first_last() {
+    let mut a = BTreeSet::new();
+    assert_eq!(a.first(), None);
+    assert_eq!(a.last(), None);
+    a.insert(1);
+    assert_eq!(a.first(), Some(&1));
+    assert_eq!(a.last(), Some(&1));
+    a.insert(2);
+    assert_eq!(a.first(), Some(&1));
+    assert_eq!(a.last(), Some(&2));
+    for i in 3..=12 {
+        a.insert(i);
+    }
+    assert_eq!(a.first(), Some(&1));
+    assert_eq!(a.last(), Some(&12));
+    assert_eq!(a.pop_first(), Some(1));
+    assert_eq!(a.pop_last(), Some(12));
+    assert_eq!(a.pop_first(), Some(2));
+    assert_eq!(a.pop_last(), Some(11));
+    assert_eq!(a.pop_first(), Some(3));
+    assert_eq!(a.pop_last(), Some(10));
+    assert_eq!(a.pop_first(), Some(4));
+    assert_eq!(a.pop_first(), Some(5));
+    assert_eq!(a.pop_first(), Some(6));
+    assert_eq!(a.pop_first(), Some(7));
+    assert_eq!(a.pop_first(), Some(8));
+    assert_eq!(a.clone().pop_last(), Some(9));
+    assert_eq!(a.pop_first(), Some(9));
+    assert_eq!(a.pop_first(), None);
+    assert_eq!(a.pop_last(), None);
+}
+
+fn rand_data(len: usize) -> Vec<u32> {
+    let mut rng = DeterministicRng::new();
+    Vec::from_iter((0..len).map(|_| rng.next()))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+    let mut data = rand_data(173);
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let right = set.split_off(&(data.iter().max().unwrap() + 1));
+
+    data.sort();
+    assert!(set.into_iter().eq(data));
+    assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+    let mut data = rand_data(314);
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let right = set.split_off(data.iter().min().unwrap());
+
+    data.sort();
+    assert!(set.into_iter().eq(None));
+    assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+    // Miri is too slow
+    let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
+    // special case with maximum height.
+    data.sort();
+
+    let mut set = BTreeSet::from_iter(data.clone());
+    let key = data[data.len() / 2];
+    let right = set.split_off(&key);
+
+    assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
+    assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
+}
index 9ac23886d4e15666c6b871f3e9fe1263784d91fe..2d25941a52412187c8a43f1bb03c25fb865eb3ab 100644 (file)
@@ -80,6 +80,7 @@
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(btree_drain_filter)]
 #![feature(cfg_sanitize)]
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
@@ -93,6 +94,7 @@
 #![feature(container_error_extra)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
+#![feature(exclusive_range_pattern)]
 #![feature(extend_one)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(lang_items)]
 #![feature(layout_for_ptr)]
 #![feature(libc)]
+#![feature(map_first_last)]
+#![feature(map_into_keys_values)]
 #![feature(negative_impls)]
 #![feature(new_uninit)]
 #![feature(nll)]
index de707a71a8c9e9c920e6947687d1142e84b1570a..8ca0a0883cb1679a538d203e3b8471e5c4f705d5 100644 (file)
@@ -2620,9 +2620,6 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 ///
 /// This `struct` is created by the `into_iter` method on [`Vec`] (provided
 /// by the [`IntoIterator`] trait).
-///
-/// [`Vec`]: struct.Vec.html
-/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     buf: NonNull<T>,
@@ -2802,10 +2799,7 @@ fn drop(&mut self) {
 
 /// A draining iterator for `Vec<T>`.
 ///
-/// This `struct` is created by the [`drain`] method on [`Vec`].
-///
-/// [`drain`]: struct.Vec.html#method.drain
-/// [`Vec`]: struct.Vec.html
+/// This `struct` is created by [`Vec::drain`].
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, T: 'a> {
     /// Index of tail to preserve
@@ -2933,11 +2927,8 @@ impl<T> FusedIterator for Drain<'_, T> {}
 
 /// A splicing iterator for `Vec`.
 ///
-/// This struct is created by the [`splice()`] method on [`Vec`]. See its
-/// documentation for more.
-///
-/// [`splice()`]: struct.Vec.html#method.splice
-/// [`Vec`]: struct.Vec.html
+/// This struct is created by [`Vec::splice()`].
+/// See its documentation for more.
 #[derive(Debug)]
 #[stable(feature = "vec_splice", since = "1.21.0")]
 pub struct Splice<'a, I: Iterator + 'a> {
diff --git a/library/alloc/tests/btree/map.rs b/library/alloc/tests/btree/map.rs
deleted file mode 100644 (file)
index 5777bd6..0000000
+++ /dev/null
@@ -1,1487 +0,0 @@
-use std::collections::btree_map::Entry::{Occupied, Vacant};
-use std::collections::BTreeMap;
-use std::convert::TryFrom;
-use std::fmt::Debug;
-use std::iter::FromIterator;
-use std::mem;
-use std::ops::Bound::{self, Excluded, Included, Unbounded};
-use std::ops::RangeBounds;
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::rc::Rc;
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-use super::DeterministicRng;
-
-// Value of node::CAPACITY, thus capacity of a tree with a single level,
-// i.e. a tree who's root is a leaf node at height 0.
-const NODE_CAPACITY: usize = 11;
-
-// Minimum number of elements to insert in order to guarantee a tree with 2 levels,
-// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes.
-// It's not the minimum size: removing an element from such a tree does not always reduce height.
-const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
-
-// Minimum number of elements to insert in order to guarantee a tree with 3 levels,
-// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes.
-// It's not the minimum size: removing an element from such a tree does not always reduce height.
-const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1;
-
-// Gather all references from a mutable iterator and make sure Miri notices if
-// using them is dangerous.
-fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
-    // Gather all those references.
-    let mut refs: Vec<&mut T> = iter.collect();
-    // Use them all. Twice, to be sure we got all interleavings.
-    for r in refs.iter_mut() {
-        mem::swap(dummy, r);
-    }
-    for r in refs {
-        mem::swap(dummy, r);
-    }
-}
-
-#[test]
-fn test_basic_large() {
-    let mut map = BTreeMap::new();
-    // Miri is too slow
-    let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 };
-    assert_eq!(map.len(), 0);
-
-    for i in 0..size {
-        assert_eq!(map.insert(i, 10 * i), None);
-        assert_eq!(map.len(), i + 1);
-    }
-
-    assert_eq!(map.first_key_value(), Some((&0, &0)));
-    assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1)))));
-    assert_eq!(map.first_entry().unwrap().key(), &0);
-    assert_eq!(map.last_entry().unwrap().key(), &(size - 1));
-
-    for i in 0..size {
-        assert_eq!(map.get(&i).unwrap(), &(i * 10));
-    }
-
-    for i in size..size * 2 {
-        assert_eq!(map.get(&i), None);
-    }
-
-    for i in 0..size {
-        assert_eq!(map.insert(i, 100 * i), Some(10 * i));
-        assert_eq!(map.len(), size);
-    }
-
-    for i in 0..size {
-        assert_eq!(map.get(&i).unwrap(), &(i * 100));
-    }
-
-    for i in 0..size / 2 {
-        assert_eq!(map.remove(&(i * 2)), Some(i * 200));
-        assert_eq!(map.len(), size - i - 1);
-    }
-
-    for i in 0..size / 2 {
-        assert_eq!(map.get(&(2 * i)), None);
-        assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
-    }
-
-    for i in 0..size / 2 {
-        assert_eq!(map.remove(&(2 * i)), None);
-        assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
-        assert_eq!(map.len(), size / 2 - i - 1);
-    }
-}
-
-#[test]
-fn test_basic_small() {
-    let mut map = BTreeMap::new();
-    // Empty, root is absent (None):
-    assert_eq!(map.remove(&1), None);
-    assert_eq!(map.len(), 0);
-    assert_eq!(map.get(&1), None);
-    assert_eq!(map.get_mut(&1), None);
-    assert_eq!(map.first_key_value(), None);
-    assert_eq!(map.last_key_value(), None);
-    assert_eq!(map.keys().count(), 0);
-    assert_eq!(map.values().count(), 0);
-    assert_eq!(map.range(..).next(), None);
-    assert_eq!(map.range(..1).next(), None);
-    assert_eq!(map.range(1..).next(), None);
-    assert_eq!(map.range(1..=1).next(), None);
-    assert_eq!(map.range(1..2).next(), None);
-    assert_eq!(map.insert(1, 1), None);
-
-    // 1 key-value pair:
-    assert_eq!(map.len(), 1);
-    assert_eq!(map.get(&1), Some(&1));
-    assert_eq!(map.get_mut(&1), Some(&mut 1));
-    assert_eq!(map.first_key_value(), Some((&1, &1)));
-    assert_eq!(map.last_key_value(), Some((&1, &1)));
-    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
-    assert_eq!(map.values().collect::<Vec<_>>(), vec![&1]);
-    assert_eq!(map.insert(1, 2), Some(1));
-    assert_eq!(map.len(), 1);
-    assert_eq!(map.get(&1), Some(&2));
-    assert_eq!(map.get_mut(&1), Some(&mut 2));
-    assert_eq!(map.first_key_value(), Some((&1, &2)));
-    assert_eq!(map.last_key_value(), Some((&1, &2)));
-    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
-    assert_eq!(map.values().collect::<Vec<_>>(), vec![&2]);
-    assert_eq!(map.insert(2, 4), None);
-
-    // 2 key-value pairs:
-    assert_eq!(map.len(), 2);
-    assert_eq!(map.get(&2), Some(&4));
-    assert_eq!(map.get_mut(&2), Some(&mut 4));
-    assert_eq!(map.first_key_value(), Some((&1, &2)));
-    assert_eq!(map.last_key_value(), Some((&2, &4)));
-    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1, &2]);
-    assert_eq!(map.values().collect::<Vec<_>>(), vec![&2, &4]);
-    assert_eq!(map.remove(&1), Some(2));
-
-    // 1 key-value pair:
-    assert_eq!(map.len(), 1);
-    assert_eq!(map.get(&1), None);
-    assert_eq!(map.get_mut(&1), None);
-    assert_eq!(map.get(&2), Some(&4));
-    assert_eq!(map.get_mut(&2), Some(&mut 4));
-    assert_eq!(map.first_key_value(), Some((&2, &4)));
-    assert_eq!(map.last_key_value(), Some((&2, &4)));
-    assert_eq!(map.keys().collect::<Vec<_>>(), vec![&2]);
-    assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
-    assert_eq!(map.remove(&2), Some(4));
-
-    // Empty but root is owned (Some(...)):
-    assert_eq!(map.len(), 0);
-    assert_eq!(map.get(&1), None);
-    assert_eq!(map.get_mut(&1), None);
-    assert_eq!(map.first_key_value(), None);
-    assert_eq!(map.last_key_value(), None);
-    assert_eq!(map.keys().count(), 0);
-    assert_eq!(map.values().count(), 0);
-    assert_eq!(map.range(..).next(), None);
-    assert_eq!(map.range(..1).next(), None);
-    assert_eq!(map.range(1..).next(), None);
-    assert_eq!(map.range(1..=1).next(), None);
-    assert_eq!(map.range(1..2).next(), None);
-    assert_eq!(map.remove(&1), None);
-}
-
-#[test]
-fn test_iter() {
-    // Miri is too slow
-    let size = if cfg!(miri) { 200 } else { 10000 };
-
-    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    fn test<T>(size: usize, mut iter: T)
-    where
-        T: Iterator<Item = (usize, usize)>,
-    {
-        for i in 0..size {
-            assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
-            assert_eq!(iter.next().unwrap(), (i, i));
-        }
-        assert_eq!(iter.size_hint(), (0, Some(0)));
-        assert_eq!(iter.next(), None);
-    }
-    test(size, map.iter().map(|(&k, &v)| (k, v)));
-    test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
-    test(size, map.into_iter());
-}
-
-#[test]
-fn test_iter_rev() {
-    // Miri is too slow
-    let size = if cfg!(miri) { 200 } else { 10000 };
-
-    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    fn test<T>(size: usize, mut iter: T)
-    where
-        T: Iterator<Item = (usize, usize)>,
-    {
-        for i in 0..size {
-            assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
-            assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
-        }
-        assert_eq!(iter.size_hint(), (0, Some(0)));
-        assert_eq!(iter.next(), None);
-    }
-    test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
-    test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
-    test(size, map.into_iter().rev());
-}
-
-/// Specifically tests iter_mut's ability to mutate the value of pairs in-line
-fn do_test_iter_mut_mutation<T>(size: usize)
-where
-    T: Copy + Debug + Ord + TryFrom<usize>,
-    <T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
-{
-    let zero = T::try_from(0).unwrap();
-    let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
-
-    // Forward and backward iteration sees enough pairs (also tested elsewhere)
-    assert_eq!(map.iter_mut().count(), size);
-    assert_eq!(map.iter_mut().rev().count(), size);
-
-    // Iterate forwards, trying to mutate to unique values
-    for (i, (k, v)) in map.iter_mut().enumerate() {
-        assert_eq!(*k, T::try_from(i).unwrap());
-        assert_eq!(*v, zero);
-        *v = T::try_from(i + 1).unwrap();
-    }
-
-    // Iterate backwards, checking that mutations succeeded and trying to mutate again
-    for (i, (k, v)) in map.iter_mut().rev().enumerate() {
-        assert_eq!(*k, T::try_from(size - i - 1).unwrap());
-        assert_eq!(*v, T::try_from(size - i).unwrap());
-        *v = T::try_from(2 * size - i).unwrap();
-    }
-
-    // Check that backward mutations succeeded
-    for (i, (k, v)) in map.iter_mut().enumerate() {
-        assert_eq!(*k, T::try_from(i).unwrap());
-        assert_eq!(*v, T::try_from(size + i + 1).unwrap());
-    }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
-#[repr(align(32))]
-struct Align32(usize);
-
-impl TryFrom<usize> for Align32 {
-    type Error = ();
-
-    fn try_from(s: usize) -> Result<Align32, ()> {
-        Ok(Align32(s))
-    }
-}
-
-#[test]
-fn test_iter_mut_mutation() {
-    // Check many alignments and trees with roots at various heights.
-    do_test_iter_mut_mutation::<u8>(0);
-    do_test_iter_mut_mutation::<u8>(1);
-    do_test_iter_mut_mutation::<u8>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<u8>(127); // not enough unique values to test MIN_INSERTS_HEIGHT_2
-    do_test_iter_mut_mutation::<u16>(1);
-    do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_2);
-    do_test_iter_mut_mutation::<u32>(1);
-    do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_2);
-    do_test_iter_mut_mutation::<u64>(1);
-    do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_2);
-    do_test_iter_mut_mutation::<u128>(1);
-    do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_2);
-    do_test_iter_mut_mutation::<Align32>(1);
-    do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_1);
-    do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_2);
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_values_mut() {
-    let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
-    test_all_refs(&mut 13, a.values_mut());
-}
-
-#[test]
-fn test_values_mut_mutation() {
-    let mut a = BTreeMap::new();
-    a.insert(1, String::from("hello"));
-    a.insert(2, String::from("goodbye"));
-
-    for value in a.values_mut() {
-        value.push_str("!");
-    }
-
-    let values: Vec<String> = a.values().cloned().collect();
-    assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_entering_root_twice() {
-    let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect();
-    let mut it = map.iter_mut();
-    let front = it.next().unwrap();
-    let back = it.next_back().unwrap();
-    assert_eq!(front, (&0, &mut 0));
-    assert_eq!(back, (&1, &mut 1));
-    *front.1 = 24;
-    *back.1 = 42;
-    assert_eq!(front, (&0, &mut 24));
-    assert_eq!(back, (&1, &mut 42));
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_descending_to_same_node_twice() {
-    let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect();
-    let mut it = map.iter_mut();
-    // Descend into first child.
-    let front = it.next().unwrap();
-    // Descend into first child again, after running through second child.
-    while it.next_back().is_some() {}
-    // Check immutable access.
-    assert_eq!(front, (&0, &mut 0));
-    // Perform mutable access.
-    *front.1 = 42;
-}
-
-#[test]
-fn test_iter_mixed() {
-    // Miri is too slow
-    let size = if cfg!(miri) { 200 } else { 10000 };
-
-    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    fn test<T>(size: usize, mut iter: T)
-    where
-        T: Iterator<Item = (usize, usize)> + DoubleEndedIterator,
-    {
-        for i in 0..size / 4 {
-            assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
-            assert_eq!(iter.next().unwrap(), (i, i));
-            assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
-        }
-        for i in size / 4..size * 3 / 4 {
-            assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
-            assert_eq!(iter.next().unwrap(), (i, i));
-        }
-        assert_eq!(iter.size_hint(), (0, Some(0)));
-        assert_eq!(iter.next(), None);
-    }
-    test(size, map.iter().map(|(&k, &v)| (k, v)));
-    test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
-    test(size, map.into_iter());
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_min_max() {
-    let mut a = BTreeMap::new();
-    assert_eq!(a.iter().min(), None);
-    assert_eq!(a.iter().max(), None);
-    assert_eq!(a.iter_mut().min(), None);
-    assert_eq!(a.iter_mut().max(), None);
-    assert_eq!(a.range(..).min(), None);
-    assert_eq!(a.range(..).max(), None);
-    assert_eq!(a.range_mut(..).min(), None);
-    assert_eq!(a.range_mut(..).max(), None);
-    assert_eq!(a.keys().min(), None);
-    assert_eq!(a.keys().max(), None);
-    assert_eq!(a.values().min(), None);
-    assert_eq!(a.values().max(), None);
-    assert_eq!(a.values_mut().min(), None);
-    assert_eq!(a.values_mut().max(), None);
-    a.insert(1, 42);
-    a.insert(2, 24);
-    assert_eq!(a.iter().min(), Some((&1, &42)));
-    assert_eq!(a.iter().max(), Some((&2, &24)));
-    assert_eq!(a.iter_mut().min(), Some((&1, &mut 42)));
-    assert_eq!(a.iter_mut().max(), Some((&2, &mut 24)));
-    assert_eq!(a.range(..).min(), Some((&1, &42)));
-    assert_eq!(a.range(..).max(), Some((&2, &24)));
-    assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42)));
-    assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24)));
-    assert_eq!(a.keys().min(), Some(&1));
-    assert_eq!(a.keys().max(), Some(&2));
-    assert_eq!(a.values().min(), Some(&24));
-    assert_eq!(a.values().max(), Some(&42));
-    assert_eq!(a.values_mut().min(), Some(&mut 24));
-    assert_eq!(a.values_mut().max(), Some(&mut 42));
-}
-
-fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
-    map.range(range)
-        .map(|(&k, &v)| {
-            assert_eq!(k, v);
-            k
-        })
-        .collect()
-}
-
-#[test]
-fn test_range_small() {
-    let size = 4;
-
-    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
-    let all: Vec<_> = (1..=size).collect();
-    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
-
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
-    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
-    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
-    assert_eq!(range_keys(&map, ..), all);
-
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
-    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
-    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
-    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
-    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
-    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
-    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
-
-    assert_eq!(range_keys(&map, ..3), vec![1, 2]);
-    assert_eq!(range_keys(&map, 3..), vec![3, 4]);
-    assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
-}
-
-#[test]
-fn test_range_height_1() {
-    // Tests tree with a root and 2 leaves. Depending on details we don't want or need
-    // to rely upon, the single key at the root will be 6 or 7.
-
-    let map: BTreeMap<_, _> = (1..=MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect();
-    for &root in &[6, 7] {
-        assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
-        assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
-        assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
-        assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
-
-        assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
-        assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
-        assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
-        assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
-    }
-}
-
-#[test]
-fn test_range_large() {
-    let size = 200;
-
-    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
-    let all: Vec<_> = (1..=size).collect();
-    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
-
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
-    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
-    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
-    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
-    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
-    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
-    assert_eq!(range_keys(&map, ..), all);
-
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
-    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
-    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
-    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
-    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
-    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
-    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
-    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
-    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
-    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
-    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
-    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
-    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
-    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
-
-    fn check<'a, L, R>(lhs: L, rhs: R)
-    where
-        L: IntoIterator<Item = (&'a i32, &'a i32)>,
-        R: IntoIterator<Item = (&'a i32, &'a i32)>,
-    {
-        let lhs: Vec<_> = lhs.into_iter().collect();
-        let rhs: Vec<_> = rhs.into_iter().collect();
-        assert_eq!(lhs, rhs);
-    }
-
-    check(map.range(..=100), map.range(..101));
-    check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
-    check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
-}
-
-#[test]
-fn test_range_inclusive_max_value() {
-    let max = usize::MAX;
-    let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
-
-    assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
-}
-
-#[test]
-fn test_range_equal_empty_cases() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
-    assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
-}
-
-#[test]
-#[should_panic]
-fn test_range_equal_excluded() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(2), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_1() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Included(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_2() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Included(3), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_3() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_4() {
-    let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
-    map.range((Excluded(3), Excluded(2)));
-}
-
-#[test]
-fn test_range_1000() {
-    // Miri is too slow
-    let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 };
-    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
-        let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
-        let mut pairs = (0..size).map(|i| (i, i));
-
-        for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
-            assert_eq!(kv, pair);
-        }
-        assert_eq!(kvs.next(), None);
-        assert_eq!(pairs.next(), None);
-    }
-    test(&map, size, Included(&0), Excluded(&size));
-    test(&map, size, Unbounded, Excluded(&size));
-    test(&map, size, Included(&0), Included(&(size - 1)));
-    test(&map, size, Unbounded, Included(&(size - 1)));
-    test(&map, size, Included(&0), Unbounded);
-    test(&map, size, Unbounded, Unbounded);
-}
-
-#[test]
-fn test_range_borrowed_key() {
-    let mut map = BTreeMap::new();
-    map.insert("aardvark".to_string(), 1);
-    map.insert("baboon".to_string(), 2);
-    map.insert("coyote".to_string(), 3);
-    map.insert("dingo".to_string(), 4);
-    // NOTE: would like to use simply "b".."d" here...
-    let mut iter = map.range::<str, _>((Included("b"), Excluded("d")));
-    assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
-    assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
-    assert_eq!(iter.next(), None);
-}
-
-#[test]
-fn test_range() {
-    let size = 200;
-    // Miri is too slow
-    let step = if cfg!(miri) { 66 } else { 1 };
-    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    for i in (0..size).step_by(step) {
-        for j in (i..size).step_by(step) {
-            let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
-            let mut pairs = (i..=j).map(|i| (i, i));
-
-            for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
-                assert_eq!(kv, pair);
-            }
-            assert_eq!(kvs.next(), None);
-            assert_eq!(pairs.next(), None);
-        }
-    }
-}
-
-#[test]
-fn test_range_mut() {
-    let size = 200;
-    // Miri is too slow
-    let step = if cfg!(miri) { 66 } else { 1 };
-    let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    for i in (0..size).step_by(step) {
-        for j in (i..size).step_by(step) {
-            let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
-            let mut pairs = (i..=j).map(|i| (i, i));
-
-            for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
-                assert_eq!(kv, pair);
-            }
-            assert_eq!(kvs.next(), None);
-            assert_eq!(pairs.next(), None);
-        }
-    }
-}
-
-mod test_drain_filter {
-    use super::*;
-
-    #[test]
-    fn empty() {
-        let mut map: BTreeMap<i32, i32> = BTreeMap::new();
-        map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn consuming_nothing() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
-    }
-
-    #[test]
-    fn consuming_all() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.clone().collect();
-        assert!(map.drain_filter(|_, _| true).eq(pairs));
-    }
-
-    #[test]
-    fn mutating_and_keeping() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        assert!(
-            map.drain_filter(|_, v| {
-                *v += 6;
-                false
-            })
-            .eq(std::iter::empty())
-        );
-        assert!(map.keys().copied().eq(0..3));
-        assert!(map.values().copied().eq(6..9));
-    }
-
-    #[test]
-    fn mutating_and_removing() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        assert!(
-            map.drain_filter(|_, v| {
-                *v += 6;
-                true
-            })
-            .eq((0..3).map(|i| (i, i + 6)))
-        );
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn underfull_keeping_all() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| false);
-        assert!(map.keys().copied().eq(0..3));
-    }
-
-    #[test]
-    fn underfull_removing_one() {
-        let pairs = (0..3).map(|i| (i, i));
-        for doomed in 0..3 {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i == doomed);
-            assert_eq!(map.len(), 2);
-        }
-    }
-
-    #[test]
-    fn underfull_keeping_one() {
-        let pairs = (0..3).map(|i| (i, i));
-        for sacred in 0..3 {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i != sacred);
-            assert!(map.keys().copied().eq(sacred..=sacred));
-        }
-    }
-
-    #[test]
-    fn underfull_removing_all() {
-        let pairs = (0..3).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| true);
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn height_0_keeping_all() {
-        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| false);
-        assert!(map.keys().copied().eq(0..NODE_CAPACITY));
-    }
-
-    #[test]
-    fn height_0_removing_one() {
-        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
-        for doomed in 0..NODE_CAPACITY {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i == doomed);
-            assert_eq!(map.len(), NODE_CAPACITY - 1);
-        }
-    }
-
-    #[test]
-    fn height_0_keeping_one() {
-        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
-        for sacred in 0..NODE_CAPACITY {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i != sacred);
-            assert!(map.keys().copied().eq(sacred..=sacred));
-        }
-    }
-
-    #[test]
-    fn height_0_removing_all() {
-        let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| true);
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn height_0_keeping_half() {
-        let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect();
-        assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8);
-        assert_eq!(map.len(), 8);
-    }
-
-    #[test]
-    fn height_1_removing_all() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| true);
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn height_1_removing_one() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
-        for doomed in 0..MIN_INSERTS_HEIGHT_1 {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i == doomed);
-            assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
-        }
-    }
-
-    #[test]
-    fn height_1_keeping_one() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
-        for sacred in 0..MIN_INSERTS_HEIGHT_1 {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i != sacred);
-            assert!(map.keys().copied().eq(sacred..=sacred));
-        }
-    }
-
-    #[cfg(not(miri))] // Miri is too slow
-    #[test]
-    fn height_2_removing_one() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
-        for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i == doomed);
-            assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
-        }
-    }
-
-    #[cfg(not(miri))] // Miri is too slow
-    #[test]
-    fn height_2_keeping_one() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
-        for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
-            let mut map: BTreeMap<_, _> = pairs.clone().collect();
-            map.drain_filter(|i, _| *i != sacred);
-            assert!(map.keys().copied().eq(sacred..=sacred));
-        }
-    }
-
-    #[test]
-    fn height_2_removing_all() {
-        let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
-        let mut map: BTreeMap<_, _> = pairs.collect();
-        map.drain_filter(|_, _| true);
-        assert!(map.is_empty());
-    }
-
-    #[test]
-    fn drop_panic_leak() {
-        static PREDS: AtomicUsize = AtomicUsize::new(0);
-        static DROPS: AtomicUsize = AtomicUsize::new(0);
-
-        struct D;
-        impl Drop for D {
-            fn drop(&mut self) {
-                if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
-                    panic!("panic in `drop`");
-                }
-            }
-        }
-
-        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
-        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
-        catch_unwind(move || {
-            drop(map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
-                true
-            }))
-        })
-        .unwrap_err();
-
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 3);
-    }
-
-    #[test]
-    fn pred_panic_leak() {
-        static PREDS: AtomicUsize = AtomicUsize::new(0);
-        static DROPS: AtomicUsize = AtomicUsize::new(0);
-
-        struct D;
-        impl Drop for D {
-            fn drop(&mut self) {
-                DROPS.fetch_add(1, Ordering::SeqCst);
-            }
-        }
-
-        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
-        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
-        catch_unwind(AssertUnwindSafe(|| {
-            drop(map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
-                match i {
-                    0 => true,
-                    _ => panic!(),
-                }
-            }))
-        }))
-        .unwrap_err();
-
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
-        assert_eq!(map.len(), 2);
-        assert_eq!(map.first_entry().unwrap().key(), &4);
-        assert_eq!(map.last_entry().unwrap().key(), &8);
-    }
-
-    // Same as above, but attempt to use the iterator again after the panic in the predicate
-    #[test]
-    fn pred_panic_reuse() {
-        static PREDS: AtomicUsize = AtomicUsize::new(0);
-        static DROPS: AtomicUsize = AtomicUsize::new(0);
-
-        struct D;
-        impl Drop for D {
-            fn drop(&mut self) {
-                DROPS.fetch_add(1, Ordering::SeqCst);
-            }
-        }
-
-        // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
-        let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
-        {
-            let mut it = map.drain_filter(|i, _| {
-                PREDS.fetch_add(1usize << i, Ordering::SeqCst);
-                match i {
-                    0 => true,
-                    _ => panic!(),
-                }
-            });
-            catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
-            // Iterator behaviour after a panic is explicitly unspecified,
-            // so this is just the current implementation:
-            let result = catch_unwind(AssertUnwindSafe(|| it.next()));
-            assert!(matches!(result, Ok(None)));
-        }
-
-        assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-        assert_eq!(DROPS.load(Ordering::SeqCst), 1);
-        assert_eq!(map.len(), 2);
-        assert_eq!(map.first_entry().unwrap().key(), &4);
-        assert_eq!(map.last_entry().unwrap().key(), &8);
-    }
-}
-
-#[test]
-fn test_borrow() {
-    // make sure these compile -- using the Borrow trait
-    {
-        let mut map = BTreeMap::new();
-        map.insert("0".to_string(), 1);
-        assert_eq!(map["0"], 1);
-    }
-
-    {
-        let mut map = BTreeMap::new();
-        map.insert(Box::new(0), 1);
-        assert_eq!(map[&0], 1);
-    }
-
-    {
-        let mut map = BTreeMap::new();
-        map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
-        assert_eq!(map[&[0, 1][..]], 1);
-    }
-
-    {
-        let mut map = BTreeMap::new();
-        map.insert(Rc::new(0), 1);
-        assert_eq!(map[&0], 1);
-    }
-}
-
-#[test]
-fn test_entry() {
-    let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-    let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
-
-    // Existing key (insert)
-    match map.entry(1) {
-        Vacant(_) => unreachable!(),
-        Occupied(mut view) => {
-            assert_eq!(view.get(), &10);
-            assert_eq!(view.insert(100), 10);
-        }
-    }
-    assert_eq!(map.get(&1).unwrap(), &100);
-    assert_eq!(map.len(), 6);
-
-    // Existing key (update)
-    match map.entry(2) {
-        Vacant(_) => unreachable!(),
-        Occupied(mut view) => {
-            let v = view.get_mut();
-            *v *= 10;
-        }
-    }
-    assert_eq!(map.get(&2).unwrap(), &200);
-    assert_eq!(map.len(), 6);
-
-    // Existing key (take)
-    match map.entry(3) {
-        Vacant(_) => unreachable!(),
-        Occupied(view) => {
-            assert_eq!(view.remove(), 30);
-        }
-    }
-    assert_eq!(map.get(&3), None);
-    assert_eq!(map.len(), 5);
-
-    // Inexistent key (insert)
-    match map.entry(10) {
-        Occupied(_) => unreachable!(),
-        Vacant(view) => {
-            assert_eq!(*view.insert(1000), 1000);
-        }
-    }
-    assert_eq!(map.get(&10).unwrap(), &1000);
-    assert_eq!(map.len(), 6);
-}
-
-#[test]
-fn test_extend_ref() {
-    let mut a = BTreeMap::new();
-    a.insert(1, "one");
-    let mut b = BTreeMap::new();
-    b.insert(2, "two");
-    b.insert(3, "three");
-
-    a.extend(&b);
-
-    assert_eq!(a.len(), 3);
-    assert_eq!(a[&1], "one");
-    assert_eq!(a[&2], "two");
-    assert_eq!(a[&3], "three");
-}
-
-#[test]
-fn test_zst() {
-    let mut m = BTreeMap::new();
-    assert_eq!(m.len(), 0);
-
-    assert_eq!(m.insert((), ()), None);
-    assert_eq!(m.len(), 1);
-
-    assert_eq!(m.insert((), ()), Some(()));
-    assert_eq!(m.len(), 1);
-    assert_eq!(m.iter().count(), 1);
-
-    m.clear();
-    assert_eq!(m.len(), 0);
-
-    for _ in 0..100 {
-        m.insert((), ());
-    }
-
-    assert_eq!(m.len(), 1);
-    assert_eq!(m.iter().count(), 1);
-}
-
-// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
-// do not cause segfaults when used with zero-sized values. All other map behavior is
-// undefined.
-#[test]
-fn test_bad_zst() {
-    use std::cmp::Ordering;
-
-    struct Bad;
-
-    impl PartialEq for Bad {
-        fn eq(&self, _: &Self) -> bool {
-            false
-        }
-    }
-
-    impl Eq for Bad {}
-
-    impl PartialOrd for Bad {
-        fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
-            Some(Ordering::Less)
-        }
-    }
-
-    impl Ord for Bad {
-        fn cmp(&self, _: &Self) -> Ordering {
-            Ordering::Less
-        }
-    }
-
-    let mut m = BTreeMap::new();
-
-    for _ in 0..100 {
-        m.insert(Bad, Bad);
-    }
-}
-
-#[test]
-fn test_clone() {
-    let mut map = BTreeMap::new();
-    let size = MIN_INSERTS_HEIGHT_1;
-    assert_eq!(map.len(), 0);
-
-    for i in 0..size {
-        assert_eq!(map.insert(i, 10 * i), None);
-        assert_eq!(map.len(), i + 1);
-        assert_eq!(map, map.clone());
-    }
-
-    for i in 0..size {
-        assert_eq!(map.insert(i, 100 * i), Some(10 * i));
-        assert_eq!(map.len(), size);
-        assert_eq!(map, map.clone());
-    }
-
-    for i in 0..size / 2 {
-        assert_eq!(map.remove(&(i * 2)), Some(i * 200));
-        assert_eq!(map.len(), size - i - 1);
-        assert_eq!(map, map.clone());
-    }
-
-    for i in 0..size / 2 {
-        assert_eq!(map.remove(&(2 * i)), None);
-        assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
-        assert_eq!(map.len(), size / 2 - i - 1);
-        assert_eq!(map, map.clone());
-    }
-
-    // Test a tree with 2 chock-full levels and a tree with 3 levels.
-    map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
-    assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
-    assert_eq!(map, map.clone());
-    map.insert(0, 0);
-    assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2);
-    assert_eq!(map, map.clone());
-}
-
-#[test]
-fn test_clone_from() {
-    let mut map1 = BTreeMap::new();
-    let max_size = MIN_INSERTS_HEIGHT_1;
-
-    // Range to max_size inclusive, because i is the size of map1 being tested.
-    for i in 0..=max_size {
-        let mut map2 = BTreeMap::new();
-        for j in 0..i {
-            let mut map1_copy = map2.clone();
-            map1_copy.clone_from(&map1); // small cloned from large
-            assert_eq!(map1_copy, map1);
-            let mut map2_copy = map1.clone();
-            map2_copy.clone_from(&map2); // large cloned from small
-            assert_eq!(map2_copy, map2);
-            map2.insert(100 * j + 1, 2 * j + 1);
-        }
-        map2.clone_from(&map1); // same length
-        assert_eq!(map2, map1);
-        map1.insert(i, 10 * i);
-    }
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
-    use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
-
-    fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
-        v
-    }
-    fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
-        v
-    }
-    fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
-        v
-    }
-    fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
-        v
-    }
-    fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
-        v
-    }
-    fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
-        v
-    }
-    fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
-        v
-    }
-    fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
-        v
-    }
-    fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
-        v
-    }
-    fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
-        v
-    }
-}
-
-#[test]
-fn test_occupied_entry_key() {
-    let mut a = BTreeMap::new();
-    let key = "hello there";
-    let value = "value goes here";
-    assert!(a.is_empty());
-    a.insert(key.clone(), value.clone());
-    assert_eq!(a.len(), 1);
-    assert_eq!(a[key], value);
-
-    match a.entry(key.clone()) {
-        Vacant(_) => panic!(),
-        Occupied(e) => assert_eq!(key, *e.key()),
-    }
-    assert_eq!(a.len(), 1);
-    assert_eq!(a[key], value);
-}
-
-#[test]
-fn test_vacant_entry_key() {
-    let mut a = BTreeMap::new();
-    let key = "hello there";
-    let value = "value goes here";
-
-    assert!(a.is_empty());
-    match a.entry(key.clone()) {
-        Occupied(_) => panic!(),
-        Vacant(e) => {
-            assert_eq!(key, *e.key());
-            e.insert(value.clone());
-        }
-    }
-    assert_eq!(a.len(), 1);
-    assert_eq!(a[key], value);
-}
-
-#[test]
-fn test_first_last_entry() {
-    let mut a = BTreeMap::new();
-    assert!(a.first_entry().is_none());
-    assert!(a.last_entry().is_none());
-    a.insert(1, 42);
-    assert_eq!(a.first_entry().unwrap().key(), &1);
-    assert_eq!(a.last_entry().unwrap().key(), &1);
-    a.insert(2, 24);
-    assert_eq!(a.first_entry().unwrap().key(), &1);
-    assert_eq!(a.last_entry().unwrap().key(), &2);
-    a.insert(0, 6);
-    assert_eq!(a.first_entry().unwrap().key(), &0);
-    assert_eq!(a.last_entry().unwrap().key(), &2);
-    let (k1, v1) = a.first_entry().unwrap().remove_entry();
-    assert_eq!(k1, 0);
-    assert_eq!(v1, 6);
-    let (k2, v2) = a.last_entry().unwrap().remove_entry();
-    assert_eq!(k2, 2);
-    assert_eq!(v2, 24);
-    assert_eq!(a.first_entry().unwrap().key(), &1);
-    assert_eq!(a.last_entry().unwrap().key(), &1);
-}
-
-macro_rules! create_append_test {
-    ($name:ident, $len:expr) => {
-        #[test]
-        fn $name() {
-            let mut a = BTreeMap::new();
-            for i in 0..8 {
-                a.insert(i, i);
-            }
-
-            let mut b = BTreeMap::new();
-            for i in 5..$len {
-                b.insert(i, 2 * i);
-            }
-
-            a.append(&mut b);
-
-            assert_eq!(a.len(), $len);
-            assert_eq!(b.len(), 0);
-
-            for i in 0..$len {
-                if i < 5 {
-                    assert_eq!(a[&i], i);
-                } else {
-                    assert_eq!(a[&i], 2 * i);
-                }
-            }
-
-            assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1)));
-            assert_eq!(a.insert($len - 1, 20), None);
-        }
-    };
-}
-
-// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
-// Single node.
-create_append_test!(test_append_9, 9);
-// Two leafs that don't need fixing.
-create_append_test!(test_append_17, 17);
-// Two leafs where the second one ends up underfull and needs stealing at the end.
-create_append_test!(test_append_14, 14);
-// Two leafs where the second one ends up empty because the insertion finished at the root.
-create_append_test!(test_append_12, 12);
-// Three levels; insertion finished at the root.
-create_append_test!(test_append_144, 144);
-// Three levels; insertion finished at leaf while there is an empty node on the second level.
-create_append_test!(test_append_145, 145);
-// Tests for several randomly chosen sizes.
-create_append_test!(test_append_170, 170);
-create_append_test!(test_append_181, 181);
-#[cfg(not(miri))] // Miri is too slow
-create_append_test!(test_append_239, 239);
-#[cfg(not(miri))] // Miri is too slow
-create_append_test!(test_append_1700, 1700);
-
-fn rand_data(len: usize) -> Vec<(u32, u32)> {
-    let mut rng = DeterministicRng::new();
-    Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
-}
-
-#[test]
-fn test_split_off_empty_right() {
-    let mut data = rand_data(173);
-
-    let mut map = BTreeMap::from_iter(data.clone());
-    let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
-
-    data.sort();
-    assert!(map.into_iter().eq(data));
-    assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
-    let mut data = rand_data(314);
-
-    let mut map = BTreeMap::from_iter(data.clone());
-    let right = map.split_off(&data.iter().min().unwrap().0);
-
-    data.sort();
-    assert!(map.into_iter().eq(None));
-    assert!(right.into_iter().eq(data));
-}
-
-// In a tree with 3 levels, if all but a part of the first leaf node is split off,
-// make sure fix_top eliminates both top levels.
-#[test]
-fn test_split_off_tiny_left_height_2() {
-    let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
-    let mut left: BTreeMap<_, _> = pairs.clone().collect();
-    let right = left.split_off(&1);
-    assert_eq!(left.len(), 1);
-    assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1);
-    assert_eq!(*left.first_key_value().unwrap().0, 0);
-    assert_eq!(*right.first_key_value().unwrap().0, 1);
-}
-
-// In a tree with 3 levels, if only part of the last leaf node is split off,
-// make sure fix_top eliminates both top levels.
-#[test]
-fn test_split_off_tiny_right_height_2() {
-    let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
-    let last = MIN_INSERTS_HEIGHT_2 - 1;
-    let mut left: BTreeMap<_, _> = pairs.clone().collect();
-    assert_eq!(*left.last_key_value().unwrap().0, last);
-    let right = left.split_off(&last);
-    assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1);
-    assert_eq!(right.len(), 1);
-    assert_eq!(*left.last_key_value().unwrap().0, last - 1);
-    assert_eq!(*right.last_key_value().unwrap().0, last);
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
-    // Miri is too slow
-    let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
-    // special case with maximum height.
-    data.sort();
-
-    let mut map = BTreeMap::from_iter(data.clone());
-    let key = data[data.len() / 2].0;
-    let right = map.split_off(&key);
-
-    assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
-    assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
-}
-
-#[test]
-fn test_into_iter_drop_leak_height_0() {
-    static DROPS: AtomicUsize = AtomicUsize::new(0);
-
-    struct D;
-
-    impl Drop for D {
-        fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
-    let mut map = BTreeMap::new();
-    map.insert("a", D);
-    map.insert("b", D);
-    map.insert("c", D);
-    map.insert("d", D);
-    map.insert("e", D);
-
-    catch_unwind(move || drop(map.into_iter())).unwrap_err();
-
-    assert_eq!(DROPS.load(Ordering::SeqCst), 5);
-}
-
-#[test]
-fn test_into_iter_drop_leak_height_1() {
-    let size = MIN_INSERTS_HEIGHT_1;
-    static DROPS: AtomicUsize = AtomicUsize::new(0);
-    static PANIC_POINT: AtomicUsize = AtomicUsize::new(0);
-
-    struct D;
-    impl Drop for D {
-        fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
-    for panic_point in vec![0, 1, size - 2, size - 1] {
-        DROPS.store(0, Ordering::SeqCst);
-        PANIC_POINT.store(panic_point, Ordering::SeqCst);
-        let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
-        catch_unwind(move || drop(map.into_iter())).unwrap_err();
-        assert_eq!(DROPS.load(Ordering::SeqCst), size);
-    }
-}
-
-#[test]
-fn test_into_keys() {
-    let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-    let map: BTreeMap<_, _> = vec.into_iter().collect();
-    let keys: Vec<_> = map.into_keys().collect();
-
-    assert_eq!(keys.len(), 3);
-    assert!(keys.contains(&1));
-    assert!(keys.contains(&2));
-    assert!(keys.contains(&3));
-}
-
-#[test]
-fn test_into_values() {
-    let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-    let map: BTreeMap<_, _> = vec.into_iter().collect();
-    let values: Vec<_> = map.into_values().collect();
-
-    assert_eq!(values.len(), 3);
-    assert!(values.contains(&'a'));
-    assert!(values.contains(&'b'));
-    assert!(values.contains(&'c'));
-}
diff --git a/library/alloc/tests/btree/mod.rs b/library/alloc/tests/btree/mod.rs
deleted file mode 100644 (file)
index 1d08ae1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-mod map;
-mod set;
-
-/// XorShiftRng
-struct DeterministicRng {
-    x: u32,
-    y: u32,
-    z: u32,
-    w: u32,
-}
-
-impl DeterministicRng {
-    fn new() -> Self {
-        DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
-    }
-
-    fn next(&mut self) -> u32 {
-        let x = self.x;
-        let t = x ^ (x << 11);
-        self.x = self.y;
-        self.y = self.z;
-        self.z = self.w;
-        let w_ = self.w;
-        self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
-        self.w
-    }
-}
diff --git a/library/alloc/tests/btree/set.rs b/library/alloc/tests/btree/set.rs
deleted file mode 100644 (file)
index b6c34b7..0000000
+++ /dev/null
@@ -1,666 +0,0 @@
-use std::collections::BTreeSet;
-use std::iter::FromIterator;
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicU32, Ordering};
-
-use super::DeterministicRng;
-
-#[test]
-fn test_clone_eq() {
-    let mut m = BTreeSet::new();
-
-    m.insert(1);
-    m.insert(2);
-
-    assert_eq!(m.clone(), m);
-}
-
-#[test]
-fn test_hash() {
-    use crate::hash;
-
-    let mut x = BTreeSet::new();
-    let mut y = BTreeSet::new();
-
-    x.insert(1);
-    x.insert(2);
-    x.insert(3);
-
-    y.insert(3);
-    y.insert(2);
-    y.insert(1);
-
-    assert_eq!(hash(&x), hash(&y));
-}
-
-#[test]
-fn test_iter_min_max() {
-    let mut a = BTreeSet::new();
-    assert_eq!(a.iter().min(), None);
-    assert_eq!(a.iter().max(), None);
-    assert_eq!(a.range(..).min(), None);
-    assert_eq!(a.range(..).max(), None);
-    assert_eq!(a.difference(&BTreeSet::new()).min(), None);
-    assert_eq!(a.difference(&BTreeSet::new()).max(), None);
-    assert_eq!(a.intersection(&a).min(), None);
-    assert_eq!(a.intersection(&a).max(), None);
-    assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None);
-    assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None);
-    assert_eq!(a.union(&a).min(), None);
-    assert_eq!(a.union(&a).max(), None);
-    a.insert(1);
-    a.insert(2);
-    assert_eq!(a.iter().min(), Some(&1));
-    assert_eq!(a.iter().max(), Some(&2));
-    assert_eq!(a.range(..).min(), Some(&1));
-    assert_eq!(a.range(..).max(), Some(&2));
-    assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1));
-    assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2));
-    assert_eq!(a.intersection(&a).min(), Some(&1));
-    assert_eq!(a.intersection(&a).max(), Some(&2));
-    assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1));
-    assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2));
-    assert_eq!(a.union(&a).min(), Some(&1));
-    assert_eq!(a.union(&a).max(), Some(&2));
-}
-
-fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
-where
-    F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool,
-{
-    let mut set_a = BTreeSet::new();
-    let mut set_b = BTreeSet::new();
-
-    for x in a {
-        assert!(set_a.insert(*x))
-    }
-    for y in b {
-        assert!(set_b.insert(*y))
-    }
-
-    let mut i = 0;
-    f(&set_a, &set_b, &mut |&x| {
-        if i < expected.len() {
-            assert_eq!(x, expected[i]);
-        }
-        i += 1;
-        true
-    });
-    assert_eq!(i, expected.len());
-}
-
-#[test]
-fn test_intersection() {
-    fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
-        check(a, b, expected, |x, y, f| x.intersection(y).all(f))
-    }
-
-    check_intersection(&[], &[], &[]);
-    check_intersection(&[1, 2, 3], &[], &[]);
-    check_intersection(&[], &[1, 2, 3], &[]);
-    check_intersection(&[2], &[1, 2, 3], &[2]);
-    check_intersection(&[1, 2, 3], &[2], &[2]);
-    check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]);
-
-    if cfg!(miri) {
-        // Miri is too slow
-        return;
-    }
-
-    let large = (0..100).collect::<Vec<_>>();
-    check_intersection(&[], &large, &[]);
-    check_intersection(&large, &[], &[]);
-    check_intersection(&[-1], &large, &[]);
-    check_intersection(&large, &[-1], &[]);
-    check_intersection(&[0], &large, &[0]);
-    check_intersection(&large, &[0], &[0]);
-    check_intersection(&[99], &large, &[99]);
-    check_intersection(&large, &[99], &[99]);
-    check_intersection(&[100], &large, &[]);
-    check_intersection(&large, &[100], &[]);
-    check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]);
-}
-
-#[test]
-fn test_intersection_size_hint() {
-    let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
-    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
-    let mut iter = x.intersection(&y);
-    assert_eq!(iter.size_hint(), (1, Some(1)));
-    assert_eq!(iter.next(), Some(&3));
-    assert_eq!(iter.size_hint(), (0, Some(0)));
-    assert_eq!(iter.next(), None);
-
-    iter = y.intersection(&y);
-    assert_eq!(iter.size_hint(), (0, Some(3)));
-    assert_eq!(iter.next(), Some(&1));
-    assert_eq!(iter.size_hint(), (0, Some(2)));
-}
-
-#[test]
-fn test_difference() {
-    fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
-        check(a, b, expected, |x, y, f| x.difference(y).all(f))
-    }
-
-    check_difference(&[], &[], &[]);
-    check_difference(&[1, 12], &[], &[1, 12]);
-    check_difference(&[], &[1, 2, 3, 9], &[]);
-    check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
-    check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]);
-    check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]);
-    check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]);
-    check_difference(
-        &[-5, 11, 22, 33, 40, 42],
-        &[-12, -5, 14, 23, 34, 38, 39, 50],
-        &[11, 22, 33, 40, 42],
-    );
-
-    if cfg!(miri) {
-        // Miri is too slow
-        return;
-    }
-
-    let large = (0..100).collect::<Vec<_>>();
-    check_difference(&[], &large, &[]);
-    check_difference(&[-1], &large, &[-1]);
-    check_difference(&[0], &large, &[]);
-    check_difference(&[99], &large, &[]);
-    check_difference(&[100], &large, &[100]);
-    check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]);
-    check_difference(&large, &[], &large);
-    check_difference(&large, &[-1], &large);
-    check_difference(&large, &[100], &large);
-}
-
-#[test]
-fn test_difference_size_hint() {
-    let s246: BTreeSet<i32> = [2, 4, 6].iter().copied().collect();
-    let s23456: BTreeSet<i32> = (2..=6).collect();
-    let mut iter = s246.difference(&s23456);
-    assert_eq!(iter.size_hint(), (0, Some(3)));
-    assert_eq!(iter.next(), None);
-
-    let s12345: BTreeSet<i32> = (1..=5).collect();
-    iter = s246.difference(&s12345);
-    assert_eq!(iter.size_hint(), (0, Some(3)));
-    assert_eq!(iter.next(), Some(&6));
-    assert_eq!(iter.size_hint(), (0, Some(0)));
-    assert_eq!(iter.next(), None);
-
-    let s34567: BTreeSet<i32> = (3..=7).collect();
-    iter = s246.difference(&s34567);
-    assert_eq!(iter.size_hint(), (0, Some(3)));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.size_hint(), (0, Some(2)));
-    assert_eq!(iter.next(), None);
-
-    let s1: BTreeSet<i32> = (-9..=1).collect();
-    iter = s246.difference(&s1);
-    assert_eq!(iter.size_hint(), (3, Some(3)));
-
-    let s2: BTreeSet<i32> = (-9..=2).collect();
-    iter = s246.difference(&s2);
-    assert_eq!(iter.size_hint(), (2, Some(2)));
-    assert_eq!(iter.next(), Some(&4));
-    assert_eq!(iter.size_hint(), (1, Some(1)));
-
-    let s23: BTreeSet<i32> = (2..=3).collect();
-    iter = s246.difference(&s23);
-    assert_eq!(iter.size_hint(), (1, Some(3)));
-    assert_eq!(iter.next(), Some(&4));
-    assert_eq!(iter.size_hint(), (1, Some(1)));
-
-    let s4: BTreeSet<i32> = (4..=4).collect();
-    iter = s246.difference(&s4);
-    assert_eq!(iter.size_hint(), (2, Some(3)));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.size_hint(), (1, Some(2)));
-    assert_eq!(iter.next(), Some(&6));
-    assert_eq!(iter.size_hint(), (0, Some(0)));
-    assert_eq!(iter.next(), None);
-
-    let s56: BTreeSet<i32> = (5..=6).collect();
-    iter = s246.difference(&s56);
-    assert_eq!(iter.size_hint(), (1, Some(3)));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.size_hint(), (0, Some(2)));
-
-    let s6: BTreeSet<i32> = (6..=19).collect();
-    iter = s246.difference(&s6);
-    assert_eq!(iter.size_hint(), (2, Some(2)));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.size_hint(), (1, Some(1)));
-
-    let s7: BTreeSet<i32> = (7..=19).collect();
-    iter = s246.difference(&s7);
-    assert_eq!(iter.size_hint(), (3, Some(3)));
-}
-
-#[test]
-fn test_symmetric_difference() {
-    fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
-        check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
-    }
-
-    check_symmetric_difference(&[], &[], &[]);
-    check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
-    check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
-    check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]);
-}
-
-#[test]
-fn test_symmetric_difference_size_hint() {
-    let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
-    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
-    let mut iter = x.symmetric_difference(&y);
-    assert_eq!(iter.size_hint(), (0, Some(5)));
-    assert_eq!(iter.next(), Some(&1));
-    assert_eq!(iter.size_hint(), (0, Some(4)));
-    assert_eq!(iter.next(), Some(&3));
-    assert_eq!(iter.size_hint(), (0, Some(1)));
-}
-
-#[test]
-fn test_union() {
-    fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
-        check(a, b, expected, |x, y, f| x.union(y).all(f))
-    }
-
-    check_union(&[], &[], &[]);
-    check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
-    check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
-    check_union(
-        &[1, 3, 5, 9, 11, 16, 19, 24],
-        &[-2, 1, 5, 9, 13, 19],
-        &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24],
-    );
-}
-
-#[test]
-fn test_union_size_hint() {
-    let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
-    let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
-    let mut iter = x.union(&y);
-    assert_eq!(iter.size_hint(), (3, Some(5)));
-    assert_eq!(iter.next(), Some(&1));
-    assert_eq!(iter.size_hint(), (2, Some(4)));
-    assert_eq!(iter.next(), Some(&2));
-    assert_eq!(iter.size_hint(), (1, Some(2)));
-}
-
-#[test]
-// Only tests the simple function definition with respect to intersection
-fn test_is_disjoint() {
-    let one = [1].iter().collect::<BTreeSet<_>>();
-    let two = [2].iter().collect::<BTreeSet<_>>();
-    assert!(one.is_disjoint(&two));
-}
-
-#[test]
-// Also implicitly tests the trivial function definition of is_superset
-fn test_is_subset() {
-    fn is_subset(a: &[i32], b: &[i32]) -> bool {
-        let set_a = a.iter().collect::<BTreeSet<_>>();
-        let set_b = b.iter().collect::<BTreeSet<_>>();
-        set_a.is_subset(&set_b)
-    }
-
-    assert_eq!(is_subset(&[], &[]), true);
-    assert_eq!(is_subset(&[], &[1, 2]), true);
-    assert_eq!(is_subset(&[0], &[1, 2]), false);
-    assert_eq!(is_subset(&[1], &[1, 2]), true);
-    assert_eq!(is_subset(&[2], &[1, 2]), true);
-    assert_eq!(is_subset(&[3], &[1, 2]), false);
-    assert_eq!(is_subset(&[1, 2], &[1]), false);
-    assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
-    assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
-    assert_eq!(
-        is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
-        true
-    );
-    assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false);
-
-    if cfg!(miri) {
-        // Miri is too slow
-        return;
-    }
-
-    let large = (0..100).collect::<Vec<_>>();
-    assert_eq!(is_subset(&[], &large), true);
-    assert_eq!(is_subset(&large, &[]), false);
-    assert_eq!(is_subset(&[-1], &large), false);
-    assert_eq!(is_subset(&[0], &large), true);
-    assert_eq!(is_subset(&[1, 2], &large), true);
-    assert_eq!(is_subset(&[99, 100], &large), false);
-}
-
-#[test]
-fn test_drain_filter() {
-    let mut x: BTreeSet<_> = [1].iter().copied().collect();
-    let mut y: BTreeSet<_> = [1].iter().copied().collect();
-
-    x.drain_filter(|_| true);
-    y.drain_filter(|_| false);
-    assert_eq!(x.len(), 0);
-    assert_eq!(y.len(), 1);
-}
-
-#[test]
-fn test_drain_filter_drop_panic_leak() {
-    static PREDS: AtomicU32 = AtomicU32::new(0);
-    static DROPS: AtomicU32 = AtomicU32::new(0);
-
-    #[derive(PartialEq, Eq, PartialOrd, Ord)]
-    struct D(i32);
-    impl Drop for D {
-        fn drop(&mut self) {
-            if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
-                panic!("panic in `drop`");
-            }
-        }
-    }
-
-    let mut set = BTreeSet::new();
-    set.insert(D(0));
-    set.insert(D(4));
-    set.insert(D(8));
-
-    catch_unwind(move || {
-        drop(set.drain_filter(|d| {
-            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
-            true
-        }))
-    })
-    .ok();
-
-    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-    assert_eq!(DROPS.load(Ordering::SeqCst), 3);
-}
-
-#[test]
-fn test_drain_filter_pred_panic_leak() {
-    static PREDS: AtomicU32 = AtomicU32::new(0);
-    static DROPS: AtomicU32 = AtomicU32::new(0);
-
-    #[derive(PartialEq, Eq, PartialOrd, Ord)]
-    struct D(i32);
-    impl Drop for D {
-        fn drop(&mut self) {
-            DROPS.fetch_add(1, Ordering::SeqCst);
-        }
-    }
-
-    let mut set = BTreeSet::new();
-    set.insert(D(0));
-    set.insert(D(4));
-    set.insert(D(8));
-
-    catch_unwind(AssertUnwindSafe(|| {
-        drop(set.drain_filter(|d| {
-            PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
-            match d.0 {
-                0 => true,
-                _ => panic!(),
-            }
-        }))
-    }))
-    .ok();
-
-    assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
-    assert_eq!(DROPS.load(Ordering::SeqCst), 1);
-    assert_eq!(set.len(), 2);
-    assert_eq!(set.first().unwrap().0, 4);
-    assert_eq!(set.last().unwrap().0, 8);
-}
-
-#[test]
-fn test_clear() {
-    let mut x = BTreeSet::new();
-    x.insert(1);
-
-    x.clear();
-    assert!(x.is_empty());
-}
-
-#[test]
-fn test_zip() {
-    let mut x = BTreeSet::new();
-    x.insert(5);
-    x.insert(12);
-    x.insert(11);
-
-    let mut y = BTreeSet::new();
-    y.insert("foo");
-    y.insert("bar");
-
-    let x = x;
-    let y = y;
-    let mut z = x.iter().zip(&y);
-
-    assert_eq!(z.next().unwrap(), (&5, &("bar")));
-    assert_eq!(z.next().unwrap(), (&11, &("foo")));
-    assert!(z.next().is_none());
-}
-
-#[test]
-fn test_from_iter() {
-    let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
-    let set: BTreeSet<_> = xs.iter().cloned().collect();
-
-    for x in &xs {
-        assert!(set.contains(x));
-    }
-}
-
-#[test]
-fn test_show() {
-    let mut set = BTreeSet::new();
-    let empty = BTreeSet::<i32>::new();
-
-    set.insert(1);
-    set.insert(2);
-
-    let set_str = format!("{:?}", set);
-
-    assert_eq!(set_str, "{1, 2}");
-    assert_eq!(format!("{:?}", empty), "{}");
-}
-
-#[test]
-fn test_extend_ref() {
-    let mut a = BTreeSet::new();
-    a.insert(1);
-
-    a.extend(&[2, 3, 4]);
-
-    assert_eq!(a.len(), 4);
-    assert!(a.contains(&1));
-    assert!(a.contains(&2));
-    assert!(a.contains(&3));
-    assert!(a.contains(&4));
-
-    let mut b = BTreeSet::new();
-    b.insert(5);
-    b.insert(6);
-
-    a.extend(&b);
-
-    assert_eq!(a.len(), 6);
-    assert!(a.contains(&1));
-    assert!(a.contains(&2));
-    assert!(a.contains(&3));
-    assert!(a.contains(&4));
-    assert!(a.contains(&5));
-    assert!(a.contains(&6));
-}
-
-#[test]
-fn test_recovery() {
-    use std::cmp::Ordering;
-
-    #[derive(Debug)]
-    struct Foo(&'static str, i32);
-
-    impl PartialEq for Foo {
-        fn eq(&self, other: &Self) -> bool {
-            self.0 == other.0
-        }
-    }
-
-    impl Eq for Foo {}
-
-    impl PartialOrd for Foo {
-        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-            self.0.partial_cmp(&other.0)
-        }
-    }
-
-    impl Ord for Foo {
-        fn cmp(&self, other: &Self) -> Ordering {
-            self.0.cmp(&other.0)
-        }
-    }
-
-    let mut s = BTreeSet::new();
-    assert_eq!(s.replace(Foo("a", 1)), None);
-    assert_eq!(s.len(), 1);
-    assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
-    assert_eq!(s.len(), 1);
-
-    {
-        let mut it = s.iter();
-        assert_eq!(it.next(), Some(&Foo("a", 2)));
-        assert_eq!(it.next(), None);
-    }
-
-    assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
-    assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
-    assert_eq!(s.len(), 0);
-
-    assert_eq!(s.get(&Foo("a", 1)), None);
-    assert_eq!(s.take(&Foo("a", 1)), None);
-
-    assert_eq!(s.iter().next(), None);
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
-    use std::collections::btree_set::{IntoIter, Iter, Range};
-
-    fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
-        v
-    }
-    fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
-        v
-    }
-    fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
-        v
-    }
-    fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
-        v
-    }
-}
-
-#[test]
-fn test_append() {
-    let mut a = BTreeSet::new();
-    a.insert(1);
-    a.insert(2);
-    a.insert(3);
-
-    let mut b = BTreeSet::new();
-    b.insert(3);
-    b.insert(4);
-    b.insert(5);
-
-    a.append(&mut b);
-
-    assert_eq!(a.len(), 5);
-    assert_eq!(b.len(), 0);
-
-    assert_eq!(a.contains(&1), true);
-    assert_eq!(a.contains(&2), true);
-    assert_eq!(a.contains(&3), true);
-    assert_eq!(a.contains(&4), true);
-    assert_eq!(a.contains(&5), true);
-}
-
-#[test]
-fn test_first_last() {
-    let mut a = BTreeSet::new();
-    assert_eq!(a.first(), None);
-    assert_eq!(a.last(), None);
-    a.insert(1);
-    assert_eq!(a.first(), Some(&1));
-    assert_eq!(a.last(), Some(&1));
-    a.insert(2);
-    assert_eq!(a.first(), Some(&1));
-    assert_eq!(a.last(), Some(&2));
-    for i in 3..=12 {
-        a.insert(i);
-    }
-    assert_eq!(a.first(), Some(&1));
-    assert_eq!(a.last(), Some(&12));
-    assert_eq!(a.pop_first(), Some(1));
-    assert_eq!(a.pop_last(), Some(12));
-    assert_eq!(a.pop_first(), Some(2));
-    assert_eq!(a.pop_last(), Some(11));
-    assert_eq!(a.pop_first(), Some(3));
-    assert_eq!(a.pop_last(), Some(10));
-    assert_eq!(a.pop_first(), Some(4));
-    assert_eq!(a.pop_first(), Some(5));
-    assert_eq!(a.pop_first(), Some(6));
-    assert_eq!(a.pop_first(), Some(7));
-    assert_eq!(a.pop_first(), Some(8));
-    assert_eq!(a.clone().pop_last(), Some(9));
-    assert_eq!(a.pop_first(), Some(9));
-    assert_eq!(a.pop_first(), None);
-    assert_eq!(a.pop_last(), None);
-}
-
-fn rand_data(len: usize) -> Vec<u32> {
-    let mut rng = DeterministicRng::new();
-    Vec::from_iter((0..len).map(|_| rng.next()))
-}
-
-#[test]
-fn test_split_off_empty_right() {
-    let mut data = rand_data(173);
-
-    let mut set = BTreeSet::from_iter(data.clone());
-    let right = set.split_off(&(data.iter().max().unwrap() + 1));
-
-    data.sort();
-    assert!(set.into_iter().eq(data));
-    assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
-    let mut data = rand_data(314);
-
-    let mut set = BTreeSet::from_iter(data.clone());
-    let right = set.split_off(data.iter().min().unwrap());
-
-    data.sort();
-    assert!(set.into_iter().eq(None));
-    assert!(right.into_iter().eq(data));
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
-    // Miri is too slow
-    let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
-    // special case with maximum height.
-    data.sort();
-
-    let mut set = BTreeSet::from_iter(data.clone());
-    let key = data[data.len() / 2];
-    let right = set.split_off(&key);
-
-    assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
-    assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
-}
diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs
new file mode 100644 (file)
index 0000000..e06a95d
--- /dev/null
@@ -0,0 +1,19 @@
+use std::collections::BTreeSet;
+
+#[test]
+fn test_hash() {
+    use crate::hash;
+
+    let mut x = BTreeSet::new();
+    let mut y = BTreeSet::new();
+
+    x.insert(1);
+    x.insert(2);
+    x.insert(3);
+
+    y.insert(3);
+    y.insert(2);
+    y.insert(1);
+
+    assert_eq!(hash(&x), hash(&y));
+}
index 3aacd4a687e384b454ab9eb12a83b732022208a7..f2ba1ab64810b11a73a86d910516e36a3ea4f377 100644 (file)
@@ -1,10 +1,7 @@
 #![feature(allocator_api)]
 #![feature(box_syntax)]
-#![feature(btree_drain_filter)]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
-#![feature(map_first_last)]
-#![feature(map_into_keys_values)]
 #![feature(new_uninit)]
 #![feature(pattern)]
 #![feature(str_split_once)]
@@ -25,7 +22,7 @@
 mod binary_heap;
 mod borrow;
 mod boxed;
-mod btree;
+mod btree_set_hash;
 mod cow_str;
 mod fmt;
 mod heap;
index c0bf3833b9c3366a3ce5e82bb588f4902bd25ca7..6b28ab7d755631f68860ed2cd402f9d1cb20c418 100644 (file)
@@ -364,3 +364,66 @@ macro_rules! array_impl_default {
 }
 
 array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
+
+#[cfg(not(bootstrap))]
+#[lang = "array"]
+impl<T, const N: usize> [T; N] {
+    /// Returns an array of the same size as `self`, with function `f` applied to each element
+    /// in order.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(array_map)]
+    /// let x = [1, 2, 3];
+    /// let y = x.map(|v| v + 1);
+    /// assert_eq!(y, [2, 3, 4]);
+    ///
+    /// let x = [1, 2, 3];
+    /// let mut temp = 0;
+    /// let y = x.map(|v| { temp += 1; v * temp });
+    /// assert_eq!(y, [1, 4, 9]);
+    ///
+    /// let x = ["Ferris", "Bueller's", "Day", "Off"];
+    /// let y = x.map(|v| v.len());
+    /// assert_eq!(y, [6, 9, 3, 3]);
+    /// ```
+    #[unstable(feature = "array_map", issue = "75243")]
+    pub fn map<F, U>(self, mut f: F) -> [U; N]
+    where
+        F: FnMut(T) -> U,
+    {
+        use crate::mem::MaybeUninit;
+        struct Guard<T, const N: usize> {
+            dst: *mut T,
+            initialized: usize,
+        }
+
+        impl<T, const N: usize> Drop for Guard<T, N> {
+            fn drop(&mut self) {
+                debug_assert!(self.initialized <= N);
+
+                let initialized_part =
+                    crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
+                // SAFETY: this raw slice will contain only initialized objects
+                // that's why, it is allowed to drop it.
+                unsafe {
+                    crate::ptr::drop_in_place(initialized_part);
+                }
+            }
+        }
+        let mut dst = MaybeUninit::uninit_array::<N>();
+        let mut guard: Guard<U, N> =
+            Guard { dst: MaybeUninit::first_ptr_mut(&mut dst), initialized: 0 };
+        for (src, dst) in IntoIter::new(self).zip(&mut dst) {
+            dst.write(f(src));
+            guard.initialized += 1;
+        }
+        // FIXME: Convert to crate::mem::transmute once it works with generics.
+        // unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
+        crate::mem::forget(guard);
+        // SAFETY: At this point we've properly initialized the whole array
+        // and we just need to cast it to the correct type.
+        unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
+    }
+}
index c329eec76ac3d9e28afc61a2adae447ffa1006b5..394db5b5917f007a82253f9df9cfcc50b1d473cd 100644 (file)
 /// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
 /// for a [`char`].
 ///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-///
 /// For an unsafe version of this function which ignores these checks, see
 /// [`from_u32_unchecked`].
 ///
-/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
-///
 /// # Examples
 ///
 /// Basic usage:
@@ -74,17 +69,12 @@ pub fn from_u32(i: u32) -> Option<char> {
 /// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
 /// [`char`], possibly creating an invalid one.
 ///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-///
 /// # Safety
 ///
 /// This function is unsafe, as it may construct invalid `char` values.
 ///
 /// For a safe version of this function, see the [`from_u32`] function.
 ///
-/// [`from_u32`]: fn.from_u32.html
-///
 /// # Examples
 ///
 /// Basic usage:
index 3dc0ee2b555300d8c5183b3141517fb1b8a15c98..461b4c79a1d1c12b8faf03978f2619d19b91f50b 100644 (file)
@@ -24,7 +24,6 @@
 /// Otherwise, consider using the [`unreachable!`] macro, which does not allow
 /// optimizations but will panic when executed.
 ///
-/// [`unreachable!`]: ../macro.unreachable.html
 ///
 /// # Example
 ///
@@ -61,7 +60,7 @@
 /// **Note**: On platforms that do not support receiving spin-loop hints this function does not
 /// do anything at all.
 ///
-/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
+/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
index 3ea3eeed6b0434f3f4f5fc7b3b5569051a255249..f89b616c4e23bd9b9b0a8125038095d60e96e5b9 100644 (file)
@@ -1543,11 +1543,10 @@ fn by_ref(&mut self) -> &mut Self
     /// collection into another. You take a collection, call [`iter`] on it,
     /// do a bunch of transformations, and then `collect()` at the end.
     ///
-    /// One of the keys to `collect()`'s power is that many things you might
-    /// not think of as 'collections' actually are. For example, a [`String`]
-    /// is a collection of [`char`]s. And a collection of
-    /// [`Result<T, E>`][`Result`] can be thought of as single
-    /// [`Result`]`<Collection<T>, E>`. See the examples below for more.
+    /// `collect()` can also create instances of types that are not typical
+    /// collections. For example, a [`String`] can be built from [`char`]s,
+    /// and an iterator of [`Result<T, E>`][`Result`] items can be collected
+    /// into `Result<Collection<T>, E>`. See the examples below for more.
     ///
     /// Because `collect()` is so general, it can cause problems with type
     /// inference. As such, `collect()` is one of the few times you'll see
index fcf5454308b475a73a412bc720bddc4e905d3892..763457d485da451a7195dffeb7fb50b62b2b6531 100644 (file)
 #![feature(abi_unadjusted)]
 #![feature(adx_target_feature)]
 #![feature(maybe_uninit_slice)]
+#![feature(maybe_uninit_extra)]
 #![feature(external_doc)]
 #![feature(associated_type_bounds)]
 #![feature(const_caller_location)]
index 920f5e9c0bd28521e732e3e5159862168fd1c807..e45aa86c0795a915d7f5b079e4189d8a7999e3a7 100644 (file)
@@ -56,9 +56,9 @@
 /// working with [pinned] data, where reusing the memory without calling the destructor could lead
 /// to Undefined Behaviour.
 ///
-/// [`mem::zeroed`]: fn.zeroed.html
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-/// [pinned]: ../pin/index.html
+/// [`mem::zeroed`]: crate::mem::zeroed
+/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
+/// [pinned]: crate::pin
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -116,8 +116,6 @@ pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
     /// leaving the state of this container unchanged.
     /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
     ///
-    /// [`ManuallyDrop::drop`]: #method.drop
-    /// [`ManuallyDrop::into_inner`]: #method.into_inner
     #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
     #[stable(feature = "manually_drop_take", since = "1.42.0")]
     #[inline]
@@ -148,9 +146,7 @@ impl<T: ?Sized> ManuallyDrop<T> {
     /// This is normally prevented by the type system, but users of `ManuallyDrop` must
     /// uphold those guarantees without assistance from the compiler.
     ///
-    /// [`ManuallyDrop::into_inner`]: #method.into_inner
-    /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html
-    /// [pinned]: ../pin/index.html
+    /// [pinned]: crate::pin
     #[stable(feature = "manually_drop", since = "1.20.0")]
     #[inline]
     pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
index 027498d3911c8fcac38383ee5df5cb0add760480..d2d65fd2fa517027c365215f4e88c28e3dc98125 100644 (file)
@@ -247,7 +247,7 @@ impl<T> MaybeUninit<T> {
     /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
     /// It is your responsibility to make sure `T` gets dropped if it got initialized.
     ///
-    /// [`assume_init`]: #method.assume_init
+    /// [`assume_init`]: MaybeUninit::assume_init
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
     #[inline(always)]
@@ -525,7 +525,7 @@ pub unsafe fn assume_init(self) -> T {
     /// to ensure that that data may indeed be duplicated.
     ///
     /// [inv]: #initialization-invariant
-    /// [`assume_init`]: #method.assume_init
+    /// [`assume_init`]: MaybeUninit::assume_init
     ///
     /// # Examples
     ///
index 3c7211fe040dcd384226f59d85ebedd29d9ed00c..6d078fb0a54d61d89173b25fa047e00ab2550cd9 100644 (file)
 //! }
 //! ```
 //!
-//! [`Option`]: enum.Option.html
-//! [`Some`]: enum.Option.html#variant.Some
-//! [`None`]: enum.Option.html#variant.None
 //! [`Box<T>`]: ../../std/boxed/struct.Box.html
-//! [`i32`]: ../../std/primitive.i32.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
     ops::{self, Deref, DerefMut},
 };
 
-/// The `Option` type. See [the module level documentation](index.html) for more.
+/// The `Option` type. See [the module level documentation](self) for more.
 #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
 #[rustc_diagnostic_item = "option_type"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -175,8 +171,6 @@ impl<T> Option<T> {
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_some(), false);
     /// ```
-    ///
-    /// [`Some`]: #variant.Some
     #[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
     #[inline]
     #[rustc_const_unstable(feature = "const_option", issue = "67441")]
@@ -196,8 +190,6 @@ pub const fn is_some(&self) -> bool {
     /// let x: Option<u32> = None;
     /// assert_eq!(x.is_none(), true);
     /// ```
-    ///
-    /// [`None`]: #variant.None
     #[must_use = "if you intended to assert that this doesn't have a value, consider \
                   `.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"]
     #[inline]
@@ -249,9 +241,8 @@ pub fn contains<U>(&self, x: &U) -> bool
     /// so this technique uses `as_ref` to first take an `Option` to a reference
     /// to the value inside the original.
     ///
-    /// [`map`]: enum.Option.html#method.map
+    /// [`map`]: Option::map
     /// [`String`]: ../../std/string/struct.String.html
-    /// [`usize`]: ../../std/primitive.usize.html
     ///
     /// ```
     /// let text: Option<String> = Some("Hello, world!".to_string());
@@ -292,8 +283,6 @@ pub fn as_mut(&mut self) -> Option<&mut T> {
     }
 
     /// Converts from [`Pin`]`<&Option<T>>` to `Option<`[`Pin`]`<&T>>`.
-    ///
-    /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
@@ -303,8 +292,6 @@ pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
     }
 
     /// Converts from [`Pin`]`<&mut Option<T>>` to `Option<`[`Pin`]`<&mut T>>`.
-    ///
-    /// [`Pin`]: ../pin/struct.Pin.html
     #[inline]
     #[stable(feature = "pin", since = "1.33.0")]
     pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
@@ -324,9 +311,6 @@ pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
     /// Panics if the value is a [`None`] with a custom panic message provided by
     /// `msg`.
     ///
-    /// [`Some`]: #variant.Some
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -355,17 +339,14 @@ pub fn expect(self, msg: &str) -> T {
     /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
     /// [`unwrap_or_default`].
     ///
-    /// [`unwrap_or`]: #method.unwrap_or
-    /// [`unwrap_or_else`]: #method.unwrap_or_else
-    /// [`unwrap_or_default`]: #method.unwrap_or_default
+    /// [`unwrap_or`]: Option::unwrap_or
+    /// [`unwrap_or_else`]: Option::unwrap_or_else
+    /// [`unwrap_or_default`]: Option::unwrap_or_default
     ///
     /// # Panics
     ///
     /// Panics if the self value equals [`None`].
     ///
-    /// [`Some`]: #variant.Some
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -394,8 +375,7 @@ pub const fn unwrap(self) -> T {
     /// the result of a function call, it is recommended to use [`unwrap_or_else`],
     /// which is lazily evaluated.
     ///
-    /// [`Some`]: #variant.Some
-    /// [`unwrap_or_else`]: #method.unwrap_or_else
+    /// [`unwrap_or_else`]: Option::unwrap_or_else
     ///
     /// # Examples
     ///
@@ -441,8 +421,6 @@ pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
     /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, consuming the original:
     ///
     /// [`String`]: ../../std/string/struct.String.html
-    /// [`usize`]: ../../std/primitive.usize.html
-    ///
     /// ```
     /// let maybe_some_string = Some(String::from("Hello, World!"));
     /// // `Option::map` takes self *by value*, consuming `maybe_some_string`
@@ -466,7 +444,7 @@ pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
     /// the result of a function call, it is recommended to use [`map_or_else`],
     /// which is lazily evaluated.
     ///
-    /// [`map_or_else`]: #method.map_or_else
+    /// [`map_or_else`]: Option::map_or_else
     ///
     /// # Examples
     ///
@@ -516,12 +494,11 @@ pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f:
     /// result of a function call, it is recommended to use [`ok_or_else`], which is
     /// lazily evaluated.
     ///
-    /// [`Result<T, E>`]: ../../std/result/enum.Result.html
-    /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`None`]: #variant.None
-    /// [`Some(v)`]: #variant.Some
-    /// [`ok_or_else`]: #method.ok_or_else
+    /// [`Result<T, E>`]: Result
+    /// [`Ok(v)`]: Ok
+    /// [`Err(err)`]: Err
+    /// [`Some(v)`]: Some
+    /// [`ok_or_else`]: Option::ok_or_else
     ///
     /// # Examples
     ///
@@ -544,11 +521,10 @@ pub fn ok_or<E>(self, err: E) -> Result<T, E> {
     /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
     /// [`Ok(v)`] and [`None`] to [`Err(err())`].
     ///
-    /// [`Result<T, E>`]: ../../std/result/enum.Result.html
-    /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`None`]: #variant.None
-    /// [`Some(v)`]: #variant.Some
+    /// [`Result<T, E>`]: Result
+    /// [`Ok(v)`]: Ok
+    /// [`Err(err())`]: Err
+    /// [`Some(v)`]: Some
     ///
     /// # Examples
     ///
@@ -617,8 +593,6 @@ pub fn iter_mut(&mut self) -> IterMut<'_, T> {
 
     /// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
     ///
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -652,8 +626,6 @@ pub fn and<U>(self, optb: Option<U>) -> Option<U> {
     ///
     /// Some languages call this operation flatmap.
     ///
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -697,9 +669,6 @@ pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
     /// assert_eq!(Some(4).filter(is_even), Some(4));
     /// ```
     ///
-    /// [`None`]: #variant.None
-    /// [`Some(t)`]: #variant.Some
-    /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter
     #[inline]
     #[stable(feature = "option_filter", since = "1.27.0")]
     pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
@@ -717,7 +686,7 @@ pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
     /// result of a function call, it is recommended to use [`or_else`], which is
     /// lazily evaluated.
     ///
-    /// [`or_else`]: #method.or_else
+    /// [`or_else`]: Option::or_else
     ///
     /// # Examples
     ///
@@ -771,9 +740,6 @@ pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
 
     /// Returns [`Some`] if exactly one of `self`, `optb` is [`Some`], otherwise returns [`None`].
     ///
-    /// [`Some`]: #variant.Some
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -810,8 +776,6 @@ pub fn xor(self, optb: Option<T>) -> Option<T> {
     /// Inserts `v` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -835,8 +799,6 @@ pub fn get_or_insert(&mut self, v: T) -> &mut T {
     /// Inserts a value computed from `f` into the option if it is [`None`], then
     /// returns a mutable reference to the contained value.
     ///
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -872,8 +834,6 @@ pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
 
     /// Takes the value out of the option, leaving a [`None`] in its place.
     ///
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -897,8 +857,6 @@ pub fn take(&mut self) -> Option<T> {
     /// returning the old value if present,
     /// leaving a [`Some`] in its place without deinitializing either one.
     ///
-    /// [`Some`]: #variant.Some
-    ///
     /// # Examples
     ///
     /// ```
@@ -1062,9 +1020,6 @@ impl<T: fmt::Debug> Option<T> {
     /// Panics if the value is a [`Some`], with a panic message including the
     /// passed message, and the content of the [`Some`].
     ///
-    /// [`Some`]: #variant.Some
-    /// [`None`]: #variant.None
-    ///
     /// # Examples
     ///
     /// ```
@@ -1105,8 +1060,7 @@ pub fn expect_none(self, msg: &str) {
     /// Panics if the value is a [`Some`], with a custom panic message provided
     /// by the [`Some`]'s value.
     ///
-    /// [`Some(v)`]: #variant.Some
-    /// [`None`]: #variant.None
+    /// [`Some(v)`]: Some
     ///
     /// # Examples
     ///
@@ -1166,11 +1120,9 @@ impl<T: Default> Option<T> {
     /// assert_eq!(0, bad_year);
     /// ```
     ///
-    /// [`Some`]: #variant.Some
-    /// [`None`]: #variant.None
-    /// [default value]: ../default/trait.Default.html#tymethod.default
-    /// [`parse`]: ../../std/primitive.str.html#method.parse
-    /// [`FromStr`]: ../../std/str/trait.FromStr.html
+    /// [default value]: Default::default
+    /// [`parse`]: str::parse
+    /// [`FromStr`]: crate::str::FromStr
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_or_default(self) -> T {
@@ -1187,8 +1139,6 @@ impl<T: Deref> Option<T> {
     /// Leaves the original Option in-place, creating a new one with a reference
     /// to the original one, additionally coercing the contents via [`Deref`].
     ///
-    /// [`Deref`]: ../../std/ops/trait.Deref.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -1232,11 +1182,6 @@ impl<T, E> Option<Result<T, E>> {
     /// [`Some`]`(`[`Ok`]`(_))` and [`Some`]`(`[`Err`]`(_))` will be mapped to
     /// [`Ok`]`(`[`Some`]`(_))` and [`Err`]`(_)`.
     ///
-    /// [`None`]: #variant.None
-    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Some`]: #variant.Some
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    ///
     /// # Examples
     ///
     /// ```
@@ -1384,9 +1329,8 @@ impl<'a, T> From<&'a Option<T>> for Option<&'a T> {
     /// so this technique uses `as_ref` to first take an `Option` to a reference
     /// to the value inside the original.
     ///
-    /// [`map`]: ../../std/option/enum.Option.html#method.map
+    /// [`map`]: Option::map
     /// [`String`]: ../../std/string/struct.String.html
-    /// [`usize`]: ../../std/primitive.usize.html
     ///
     /// ```
     /// let s: Option<String> = Some(String::from("Hello, Rustaceans!"));
@@ -1465,10 +1409,6 @@ unsafe impl<A> TrustedLen for Item<A> {}
 /// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
 ///
 /// This `struct` is created by the [`Option::iter`] function.
-///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
-/// [`Option::iter`]: enum.Option.html#method.iter
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Iter<'a, A: 'a> {
@@ -1519,10 +1459,6 @@ fn clone(&self) -> Self {
 /// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
 ///
 /// This `struct` is created by the [`Option::iter_mut`] function.
-///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
-/// [`Option::iter_mut`]: enum.Option.html#method.iter_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct IterMut<'a, A: 'a> {
@@ -1565,8 +1501,6 @@ unsafe impl<A> TrustedLen for IterMut<'_, A> {}
 ///
 /// This `struct` is created by the [`Option::into_iter`] function.
 ///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
 /// [`Option::into_iter`]: enum.Option.html#method.into_iter
 #[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1671,8 +1605,6 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     ///
     /// Since the third element caused an underflow, no further elements were taken,
     /// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
-    ///
-    /// [`Iterator`]: ../iter/trait.Iterator.html
     #[inline]
     fn from_iter<I: IntoIterator<Item = Option<A>>>(iter: I) -> Option<V> {
         // FIXME(#11084): This could be replaced with Iterator::scan when this
index eac4741cd260ad483969d3dfdc70f9cb838f2c45..934f581f3faeb7575aa8f99726e22c69f51b50a2 100644 (file)
@@ -414,12 +414,13 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
-    // SAFETY: the caller must guarantee that the bytes `v`
-    // are valid UTF-8, thus the cast to `*const str` is safe.
-    // Also, the pointer dereference is safe because that pointer
-    // comes from a reference which is guaranteed to be valid for reads.
-    unsafe { &*(v as *const [u8] as *const str) }
+#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
+#[allow(unused_attributes)]
+#[allow_internal_unstable(const_fn_transmute)]
+pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
+    // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
+    // Also relies on `&str` and `&[u8]` having the same layout.
+    unsafe { mem::transmute(v) }
 }
 
 /// Converts a slice of bytes to a string slice without checking
@@ -2357,15 +2358,10 @@ pub fn is_char_boundary(&self, index: usize) -> bool {
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
     #[allow(unused_attributes)]
-    #[allow_internal_unstable(const_fn_union)]
+    #[allow_internal_unstable(const_fn_transmute)]
     pub const fn as_bytes(&self) -> &[u8] {
-        #[repr(C)]
-        union Slices<'a> {
-            str: &'a str,
-            slice: &'a [u8],
-        }
         // SAFETY: const sound because we transmute two types with the same layout
-        unsafe { Slices { str: self }.slice }
+        unsafe { mem::transmute(self) }
     }
 
     /// Converts a mutable string slice to a mutable byte slice.
index 4bc44e98fc802a7efee5106bac8409c3b0cfa9e7..5aba1a5d958d1dfe38f66230be09f0a5b3deec99 100644 (file)
@@ -290,3 +290,43 @@ fn empty_array_is_always_default() {
 
     let _arr = <[DoesNotImplDefault; 0]>::default();
 }
+
+#[test]
+fn array_map() {
+    let a = [1, 2, 3];
+    let b = a.map(|v| v + 1);
+    assert_eq!(b, [2, 3, 4]);
+
+    let a = [1u8, 2, 3];
+    let b = a.map(|v| v as u64);
+    assert_eq!(b, [1, 2, 3]);
+}
+
+// See note on above test for why `should_panic` is used.
+#[test]
+#[should_panic(expected = "test succeeded")]
+fn array_map_drop_safety() {
+    use core::sync::atomic::AtomicUsize;
+    use core::sync::atomic::Ordering;
+    static DROPPED: AtomicUsize = AtomicUsize::new(0);
+    struct DropCounter;
+    impl Drop for DropCounter {
+        fn drop(&mut self) {
+            DROPPED.fetch_add(1, Ordering::SeqCst);
+        }
+    }
+
+    let num_to_create = 5;
+    let success = std::panic::catch_unwind(|| {
+        let items = [0; 10];
+        let mut nth = 0;
+        items.map(|_| {
+            assert!(nth < num_to_create);
+            nth += 1;
+            DropCounter
+        });
+    });
+    assert!(success.is_err());
+    assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
+    panic!("test succeeded")
+}
index b4c299d390586d05665923f442e2043135078f8f..904e3f7284049b982ae68af411759276dc6eb3b4 100644 (file)
@@ -1,5 +1,6 @@
 #![feature(alloc_layout_extra)]
 #![feature(array_chunks)]
+#![feature(array_map)]
 #![feature(bool_to_option)]
 #![feature(bound_cloned)]
 #![feature(box_syntax)]
index fc07fa77b85e7660cebdd53a9e24d30cae5c5ff7..ef0ef415b4cbab4bbc00d7dbf5e8b86b00c627fd 100644 (file)
@@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.32" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
index 83073cc77dd1a12354ce6b9e535804e83f33e27e..04bfed12153ec42a3f3e69893fd2a2ffe80a3a0e 100644 (file)
@@ -16,6 +16,9 @@ fn main() {
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=execinfo");
         println!("cargo:rustc-link-lib=pthread");
+        if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() {
+            println!("cargo:rustc-cfg=freebsd12");
+        }
     } else if target.contains("netbsd") {
         println!("cargo:rustc-link-lib=pthread");
         println!("cargo:rustc-link-lib=rt");
index da25a0ede729d1fd3c66b1819fda6e91d17aa3bb..11b3f22503e83c6c6c8a474efb6519e94884ebd5 100644 (file)
@@ -1,3 +1,4 @@
+#![deny(unsafe_op_in_unsafe_fn)]
 use crate::ascii;
 use crate::borrow::{Borrow, Cow};
 use crate::cmp::Ordering;
 /// example, you can build a `CString` straight out of a [`String`] or
 /// a [`&str`], since both implement that trait).
 ///
-/// The [`new`] method will actually check that the provided `&[u8]`
+/// The [`CString::new`] method will actually check that the provided `&[u8]`
 /// does not have 0 bytes in the middle, and return an error if it
 /// finds one.
 ///
 /// # Extracting a raw pointer to the whole C string
 ///
-/// `CString` implements a [`as_ptr`] method through the [`Deref`]
+/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
 /// trait. This method will give you a `*const c_char` which you can
 /// feed directly to extern functions that expect a nul-terminated
-/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a
+/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
 /// read-only pointer; if the C code writes to it, that causes
 /// undefined behavior.
 ///
 /// # Extracting a slice of the whole C string
 ///
 /// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
-/// `CString` with the [`as_bytes`] method. Slices produced in this
+/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
 /// way do *not* contain the trailing nul terminator. This is useful
 /// when you will be calling an extern function that takes a `*const
 /// u8` argument which is not necessarily nul-terminated, plus another
@@ -60,7 +61,7 @@
 /// [`len`][slice.len] method.
 ///
 /// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
-/// can use [`as_bytes_with_nul`] instead.
+/// can use [`CString::as_bytes_with_nul`] instead.
 ///
 /// Once you have the kind of slice you need (with or without a nul
 /// terminator), you can call the slice's own
 /// extern functions. See the documentation for that function for a
 /// discussion on ensuring the lifetime of the raw pointer.
 ///
-/// [`Into`]: ../convert/trait.Into.html
-/// [`Vec`]: ../vec/struct.Vec.html
-/// [`String`]: ../string/struct.String.html
-/// [`&str`]: ../primitive.str.html
-/// [`u8`]: ../primitive.u8.html
-/// [`new`]: #method.new
-/// [`as_bytes`]: #method.as_bytes
-/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
-/// [`as_ptr`]: #method.as_ptr
+/// [`&str`]: str
 /// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
 /// [slice.len]: ../primitive.slice.html#method.len
-/// [`Deref`]: ../ops/trait.Deref.html
-/// [`CStr`]: struct.CStr.html
-/// [`&CStr`]: struct.CStr.html
+/// [`Deref`]: ops::Deref
+/// [`&CStr`]: CStr
 ///
 /// # Examples
 ///
 /// documentation of `CString` before use, as improper ownership management
 /// of `CString` instances can lead to invalid memory accesses, memory leaks,
 /// and other memory errors.
-
 #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct CString {
@@ -137,8 +128,8 @@ pub struct CString {
 ///
 /// Note that this structure is **not** `repr(C)` and is not recommended to be
 /// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
-/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
-/// interface to other consumers.
+/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
+/// a safe interface to other consumers.
 ///
 /// # Examples
 ///
@@ -189,11 +180,7 @@ pub struct CString {
 /// println!("string: {}", my_string_safe());
 /// ```
 ///
-/// [`u8`]: ../primitive.u8.html
-/// [`&str`]: ../primitive.str.html
-/// [`String`]: ../string/struct.String.html
-/// [`CString`]: struct.CString.html
-/// [`from_ptr`]: #method.from_ptr
+/// [`&str`]: str
 #[derive(Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
@@ -218,9 +205,6 @@ pub struct CStr {
 /// This error is created by the [`new`][`CString::new`] method on
 /// [`CString`]. See its documentation for more.
 ///
-/// [`CString`]: struct.CString.html
-/// [`CString::new`]: struct.CString.html#method.new
-///
 /// # Examples
 ///
 /// ```
@@ -237,12 +221,9 @@ pub struct CStr {
 /// The slice used to create a [`CStr`] must have one and only one nul byte,
 /// positioned at the end.
 ///
-/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
+/// This error is created by the [`CStr::from_bytes_with_nul`] method.
 /// See its documentation for more.
 ///
-/// [`CStr`]: struct.CStr.html
-/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
-///
 /// # Examples
 ///
 /// ```
@@ -261,12 +242,9 @@ pub struct FromBytesWithNulError {
 /// The vector used to create a [`CString`] must have one and only one nul byte,
 /// positioned at the end.
 ///
-/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
+/// This error is created by the [`CString::from_vec_with_nul`] method.
 /// See its documentation for more.
 ///
-/// [`CString`]: struct.CString.html
-/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
-///
 /// # Examples
 ///
 /// ```
@@ -316,8 +294,6 @@ impl FromVecWithNulError {
     ///
     /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
     /// ```
-    ///
-    /// [`CString`]: struct.CString.html
     pub fn as_bytes(&self) -> &[u8] {
         &self.bytes[..]
     }
@@ -343,8 +319,6 @@ pub fn as_bytes(&self) -> &[u8] {
     ///
     /// assert_eq!(bytes, value.unwrap_err().into_bytes());
     /// ```
-    ///
-    /// [`CString`]: struct.CString.html
     pub fn into_bytes(self) -> Vec<u8> {
         self.bytes
     }
@@ -352,17 +326,12 @@ pub fn into_bytes(self) -> Vec<u8> {
 
 /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
 ///
-/// `CString` is just a wrapper over a buffer of bytes with a nul
-/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
-/// validation on those bytes and may return this error.
+/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
+/// [`CString::into_string`] performs UTF-8 validation on those bytes and may
+/// return this error.
 ///
-/// This `struct` is created by the
-/// [`into_string`][`CString::into_string`] method on [`CString`]. See
+/// This `struct` is created by [`CString::into_string()`]. See
 /// its documentation for more.
-///
-/// [`String`]: ../string/struct.String.html
-/// [`CString`]: struct.CString.html
-/// [`CString::into_string`]: struct.CString.html#method.into_string
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstring_into", since = "1.7.0")]
 pub struct IntoStringError {
@@ -398,8 +367,6 @@ impl CString {
     /// This function will return an error if the supplied bytes contain an
     /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
     /// the position of the nul byte.
-    ///
-    /// [`NulError`]: struct.NulError.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
         trait SpecIntoVec {
@@ -439,11 +406,9 @@ fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
     /// Creates a C-compatible string by consuming a byte vector,
     /// without checking for interior 0 bytes.
     ///
-    /// This method is equivalent to [`new`] except that no runtime assertion
-    /// is made that `v` contains no 0 bytes, and it requires an actual
-    /// byte vector, not anything that can be converted to one with Into.
-    ///
-    /// [`new`]: #method.new
+    /// This method is equivalent to [`CString::new`] except that no runtime
+    /// assertion is made that `v` contains no 0 bytes, and it requires an
+    /// actual byte vector, not anything that can be converted to one with Into.
     ///
     /// # Examples
     ///
@@ -462,21 +427,22 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
         CString { inner: v.into_boxed_slice() }
     }
 
-    /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
+    /// Retakes ownership of a `CString` that was transferred to C via
+    /// [`CString::into_raw`].
     ///
     /// Additionally, the length of the string will be recalculated from the pointer.
     ///
     /// # Safety
     ///
     /// This should only ever be called with a pointer that was earlier
-    /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take
+    /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take
     /// ownership of a string that was allocated by foreign code) is likely to lead
     /// to undefined behavior or allocator corruption.
     ///
     /// It should be noted that the length isn't just "recomputed," but that
     /// the recomputed length must match the original length from the
-    /// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods
-    /// should not be used when passing the string to C functions that can
+    /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw`
+    /// methods should not be used when passing the string to C functions that can
     /// modify the string's length.
     ///
     /// > **Note:** If you need to borrow a string that was allocated by
@@ -485,9 +451,6 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
     /// > make your own provisions for freeing it appropriately, likely
     /// > with the foreign code's API to do that.
     ///
-    /// [`into_raw`]: #method.into_raw
-    /// [`CStr`]: struct.CStr.html
-    ///
     /// # Examples
     ///
     /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
@@ -510,26 +473,31 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
     /// ```
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
-        let len = sys::strlen(ptr) + 1; // Including the NUL byte
-        let slice = slice::from_raw_parts_mut(ptr, len as usize);
-        CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
+        // SAFETY: This is called with a pointer that was obtained from a call
+        // to `CString::into_raw` and the length has not been modified. As such,
+        // we know there is a NUL byte (and only one) at the end and that the
+        // information about the size of the allocation is correct on Rust's
+        // side.
+        unsafe {
+            let len = sys::strlen(ptr) + 1; // Including the NUL byte
+            let slice = slice::from_raw_parts_mut(ptr, len as usize);
+            CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
+        }
     }
 
     /// Consumes the `CString` and transfers ownership of the string to a C caller.
     ///
     /// The pointer which this function returns must be returned to Rust and reconstituted using
-    /// [`from_raw`] to be properly deallocated. Specifically, one
+    /// [`CString::from_raw`] to be properly deallocated. Specifically, one
     /// should *not* use the standard C `free()` function to deallocate
     /// this string.
     ///
-    /// Failure to call [`from_raw`] will lead to a memory leak.
+    /// Failure to call [`CString::from_raw`] will lead to a memory leak.
     ///
     /// The C side must **not** modify the length of the string (by writing a
     /// `NULL` somewhere inside the string or removing the final one) before
-    /// it makes it back into Rust using [`from_raw`]. See the safety section
-    /// in [`from_raw`].
-    ///
-    /// [`from_raw`]: #method.from_raw
+    /// it makes it back into Rust using [`CString::from_raw`]. See the safety section
+    /// in [`CString::from_raw`].
     ///
     /// # Examples
     ///
@@ -560,8 +528,6 @@ pub fn into_raw(self) -> *mut c_char {
     ///
     /// On failure, ownership of the original `CString` is returned.
     ///
-    /// [`String`]: ../string/struct.String.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -608,10 +574,8 @@ pub fn into_bytes(self) -> Vec<u8> {
         vec
     }
 
-    /// Equivalent to the [`into_bytes`] function except that the returned vector
-    /// includes the trailing nul terminator.
-    ///
-    /// [`into_bytes`]: #method.into_bytes
+    /// Equivalent to [`CString::into_bytes()`] except that the
+    /// returned vector includes the trailing nul terminator.
     ///
     /// # Examples
     ///
@@ -632,9 +596,7 @@ pub fn into_bytes_with_nul(self) -> Vec<u8> {
     /// The returned slice does **not** contain the trailing nul
     /// terminator, and it is guaranteed to not have any interior nul
     /// bytes. If you need the nul terminator, use
-    /// [`as_bytes_with_nul`] instead.
-    ///
-    /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
+    /// [`CString::as_bytes_with_nul`] instead.
     ///
     /// # Examples
     ///
@@ -651,10 +613,8 @@ pub fn as_bytes(&self) -> &[u8] {
         &self.inner[..self.inner.len() - 1]
     }
 
-    /// Equivalent to the [`as_bytes`] function except that the returned slice
-    /// includes the trailing nul terminator.
-    ///
-    /// [`as_bytes`]: #method.as_bytes
+    /// Equivalent to [`CString::as_bytes()`] except that the
+    /// returned slice includes the trailing nul terminator.
     ///
     /// # Examples
     ///
@@ -673,8 +633,6 @@ pub fn as_bytes_with_nul(&self) -> &[u8] {
 
     /// Extracts a [`CStr`] slice containing the entire string.
     ///
-    /// [`CStr`]: struct.CStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -693,8 +651,6 @@ pub fn as_c_str(&self) -> &CStr {
 
     /// Converts this `CString` into a boxed [`CStr`].
     ///
-    /// [`CStr`]: struct.CStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -711,8 +667,6 @@ pub fn into_boxed_c_str(self) -> Box<CStr> {
     }
 
     /// Bypass "move out of struct which implements [`Drop`] trait" restriction.
-    ///
-    /// [`Drop`]: ../ops/trait.Drop.html
     fn into_inner(self) -> Box<[u8]> {
         // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
         // so we use `ManuallyDrop` to ensure `self` is not dropped.
@@ -722,12 +676,12 @@ fn into_inner(self) -> Box<[u8]> {
         unsafe { ptr::read(&this.inner) }
     }
 
-    /// Converts a `Vec` of `u8` to a `CString` without checking the invariants
-    /// on the given `Vec`.
+    /// Converts a [`Vec`]`<u8>` to a [`CString`] without checking the
+    /// invariants on the given [`Vec`].
     ///
     /// # Safety
     ///
-    /// The given `Vec` **must** have one nul byte as its last element.
+    /// The given [`Vec`] **must** have one nul byte as its last element.
     /// This means it cannot be empty nor have any other nul byte anywhere else.
     ///
     /// # Example
@@ -745,10 +699,10 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
         Self { inner: v.into_boxed_slice() }
     }
 
-    /// Attempts to converts a `Vec` of `u8` to a `CString`.
+    /// Attempts to converts a [`Vec`]`<u8>` to a [`CString`].
     ///
     /// Runtime checks are present to ensure there is only one nul byte in the
-    /// `Vec`, its last element.
+    /// [`Vec`], its last element.
     ///
     /// # Errors
     ///
@@ -757,8 +711,8 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     ///
     /// # Examples
     ///
-    /// A successful conversion will produce the same result as [`new`] when
-    /// called without the ending nul byte.
+    /// A successful conversion will produce the same result as [`CString::new`]
+    /// when called without the ending nul byte.
     ///
     /// ```
     /// #![feature(cstring_from_vec_with_nul)]
@@ -770,7 +724,7 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     /// );
     /// ```
     ///
-    /// A incorrectly formatted vector will produce an error.
+    /// A incorrectly formatted [`Vec`] will produce an error.
     ///
     /// ```
     /// #![feature(cstring_from_vec_with_nul)]
@@ -780,8 +734,6 @@ pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
     /// // No nul byte
     /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
     /// ```
-    ///
-    /// [`new`]: #method.new
     #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
     pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
         let nul_pos = memchr::memchr(0, &v);
@@ -838,9 +790,6 @@ impl From<CString> for Vec<u8> {
     /// Converts a [`CString`] into a [`Vec`]`<u8>`.
     ///
     /// The conversion consumes the [`CString`], and removes the terminating NUL byte.
-    ///
-    /// [`Vec`]: ../vec/struct.Vec.html
-    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: CString) -> Vec<u8> {
         s.into_bytes()
@@ -913,9 +862,6 @@ fn from(cow: Cow<'_, CStr>) -> Box<CStr> {
 #[stable(feature = "c_string_from_box", since = "1.18.0")]
 impl From<Box<CStr>> for CString {
     /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
-    ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`CString`]: ../ffi/struct.CString.html
     #[inline]
     fn from(s: Box<CStr>) -> CString {
         s.into_c_string()
@@ -926,10 +872,6 @@ fn from(s: Box<CStr>) -> CString {
 impl From<Vec<NonZeroU8>> for CString {
     /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
     /// copying nor checking for inner null bytes.
-    ///
-    /// [`CString`]: ../ffi/struct.CString.html
-    /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
-    /// [`Vec`]: ../vec/struct.Vec.html
     #[inline]
     fn from(v: Vec<NonZeroU8>) -> CString {
         unsafe {
@@ -959,9 +901,6 @@ fn clone(&self) -> Self {
 #[stable(feature = "box_from_c_string", since = "1.20.0")]
 impl From<CString> for Box<CStr> {
     /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
-    ///
-    /// [`CString`]: ../ffi/struct.CString.html
-    /// [`Box`]: ../boxed/struct.Box.html
     #[inline]
     fn from(s: CString) -> Box<CStr> {
         s.into_boxed_c_str()
@@ -995,9 +934,6 @@ fn from(s: &'a CString) -> Cow<'a, CStr> {
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Arc<CStr> {
     /// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
-    ///
-    /// [`CString`]: ../ffi/struct.CString.html
-    /// [`Arc`]: ../sync/struct.Arc.html
     #[inline]
     fn from(s: CString) -> Arc<CStr> {
         let arc: Arc<[u8]> = Arc::from(s.into_inner());
@@ -1017,9 +953,6 @@ fn from(s: &CStr) -> Arc<CStr> {
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
     /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
-    ///
-    /// [`CString`]: ../ffi/struct.CString.html
-    /// [`Rc`]: ../rc/struct.Rc.html
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
@@ -1048,8 +981,6 @@ impl NulError {
     /// Returns the position of the nul byte in the slice that caused
     /// [`CString::new`] to fail.
     ///
-    /// [`CString::new`]: struct.CString.html#method.new
-    ///
     /// # Examples
     ///
     /// ```
@@ -1101,9 +1032,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<NulError> for io::Error {
     /// Converts a [`NulError`] into a [`io::Error`].
-    ///
-    /// [`NulError`]: ../ffi/struct.NulError.html
-    /// [`io::Error`]: ../io/struct.Error.html
     fn from(_: NulError) -> io::Error {
         io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
     }
@@ -1154,8 +1082,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl IntoStringError {
     /// Consumes this error, returning original [`CString`] which generated the
     /// error.
-    ///
-    /// [`CString`]: struct.CString.html
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_cstring(self) -> CString {
         self.inner
@@ -1228,9 +1154,21 @@ impl CStr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
-        let len = sys::strlen(ptr);
-        let ptr = ptr as *const u8;
-        CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+        // SAFETY: The caller has provided a pointer that points to a valid C
+        // string with a NUL terminator of size less than `isize::MAX`, whose
+        // content remain valid and doesn't change for the lifetime of the
+        // returned `CStr`.
+        //
+        // Thus computing the length is fine (a NUL byte exists), the call to
+        // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
+        // the call to `from_bytes_with_nul_unchecked` is correct.
+        //
+        // The cast from c_char to u8 is ok because a c_char is always one byte.
+        unsafe {
+            let len = sys::strlen(ptr);
+            let ptr = ptr as *const u8;
+            CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+        }
     }
 
     /// Creates a C string wrapper from a byte slice.
@@ -1299,7 +1237,12 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
     #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
-        &*(bytes as *const [u8] as *const CStr)
+        // SAFETY: Casting to CStr is safe because its internal representation
+        // is a [u8] too (safe only inside std).
+        // Dereferencing the obtained pointer is safe because it comes from a
+        // reference. Making a reference is then safe because its lifetime
+        // is bound by the lifetime of the given `bytes`.
+        unsafe { &*(bytes as *const [u8] as *const CStr) }
     }
 
     /// Returns the inner pointer to this C string.
@@ -1330,7 +1273,8 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     ///
     /// This happens because the pointer returned by `as_ptr` does not carry any
     /// lifetime information and the [`CString`] is deallocated immediately after
-    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
+    /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
+    /// expression is evaluated.
     /// To fix the problem, bind the `CString` to a local variable:
     ///
     /// ```no_run
@@ -1345,10 +1289,8 @@ pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError>
     /// }
     /// ```
     ///
-    /// This way, the lifetime of the `CString` in `hello` encompasses
+    /// This way, the lifetime of the [`CString`] in `hello` encompasses
     /// the lifetime of `ptr` and the `unsafe` block.
-    ///
-    /// [`CString`]: struct.CString.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
@@ -1382,15 +1324,13 @@ pub fn to_bytes(&self) -> &[u8] {
 
     /// Converts this C string to a byte slice containing the trailing 0 byte.
     ///
-    /// This function is the equivalent of [`to_bytes`] except that it will retain
-    /// the trailing nul terminator instead of chopping it off.
+    /// This function is the equivalent of [`CStr::to_bytes`] except that it
+    /// will retain the trailing nul terminator instead of chopping it off.
     ///
     /// > **Note**: This method is currently implemented as a 0-cost cast, but
     /// > it is planned to alter its definition in the future to perform the
     /// > length calculation whenever this method is called.
     ///
-    /// [`to_bytes`]: #method.to_bytes
-    ///
     /// # Examples
     ///
     /// ```
@@ -1411,7 +1351,7 @@ pub fn to_bytes_with_nul(&self) -> &[u8] {
     /// function will return the corresponding [`&str`] slice. Otherwise,
     /// it will return an error with details of where UTF-8 validation failed.
     ///
-    /// [`&str`]: ../primitive.str.html
+    /// [`&str`]: str
     ///
     /// # Examples
     ///
@@ -1439,12 +1379,9 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
     /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
     ///
-    /// [`Cow`]: ../borrow/enum.Cow.html
-    /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
-    /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
-    /// [`str`]: ../primitive.str.html
-    /// [`String`]: ../string/struct.String.html
-    /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
+    /// [`Borrowed`]: Cow::Borrowed
+    /// [`Owned`]: Cow::Owned
+    /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
     ///
     /// # Examples
     ///
@@ -1479,9 +1416,6 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
 
     /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
     ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`CString`]: struct.CString.html
-    ///
     /// # Examples
     ///
     /// ```
index f442d7fde1a5e9464fe0e6116e2dc204930cce39..0184495eecf09ffdf59ca11148b34f41f974acd1 100644 (file)
@@ -88,7 +88,7 @@
 //! [`env::var_os()`] is used to query environment variables; it
 //! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
 //! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
-//! convert to a Rust string. This yields a [`Result<>`], so that
+//! convert to a Rust string. This yields a [`Result`], so that
 //! your code can detect errors in case the environment variable did
 //! not in fact contain valid Unicode data.
 //!
 //! method is an [`OsString`] which can be round-tripped to a Windows
 //! string losslessly.
 //!
-//! [`String`]: ../string/struct.String.html
-//! [`str`]: ../primitive.str.html
-//! [`char`]: ../primitive.char.html
-//! [`u8`]: ../primitive.u8.html
-//! [`u16`]: ../primitive.u16.html
 //! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
 //! [Unicode code point]: http://www.unicode.org/glossary/#code_point
-//! [`CString`]: struct.CString.html
-//! [`CStr`]: struct.CStr.html
-//! [`OsString`]: struct.OsString.html
-//! [`OsStr`]: struct.OsStr.html
-//! [`env::set_var()`]: ../env/fn.set_var.html
-//! [`env::var_os()`]: ../env/fn.var_os.html
-//! [`Result<>`]: ../result/enum.Result.html
-//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
-//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
-//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
-//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
-//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
-//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
-//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
-//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
-//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
-//! [`collect`]: ../iter/trait.Iterator.html#method.collect
-//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
-//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
-//! [`Option`]: ../option/enum.Option.html
-//! [`Some`]: ../option/enum.Option.html#variant.Some
+//! [`env::set_var()`]: crate::env::set_var
+//! [`env::var_os()`]: crate::env::var_os
+//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt
+//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec
+//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec
+//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt
+//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes
+//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes
+//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt
+//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt
+//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide
+//! [`collect`]: crate::iter::Iterator::collect
+//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt
+//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index d1eaf3c583f2d4b5a0ced796d64aec3576eaf263..262d39d98ee2ecc66790141c9cb2b11fe3b96162 100644 (file)
 /// create an `OsString` from a normal Rust string.
 ///
 /// **From slices:** Just like you can start with an empty Rust
-/// [`String`] and then [`push_str`][String.push_str] `&str`
+/// [`String`] and then [`String::push_str`] `&str`
 /// sub-string slices into it, you can create an empty `OsString` with
-/// the [`new`] method and then push string slices into it with the
-/// [`push`] method.
+/// the [`OsString::new`] method and then push string slices into it with the
+/// [`OsString::push`] method.
 ///
 /// # Extracting a borrowed reference to the whole OS string
 ///
-/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
+/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from
 /// an `OsString`; this is effectively a borrowed reference to the
 /// whole string.
 ///
 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
 /// the traits which `OsString` implements for [conversions] from/to native representations.
 ///
-/// [`OsStr`]: struct.OsStr.html
-/// [`&OsStr`]: struct.OsStr.html
-/// [`CStr`]: struct.CStr.html
-/// [`From`]: ../convert/trait.From.html
-/// [`String`]: ../string/struct.String.html
-/// [`&str`]: ../primitive.str.html
-/// [`u8`]: ../primitive.u8.html
-/// [`u16`]: ../primitive.u16.html
-/// [String.push_str]: ../string/struct.String.html#method.push_str
-/// [`new`]: #method.new
-/// [`push`]: #method.push
-/// [`as_os_str`]: #method.as_os_str
+/// [`&OsStr`]: OsStr
+/// [`&str`]: str
+/// [`CStr`]: crate::ffi::CStr
 /// [conversions]: index.html#conversions
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -93,9 +84,7 @@ pub struct OsString {
 /// See the [module's toplevel documentation about conversions][conversions] for a discussion on
 /// the traits which `OsStr` implements for [conversions] from/to native representations.
 ///
-/// [`OsString`]: struct.OsString.html
-/// [`&str`]: ../primitive.str.html
-/// [`String`]: ../string/struct.String.html
+/// [`&str`]: str
 /// [conversions]: index.html#conversions
 #[stable(feature = "rust1", since = "1.0.0")]
 // FIXME:
@@ -125,8 +114,6 @@ pub fn new() -> OsString {
 
     /// Converts to an [`OsStr`] slice.
     ///
-    /// [`OsStr`]: struct.OsStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -145,8 +132,6 @@ pub fn as_os_str(&self) -> &OsStr {
     ///
     /// On failure, ownership of the original `OsString` is returned.
     ///
-    /// [`String`]: ../../std/string/struct.String.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -163,7 +148,7 @@ pub fn into_string(self) -> Result<String, OsString> {
 
     /// Extends the string with the given [`&OsStr`] slice.
     ///
-    /// [`&OsStr`]: struct.OsStr.html
+    /// [`&OsStr`]: OsStr
     ///
     /// # Examples
     ///
@@ -333,8 +318,6 @@ pub fn shrink_to(&mut self, min_capacity: usize) {
 
     /// Converts this `OsString` into a boxed [`OsStr`].
     ///
-    /// [`OsStr`]: struct.OsStr.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -356,8 +339,6 @@ impl From<String> for OsString {
     /// Converts a [`String`] into a [`OsString`].
     ///
     /// The conversion copies the data, and includes an allocation on the heap.
-    ///
-    /// [`OsString`]: ../../std/ffi/struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
@@ -544,7 +525,7 @@ fn from_inner_mut(inner: &mut Slice) -> &mut OsStr {
     ///
     /// This conversion may entail doing a check for UTF-8 validity.
     ///
-    /// [`&str`]: ../../std/primitive.str.html
+    /// [`&str`]: str
     ///
     /// # Examples
     ///
@@ -564,9 +545,7 @@ pub fn to_str(&self) -> Option<&str> {
     /// Any non-Unicode sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
-    /// [`Cow`]: ../../std/borrow/enum.Cow.html
-    /// [`str`]: ../../std/primitive.str.html
-    /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
+    /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
     ///
     /// # Examples
     ///
@@ -613,8 +592,6 @@ pub fn to_string_lossy(&self) -> Cow<'_, str> {
 
     /// Copies the slice into an owned [`OsString`].
     ///
-    /// [`OsString`]: struct.OsString.html
-    ///
     /// # Examples
     ///
     /// ```
@@ -662,9 +639,6 @@ pub fn is_empty(&self) -> bool {
     /// This number is simply useful for passing to other methods, like
     /// [`OsString::with_capacity`] to avoid reallocations.
     ///
-    /// [`OsString`]: struct.OsString.html
-    /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
-    ///
     /// # Examples
     ///
     /// ```
@@ -682,9 +656,6 @@ pub fn len(&self) -> usize {
     }
 
     /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
-    ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`OsString`]: struct.OsString.html
     #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
     pub fn into_os_string(self: Box<OsStr>) -> OsString {
         let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
@@ -706,9 +677,7 @@ fn bytes(&self) -> &[u8] {
     /// but non-ASCII letters are unchanged.
     ///
     /// To return a new lowercased value without modifying the existing one, use
-    /// [`to_ascii_lowercase`].
-    ///
-    /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+    /// [`OsStr::to_ascii_lowercase`].
     ///
     /// # Examples
     ///
@@ -733,9 +702,7 @@ pub fn make_ascii_lowercase(&mut self) {
     /// but non-ASCII letters are unchanged.
     ///
     /// To return a new uppercased value without modifying the existing one, use
-    /// [`to_ascii_uppercase`].
-    ///
-    /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+    /// [`OsStr::to_ascii_uppercase`].
     ///
     /// # Examples
     ///
@@ -760,9 +727,7 @@ pub fn make_ascii_uppercase(&mut self) {
     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
-    ///
-    /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+    /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
     ///
     /// # Examples
     ///
@@ -784,9 +749,7 @@ pub fn to_ascii_lowercase(&self) -> OsString {
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
-    ///
-    /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+    /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
     ///
     /// # Examples
     ///
@@ -865,9 +828,6 @@ fn from(cow: Cow<'_, OsStr>) -> Box<OsStr> {
 impl From<Box<OsStr>> for OsString {
     /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
     /// allocating.
-    ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`OsStr`]: ../ffi/struct.OsStr.html
     fn from(boxed: Box<OsStr>) -> OsString {
         boxed.into_os_string()
     }
@@ -876,9 +836,6 @@ fn from(boxed: Box<OsStr>) -> OsString {
 #[stable(feature = "box_from_os_string", since = "1.20.0")]
 impl From<OsString> for Box<OsStr> {
     /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
-    ///
-    /// [`Box`]: ../boxed/struct.Box.html
-    /// [`OsString`]: ../ffi/struct.OsString.html
     fn from(s: OsString) -> Box<OsStr> {
         s.into_boxed_os_str()
     }
@@ -895,9 +852,6 @@ fn clone(&self) -> Self {
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Arc<OsStr> {
     /// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
-    ///
-    /// [`Arc`]: ../sync/struct.Arc.html
-    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Arc<OsStr> {
         let arc = s.inner.into_arc();
@@ -917,9 +871,6 @@ fn from(s: &OsStr) -> Arc<OsStr> {
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
     /// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
-    ///
-    /// [`Rc`]: ../rc/struct.Rc.html
-    /// [`OsString`]: ../ffi/struct.OsString.html
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
index ff343625a19ed75932bf944f9e9cd57f394aa1e1..c39989a60c92b5c62d4615de8c46192064f45963 100644 (file)
@@ -1813,12 +1813,190 @@ mod type_keyword {}
 
 #[doc(keyword = "unsafe")]
 //
-/// Code or interfaces whose [memory safety] cannot be verified by the type system.
+/// Code or interfaces whose [memory safety] cannot be verified by the type
+/// system.
+///
+/// The `unsafe` keyword has two uses: to declare the existence of contracts the
+/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a
+/// programmer has checked that these contracts have been upheld (`unsafe {}`
+/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually
+/// exclusive, as can be seen in `unsafe fn`.
+///
+/// # Unsafe abilities
+///
+/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is
+/// referred to as [soundness]: a well-typed program actually has the desired
+/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation
+/// on the subject.
+///
+/// To ensure soundness, Safe Rust is restricted enough that it can be
+/// automatically checked. Sometimes, however, it is necessary to write code
+/// that is correct for reasons which are too clever for the compiler to
+/// understand. In those cases, you need to use Unsafe Rust.
+///
+/// Here are the abilities Unsafe Rust has in addition to Safe Rust:
+///
+/// - Dereference [raw pointers]
+/// - Implement `unsafe` [`trait`]s
+/// - Call `unsafe` functions
+/// - Mutate [`static`]s (including [`extern`]al ones)
+/// - Access fields of [`union`]s
+///
+/// However, this extra power comes with extra responsibilities: it is now up to
+/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the
+/// pieces of code that need to worry about this.
+///
+/// ## The different meanings of `unsafe`
+///
+/// Not all uses of `unsafe` are equivalent: some are here to mark the existence
+/// of a contract the programmer must check, others are to say "I have checked
+/// the contract, go ahead and do this". The following
+/// [discussion on Rust Internals] has more in-depth explanations about this but
+/// here is a summary of the main points:
+///
+/// - `unsafe fn`: calling this function means abiding by a contract the
+/// compiler cannot enforce.
+/// - `unsafe trait`: implementing the [`trait`] means abiding by a
+/// contract the compiler cannot enforce.
+/// - `unsafe {}`: the contract necessary to call the operations inside the
+/// block has been checked by the programmer and is guaranteed to be respected.
+/// - `unsafe impl`: the contract necessary to implement the trait has been
+/// checked by the programmer and is guaranteed to be respected.
+///
+/// `unsafe fn` also acts like an `unsafe {}` block
+/// around the code inside the function. This means it is not just a signal to
+/// the caller, but also promises that the preconditions for the operations
+/// inside the function are upheld. Mixing these two meanings can be confusing
+/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when
+/// making `unsafe` operations.
+///
+/// See the [Rustnomicon] and the [Reference] for more informations.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// # Examples
+///
+/// ## Marking elements as `unsafe`
+///
+/// `unsafe` can be used on functions. Note that functions and statics declared
+/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions
+/// declared as `extern "something" fn ...`). Mutable statics are always unsafe,
+/// wherever they are declared. Methods can also be declared as `unsafe`:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// static mut FOO: &str = "hello";
+///
+/// unsafe fn unsafe_fn() {}
+///
+/// extern "C" {
+///     fn unsafe_extern_fn();
+///     static BAR: *mut u32;
+/// }
+///
+/// trait SafeTraitWithUnsafeMethod {
+///     unsafe fn unsafe_method(&self);
+/// }
+///
+/// struct S;
+///
+/// impl S {
+///     unsafe fn unsafe_method_on_struct() {}
+/// }
+/// ```
+///
+/// Traits can also be declared as `unsafe`:
+///
+/// ```rust
+/// unsafe trait UnsafeTrait {}
+/// ```
 ///
+/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety
+/// contract that the compiler cannot enforce, documenting it is important. The
+/// standard library has many examples of this, like the following which is an
+/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract
+/// that must be fulfilled to safely call the function.
+///
+/// ```rust,ignore (stub-to-show-doc-example)
+/// /// Forces the length of the vector to `new_len`.
+/// ///
+/// /// This is a low-level operation that maintains none of the normal
+/// /// invariants of the type. Normally changing the length of a vector
+/// /// is done using one of the safe operations instead, such as
+/// /// `truncate`, `resize`, `extend`, or `clear`.
+/// ///
+/// /// # Safety
+/// ///
+/// /// - `new_len` must be less than or equal to `capacity()`.
+/// /// - The elements at `old_len..new_len` must be initialized.
+/// pub unsafe fn set_len(&mut self, new_len: usize)
+/// ```
+///
+/// ## Using `unsafe {}` blocks and `impl`s
+///
+/// Performing `unsafe` operations requires an `unsafe {}` block:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// /// Dereference the given pointer.
+/// ///
+/// /// # Safety
+/// ///
+/// /// `ptr` must be aligned and must not be dangling.
+/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 {
+///     *ptr
+/// }
+///
+/// let a = 3;
+/// let b = &a as *const _;
+/// // SAFETY: `a` has not been dropped and references are always aligned,
+/// // so `b` is a valid address.
+/// unsafe { assert_eq!(*b, deref_unchecked(b)); };
+/// ```
+///
+/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This
+/// makes a guarantee to other `unsafe` code that the implementation satisfies
+/// the trait's safety contract. The [Send] and [Sync] traits are examples of
+/// this behaviour in the standard library.
+///
+/// ```rust
+/// /// Implementors of this trait must guarantee an element is always
+/// /// accessible with index 3.
+/// unsafe trait ThreeIndexable<T> {
+///     /// Returns a reference to the element with index 3 in `&self`.
+///     fn three(&self) -> &T;
+/// }
+///
+/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe`
+/// // because the implementor must abide by a contract the compiler cannot
+/// // check but as a programmer we know there will always be a valid element
+/// // at index 3 to access.
+/// unsafe impl<T> ThreeIndexable<T> for [T; 4] {
+///     fn three(&self) -> &T {
+///         // SAFETY: implementing the trait means there always is an element
+///         // with index 3 accessible.
+///         unsafe { self.get_unchecked(3) }
+///     }
+/// }
+///
+/// let a = [1, 2, 4, 8];
+/// assert_eq!(a.three(), &8);
+/// ```
+///
+/// [`extern`]: keyword.extern.html
+/// [`trait`]: keyword.trait.html
+/// [`static`]: keyword.static.html
+/// [`union`]: keyword.union.html
+/// [`impl`]: keyword.impl.html
+/// [Send]: marker/trait.Send.html
+/// [Sync]: marker/trait.Sync.html
+/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len
+/// [raw pointers]: ../reference/types/pointer.html
 /// [memory safety]: ../book/ch19-01-unsafe-rust.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// [Rustnomicon]: ../nomicon/index.html
+/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
+/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
+/// [Reference]: ../reference/unsafety.html
+/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585
+/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696
 mod unsafe_keyword {}
 
 #[doc(keyword = "use")]
index 8c8d1aadf48e2076b8e685ce434daffb45883091..c11049fb98152e0696675f077293c4c3ed287867 100644 (file)
@@ -22,9 +22,7 @@
 /// The size of a `SocketAddr` instance may vary depending on the target operating
 /// system.
 ///
-/// [IP address]: ../../std/net/enum.IpAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+/// [IP address]: IpAddr
 ///
 /// # Examples
 ///
@@ -37,7 +35,7 @@
 /// assert_eq!(socket.port(), 8080);
 /// assert_eq!(socket.is_ipv4(), true);
 /// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum SocketAddr {
     /// An IPv4 socket address.
@@ -50,7 +48,7 @@ pub enum SocketAddr {
 
 /// An IPv4 socket address.
 ///
-/// IPv4 socket addresses consist of an [IPv4 address] and a 16-bit port number, as
+/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
 /// stated in [IETF RFC 793].
 ///
 /// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
@@ -59,8 +57,7 @@ pub enum SocketAddr {
 /// system.
 ///
 /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`IPv4` address]: Ipv4Addr
 ///
 /// # Examples
 ///
@@ -81,7 +78,7 @@ pub struct SocketAddrV4 {
 
 /// An IPv6 socket address.
 ///
-/// IPv6 socket addresses consist of an [Ipv6 address], a 16-bit port number, as well
+/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
 /// as fields containing the traffic class, the flow label, and a scope identifier
 /// (see [IETF RFC 2553, Section 3.3] for more details).
 ///
@@ -91,8 +88,7 @@ pub struct SocketAddrV4 {
 /// system.
 ///
 /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`IPv6` address]: Ipv6Addr
 ///
 /// # Examples
 ///
@@ -114,7 +110,7 @@ pub struct SocketAddrV6 {
 impl SocketAddr {
     /// Creates a new socket address from an [IP address] and a port number.
     ///
-    /// [IP address]: ../../std/net/enum.IpAddr.html
+    /// [IP address]: IpAddr
     ///
     /// # Examples
     ///
@@ -210,12 +206,12 @@ pub fn set_port(&mut self, new_port: u16) {
     }
 
     /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
-    /// [IPv4 address], and [`false`] otherwise.
+    /// [`IPv4` address], and [`false`] otherwise.
     ///
-    /// [`true`]: ../../std/primitive.bool.html
+    /// [IP address]: IpAddr
+    /// [`IPv4` address]: IpAddr::V4
     /// [`false`]: ../../std/primitive.bool.html
-    /// [IP address]: ../../std/net/enum.IpAddr.html
-    /// [IPv4 address]: ../../std/net/enum.IpAddr.html#variant.V4
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -232,12 +228,12 @@ pub fn is_ipv4(&self) -> bool {
     }
 
     /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
-    /// [IPv6 address], and [`false`] otherwise.
+    /// [`IPv6` address], and [`false`] otherwise.
     ///
-    /// [`true`]: ../../std/primitive.bool.html
+    /// [IP address]: IpAddr
+    /// [`IPv6` address]: IpAddr::V6
     /// [`false`]: ../../std/primitive.bool.html
-    /// [IP address]: ../../std/net/enum.IpAddr.html
-    /// [IPv6 address]: ../../std/net/enum.IpAddr.html#variant.V6
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -255,9 +251,9 @@ pub fn is_ipv6(&self) -> bool {
 }
 
 impl SocketAddrV4 {
-    /// Creates a new socket address from an [IPv4 address] and a port number.
+    /// Creates a new socket address from an [`IPv4` address] and a port number.
     ///
-    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+    /// [`IPv4` address]: Ipv4Addr
     ///
     /// # Examples
     ///
@@ -342,14 +338,14 @@ pub fn set_port(&mut self, new_port: u16) {
 }
 
 impl SocketAddrV6 {
-    /// Creates a new socket address from an [IPv6 address], a 16-bit port number,
+    /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
     /// and the `flowinfo` and `scope_id` fields.
     ///
     /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
     /// parameters, see [IETF RFC 2553, Section 3.3].
     ///
     /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+    /// [`IPv6` address]: Ipv6Addr
     ///
     /// # Examples
     ///
@@ -461,9 +457,7 @@ pub fn flowinfo(&self) -> u32 {
 
     /// Changes the flow information associated with this socket address.
     ///
-    /// See the [`flowinfo`] method's documentation for more details.
-    ///
-    /// [`flowinfo`]: #method.flowinfo
+    /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
     ///
     /// # Examples
     ///
@@ -501,9 +495,7 @@ pub fn scope_id(&self) -> u32 {
 
     /// Changes the scope ID associated with this socket address.
     ///
-    /// See the [`scope_id`] method's documentation for more details.
-    ///
-    /// [`scope_id`]: #method.scope_id
+    /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
     ///
     /// # Examples
     ///
@@ -535,9 +527,6 @@ fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV4> for SocketAddr {
     /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
-    ///
-    /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
     fn from(sock4: SocketAddrV4) -> SocketAddr {
         SocketAddr::V4(sock4)
     }
@@ -546,9 +535,6 @@ fn from(sock4: SocketAddrV4) -> SocketAddr {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV6> for SocketAddr {
     /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
-    ///
-    /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
-    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(sock6: SocketAddrV6) -> SocketAddr {
         SocketAddr::V6(sock6)
     }
@@ -562,13 +548,6 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
     /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
     ///
     /// `u16` is treated as port of the newly created [`SocketAddr`].
-    ///
-    /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
-    /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4
-    /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6
-    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
-    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(pieces: (I, u16)) -> SocketAddr {
         SocketAddr::new(pieces.0.into(), pieces.1)
     }
@@ -597,6 +576,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV4 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -778,18 +764,11 @@ fn hash<H: hash::Hasher>(&self, s: &mut H) {
 /// Addresses returned by the operating system that are not IP addresses are
 /// silently ignored.
 ///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
-/// [`&str`]: ../../std/primitive.str.html
-/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-/// [`to_socket_addrs`]: #tymethod.to_socket_addrs
-/// [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
-/// [`u16`]: ../../std/primitive.u16.html
+/// [`FromStr`]: crate::str::FromStr
+/// [`&str`]: str
+/// [`TcpStream`]: crate::net::TcpStream
+/// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs
+/// [`UdpSocket`]: crate::net::UdpSocket
 ///
 /// # Examples
 ///
@@ -860,7 +839,7 @@ fn hash<H: hash::Hasher>(&self, s: &mut H) {
 /// let stream = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), 443));
 /// ```
 ///
-/// [`TcpStream::connect`]: ../../std/net/struct.TcpStream.html#method.connect
+/// [`TcpStream::connect`]: crate::net::TcpStream::connect
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToSocketAddrs {
     /// Returned iterator over socket addresses which this type may correspond
index 2c0025bcba069ea16e370713977e3e6b059fdc57..de28268ea368212ee8593e01a7f087dc20b103c4 100644 (file)
@@ -22,9 +22,6 @@
 /// The size of an `IpAddr` instance may vary depending on the target operating
 /// system.
 ///
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-///
 /// # Examples
 ///
 /// ```
@@ -40,7 +37,7 @@
 /// assert_eq!(localhost_v4.is_ipv4(), true);
 /// ```
 #[stable(feature = "ip_addr", since = "1.7.0")]
-#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
 pub enum IpAddr {
     /// An IPv4 address.
     #[stable(feature = "ip_addr", since = "1.7.0")]
@@ -61,14 +58,13 @@ pub enum IpAddr {
 /// system.
 ///
 /// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
 ///
 /// # Textual representation
 ///
 /// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
 /// notation, divided by `.` (this is called "dot-decimal notation").
 ///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`FromStr`]: crate::str::FromStr
 ///
 /// # Examples
 ///
@@ -96,7 +92,6 @@ pub struct Ipv4Addr {
 /// system.
 ///
 /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
 ///
 /// # Textual representation
 ///
@@ -105,7 +100,7 @@ pub struct Ipv4Addr {
 /// notation, and segments are separated by `:`. For more information, see
 /// [IETF RFC 5952].
 ///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`FromStr`]: crate::str::FromStr
 /// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
 ///
 /// # Examples
@@ -138,11 +133,9 @@ pub enum Ipv6MulticastScope {
 impl IpAddr {
     /// Returns [`true`] for the special 'unspecified' address.
     ///
-    /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
-    /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
+    /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
+    /// [`Ipv6Addr::is_unspecified()`] for more details.
     ///
-    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
-    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -163,11 +156,9 @@ pub fn is_unspecified(&self) -> bool {
 
     /// Returns [`true`] if this is a loopback address.
     ///
-    /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
-    /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
+    /// See the documentation for [`Ipv4Addr::is_loopback()`] and
+    /// [`Ipv6Addr::is_loopback()`] for more details.
     ///
-    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
-    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -188,11 +179,9 @@ pub fn is_loopback(&self) -> bool {
 
     /// Returns [`true`] if the address appears to be globally routable.
     ///
-    /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
-    /// [`Ipv6Addr::is_global`][IPv6] for more details.
+    /// See the documentation for [`Ipv4Addr::is_global()`] and
+    /// [`Ipv6Addr::is_global()`] for more details.
     ///
-    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
-    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -214,11 +203,9 @@ pub fn is_global(&self) -> bool {
 
     /// Returns [`true`] if this is a multicast address.
     ///
-    /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
-    /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
+    /// See the documentation for [`Ipv4Addr::is_multicast()`] and
+    /// [`Ipv6Addr::is_multicast()`] for more details.
     ///
-    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
-    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -239,11 +226,9 @@ pub fn is_multicast(&self) -> bool {
 
     /// Returns [`true`] if this address is in a range designated for documentation.
     ///
-    /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
-    /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
+    /// See the documentation for [`Ipv4Addr::is_documentation()`] and
+    /// [`Ipv6Addr::is_documentation()`] for more details.
     ///
-    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
-    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -266,11 +251,12 @@ pub fn is_documentation(&self) -> bool {
         }
     }
 
-    /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
+    /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
+    /// otherwise.
     ///
     /// [`true`]: ../../std/primitive.bool.html
     /// [`false`]: ../../std/primitive.bool.html
-    /// [IPv4 address]: #variant.V4
+    /// [`IPv4` address]: IpAddr::V4
     ///
     /// # Examples
     ///
@@ -285,11 +271,12 @@ pub fn is_ipv4(&self) -> bool {
         matches!(self, IpAddr::V4(_))
     }
 
-    /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
+    /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
+    /// otherwise.
     ///
     /// [`true`]: ../../std/primitive.bool.html
     /// [`false`]: ../../std/primitive.bool.html
-    /// [IPv6 address]: #variant.V6
+    /// [`IPv6` address]: IpAddr::V6
     ///
     /// # Examples
     ///
@@ -385,8 +372,8 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// This property is defined in _UNIX Network Programming, Second Edition_,
     /// W. Richard Stevens, p. 891; see also [ip7].
     ///
-    /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
     /// [`true`]: ../../std/primitive.bool.html
+    /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
     ///
     /// # Examples
     ///
@@ -406,8 +393,8 @@ pub const fn is_unspecified(&self) -> bool {
     ///
     /// This property is defined by [IETF RFC 1122].
     ///
-    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
     ///
     /// # Examples
     ///
@@ -430,8 +417,8 @@ pub fn is_loopback(&self) -> bool {
     ///  - 172.16.0.0/12
     ///  - 192.168.0.0/16
     ///
-    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
     ///
     /// # Examples
     ///
@@ -460,8 +447,8 @@ pub fn is_private(&self) -> bool {
     ///
     /// This property is defined by [IETF RFC 3927].
     ///
-    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
     ///
     /// # Examples
     ///
@@ -483,24 +470,25 @@ pub fn is_link_local(&self) -> bool {
     /// Returns [`true`] if the address appears to be globally routable.
     /// See [iana-ipv4-special-registry][ipv4-sr].
     ///
-    /// The following return false:
+    /// The following return [`false`]:
     ///
-    /// - private addresses (see [`is_private()`](#method.is_private))
-    /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
-    /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
-    /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
-    /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
-    /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
+    /// - private addresses (see [`Ipv4Addr::is_private()`])
+    /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
+    /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
+    /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
+    /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
+    /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
     ///   0.0.0.0/8 block
     /// - addresses reserved for future protocols (see
-    /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
+    /// [`Ipv4Addr::is_ietf_protocol_assignment()`], except
     /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
-    /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
+    /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
     /// - addresses reserved for networking devices benchmarking (see
-    /// [`is_benchmarking`](#method.is_benchmarking))
+    /// [`Ipv4Addr::is_benchmarking()`])
     ///
-    /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     ///
     /// # Examples
     ///
@@ -572,8 +560,8 @@ pub fn is_global(&self) -> bool {
     /// Returns [`true`] if this address is part of the Shared Address Space defined in
     /// [IETF RFC 6598] (`100.64.0.0/10`).
     ///
-    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
     ///
     /// # Examples
     ///
@@ -598,11 +586,11 @@ pub fn is_shared(&self) -> bool {
     /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
     /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
     ///
+    /// [`true`]: ../../std/primitive.bool.html
     /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
     /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
     /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
     /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
-    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -625,9 +613,9 @@ pub fn is_ietf_protocol_assignment(&self) -> bool {
     /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
     /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
     ///
+    /// [`true`]: ../../std/primitive.bool.html
     /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
     /// [errata 423]: https://www.rfc-editor.org/errata/eid423
-    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -649,8 +637,8 @@ pub fn is_benchmarking(&self) -> bool {
     /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
     /// it is obviously not reserved for future use.
     ///
-    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
     ///
     /// # Warning
     ///
@@ -681,8 +669,8 @@ pub fn is_reserved(&self) -> bool {
     /// Multicast addresses have a most significant octet between 224 and 239,
     /// and is defined by [IETF RFC 5771].
     ///
-    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
     ///
     /// # Examples
     ///
@@ -702,8 +690,8 @@ pub fn is_multicast(&self) -> bool {
     ///
     /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
     ///
-    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
     ///
     /// # Examples
     ///
@@ -726,8 +714,8 @@ pub fn is_broadcast(&self) -> bool {
     /// - 198.51.100.0/24 (TEST-NET-2)
     /// - 203.0.113.0/24 (TEST-NET-3)
     ///
-    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
     ///
     /// # Examples
     ///
@@ -749,11 +737,11 @@ pub fn is_documentation(&self) -> bool {
         }
     }
 
-    /// Converts this address to an IPv4-compatible [IPv6 address].
+    /// Converts this address to an IPv4-compatible [`IPv6` address].
     ///
     /// a.b.c.d becomes ::a.b.c.d
     ///
-    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+    /// [`IPv6` address]: Ipv6Addr
     ///
     /// # Examples
     ///
@@ -771,11 +759,11 @@ pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
         Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
     }
 
-    /// Converts this address to an IPv4-mapped [IPv6 address].
+    /// Converts this address to an IPv4-mapped [`IPv6` address].
     ///
     /// a.b.c.d becomes ::ffff:a.b.c.d
     ///
-    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+    /// [`IPv6` address]: Ipv6Addr
     ///
     /// # Examples
     ///
@@ -802,6 +790,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Debug for IpAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<Ipv4Addr> for IpAddr {
     /// Copies this address to a new `IpAddr::V4`.
@@ -1121,8 +1116,8 @@ pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16)
     ///
     /// This property is defined in [IETF RFC 4291].
     ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     ///
     /// # Examples
     ///
@@ -1141,8 +1136,8 @@ pub fn is_unspecified(&self) -> bool {
     ///
     /// This property is defined in [IETF RFC 4291].
     ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     ///
     /// # Examples
     ///
@@ -1192,6 +1187,7 @@ pub fn is_global(&self) -> bool {
     /// This property is defined in [IETF RFC 4193].
     ///
     /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+    ///
     /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
@@ -1223,7 +1219,9 @@ pub fn is_unique_local(&self) -> bool {
     ///
     /// This method validates the format defined in the RFC and won't recognize the following
     /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
-    /// If you need a less strict validation use [`is_unicast_link_local()`] instead.
+    /// If you need a less strict validation use [`Ipv6Addr::is_unicast_link_local()`] instead.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -1252,13 +1250,11 @@ pub fn is_unique_local(&self) -> bool {
     /// - [IETF RFC 4291 section 2.5.6]
     /// - [RFC 4291 errata 4406] (which has been rejected but provides useful
     ///   insight)
-    /// - [`is_unicast_link_local()`]
+    /// - [`Ipv6Addr::is_unicast_link_local()`]
     ///
     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
-    /// [`true`]: ../../std/primitive.bool.html
     /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
-    /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
     pub fn is_unicast_link_local_strict(&self) -> bool {
         (self.segments()[0] & 0xffff) == 0xfe80
             && (self.segments()[1] & 0xffff) == 0
@@ -1280,9 +1276,11 @@ pub fn is_unicast_link_local_strict(&self) -> bool {
     /// ```
     ///
     /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
-    /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you
-    /// need a strict validation fully compliant with the RFC, use
-    /// [`is_unicast_link_local_strict()`].
+    /// unicast link-local addresses, whereas [`Ipv6Addr::is_unicast_link_local_strict()`] does not.
+    /// If you need a strict validation fully compliant with the RFC, use
+    /// [`Ipv6Addr::is_unicast_link_local_strict()`] instead.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -1313,9 +1311,7 @@ pub fn is_unicast_link_local_strict(&self) -> bool {
     ///   insight)
     ///
     /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
-    /// [`true`]: ../../std/primitive.bool.html
     /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
-    /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
     pub fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
@@ -1364,8 +1360,8 @@ pub fn is_unicast_site_local(&self) -> bool {
     ///
     /// This property is defined in [IETF RFC 3849].
     ///
-    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
     ///
     /// # Examples
     ///
@@ -1457,8 +1453,8 @@ pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
     ///
     /// This property is defined by [IETF RFC 4291].
     ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     /// [`true`]: ../../std/primitive.bool.html
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
     ///
     /// # Examples
     ///
@@ -1473,14 +1469,13 @@ pub fn is_multicast(&self) -> bool {
         (self.segments()[0] & 0xff00) == 0xff00
     }
 
-    /// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
+    /// Converts this address to an [`IPv4` address] if it's an "IPv4-mapped IPv6 address"
     /// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
     ///
     /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
     /// All addresses *not* starting with `::ffff` will return `None`.
     ///
-    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`IPv4` address]: Ipv4Addr
     /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
     ///
     /// # Examples
@@ -1504,13 +1499,12 @@ pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
         }
     }
 
-    /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
+    /// Converts this address to an [`IPv4` address]. Returns [`None`] if this address is
     /// neither IPv4-compatible or IPv4-mapped.
     ///
     /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
     ///
-    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    /// [`IPv4` address]: Ipv4Addr
     ///
     /// # Examples
     ///
index c87e0661dc9f6bc423b138e2838dd76d8db020b0..d4b1552fec5fff05780804082be7bafb5cc2b68d 100644 (file)
 //! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting
 //!   with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
 //! * Other types are return or parameter types for various methods in this module
-//!
-//! [`IpAddr`]: ../../std/net/enum.IpAddr.html
-//! [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-//! [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-//! [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-//! [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-//! [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
-//! [`TcpListener`]: ../../std/net/struct.TcpListener.html
-//! [`TcpStream`]: ../../std/net/struct.TcpStream.html
-//! [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-//! [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 mod test;
 mod udp;
 
-/// Possible values which can be passed to the [`shutdown`] method of
-/// [`TcpStream`].
-///
-/// [`shutdown`]: struct.TcpStream.html#method.shutdown
-/// [`TcpStream`]: struct.TcpStream.html
+/// Possible values which can be passed to the [`TcpStream::shutdown`] method.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Shutdown {
     /// The reading portion of the [`TcpStream`] should be shut down.
     ///
-    /// All currently blocked and future [reads] will return [`Ok(0)`].
+    /// All currently blocked and future [reads] will return [`Ok`]`(0)`.
     ///
-    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-    /// [reads]: ../../std/io/trait.Read.html
-    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [reads]: crate::io::Read
     #[stable(feature = "rust1", since = "1.0.0")]
     Read,
     /// The writing portion of the [`TcpStream`] should be shut down.
     ///
     /// All currently blocked and future [writes] will return an error.
     ///
-    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-    /// [writes]: ../../std/io/trait.Write.html
+    /// [writes]: crate::io::Write
     #[stable(feature = "rust1", since = "1.0.0")]
     Write,
     /// Both the reading and the writing portions of the [`TcpStream`] should be shut down.
     ///
     /// See [`Shutdown::Read`] and [`Shutdown::Write`] for more information.
-    ///
-    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-    /// [`Shutdown::Read`]: #variant.Read
-    /// [`Shutdown::Write`]: #variant.Write
     #[stable(feature = "rust1", since = "1.0.0")]
     Both,
 }
index 12d3baf633362b55369139d1ba86c9cf27ddc2cf..a425aca5a646debbdeadf98844601dafc3fb70d5 100644 (file)
@@ -302,14 +302,6 @@ fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
 /// // No problem, the `panic!` message has disappeared.
 /// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic");
 /// ```
-///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct AddrParseError(());
index 47b8532b7a6e6d1bdada556bbc32b8bc4f8f645b..a76c9c46c05d2d1068db981c9a7a7c91e1f1a342 100644 (file)
 ///
 /// The Transmission Control Protocol is specified in [IETF RFC 793].
 ///
-/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
-/// [`connect`]: #method.connect
+/// [`accept`]: TcpListener::accept
+/// [`connect`]: TcpStream::connect
 /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [reading]: ../../std/io/trait.Read.html
-/// [`shutdown`]: #method.shutdown
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
-/// [writing]: ../../std/io/trait.Write.html
+/// [reading]: Read
+/// [`shutdown`]: TcpStream::shutdown
+/// [writing]: Write
 ///
 /// # Examples
 ///
 ///
 /// The Transmission Control Protocol is specified in [IETF RFC 793].
 ///
-/// [`accept`]: #method.accept
-/// [`bind`]: #method.bind
+/// [`accept`]: TcpListener::accept
+/// [`bind`]: TcpListener::bind
 /// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [`Incoming`]: ../../std/net/struct.Incoming.html
-/// [`TcpListener::incoming`]: #method.incoming
 ///
 /// # Examples
 ///
 
 /// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
 ///
-/// This `struct` is created by the [`incoming`] method on [`TcpListener`].
+/// This `struct` is created by the [`TcpListener::incoming`] method.
 /// See its documentation for more.
 ///
-/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
-/// [`incoming`]: ../../std/net/struct.TcpListener.html#method.incoming
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [`accept`]: TcpListener::accept
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Incoming<'a> {
@@ -109,8 +104,6 @@ impl TcpStream {
     /// the addresses result in a successful connection, the error returned from
     /// the last connection attempt (the last address) is returned.
     ///
-    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-    ///
     /// # Examples
     ///
     /// Open a TCP connection to `127.0.0.1:8080`:
@@ -157,8 +150,6 @@ pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
     /// single system call. It instead calls `connect` in nonblocking mode and
     /// then uses an OS-specific mechanism to await the completion of the
     /// connection request.
-    ///
-    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
     #[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
         net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
@@ -204,8 +195,6 @@ pub fn local_addr(&self) -> io::Result<SocketAddr> {
     /// portions to return immediately with an appropriate value (see the
     /// documentation of [`Shutdown`]).
     ///
-    /// [`Shutdown`]: ../../std/net/enum.Shutdown.html
-    ///
     /// # Platform-specific behavior
     ///
     /// Calling this function multiple times may result in different behavior,
@@ -260,12 +249,9 @@ pub fn try_clone(&self) -> io::Result<TcpStream> {
     /// a result of setting this option. For example Unix typically returns an
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
-    /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
-    /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
-    /// [`Duration`]: ../../std/time/struct.Duration.html
+    /// [`read`]: Read::read
+    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+    /// [`TimedOut`]: io::ErrorKind::TimedOut
     ///
     /// # Examples
     ///
@@ -307,12 +293,9 @@ pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
     /// as a result of setting this option. For example Unix typically returns
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
-    /// [`Duration`]: ../../std/time/struct.Duration.html
-    /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
-    /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+    /// [`write`]: Write::write
+    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+    /// [`TimedOut`]: io::ErrorKind::TimedOut
     ///
     /// # Examples
     ///
@@ -350,8 +333,7 @@ pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
     ///
     /// Some platforms do not provide access to the current timeout.
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
+    /// [`read`]: Read::read
     ///
     /// # Examples
     ///
@@ -376,8 +358,7 @@ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
     ///
     /// Some platforms do not provide access to the current timeout.
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
+    /// [`write`]: Write::write
     ///
     /// # Examples
     ///
@@ -440,9 +421,7 @@ pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
 
     /// Gets the value of the `TCP_NODELAY` option on this socket.
     ///
-    /// For more information about this option, see [`set_nodelay`][link].
-    ///
-    /// [link]: #method.set_nodelay
+    /// For more information about this option, see [`TcpStream::set_nodelay`].
     ///
     /// # Examples
     ///
@@ -480,9 +459,7 @@ pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
 
     /// Gets the value of the `IP_TTL` option for this socket.
     ///
-    /// For more information about this option, see [`set_ttl`][link].
-    ///
-    /// [link]: #method.set_ttl
+    /// For more information about this option, see [`TcpStream::set_ttl`].
     ///
     /// # Examples
     ///
@@ -559,8 +536,6 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
     /// };
     /// println!("bytes: {:?}", buf);
     /// ```
-    ///
-    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
@@ -681,7 +656,7 @@ impl TcpListener {
     ///
     /// Binding with a port number of 0 will request that the OS assigns a port
     /// to this listener. The port allocated can be queried via the
-    /// [`local_addr`] method.
+    /// [`TcpListener::local_addr`] method.
     ///
     /// The address type can be any implementor of [`ToSocketAddrs`] trait. See
     /// its documentation for concrete examples.
@@ -691,9 +666,6 @@ impl TcpListener {
     /// none of the addresses succeed in creating a listener, the error returned
     /// from the last attempt (the last address) is returned.
     ///
-    /// [`local_addr`]: #method.local_addr
-    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-    ///
     /// # Examples
     ///
     /// Creates a TCP listener bound to `127.0.0.1:80`:
@@ -743,8 +715,6 @@ pub fn local_addr(&self) -> io::Result<SocketAddr> {
     /// object references. Both handles can be used to accept incoming
     /// connections and options set on one listener will affect the other.
     ///
-    /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -764,8 +734,6 @@ pub fn try_clone(&self) -> io::Result<TcpListener> {
     /// is established. When established, the corresponding [`TcpStream`] and the
     /// remote peer's address will be returned.
     ///
-    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -790,11 +758,7 @@ pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
     ///
     /// The returned iterator will never return [`None`] and will also not yield
     /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
-    /// calling [`accept`] in a loop.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-    /// [`accept`]: #method.accept
+    /// calling [`TcpListener::accept`] in a loop.
     ///
     /// # Examples
     ///
@@ -837,9 +801,7 @@ pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
 
     /// Gets the value of the `IP_TTL` option for this socket.
     ///
-    /// For more information about this option, see [`set_ttl`][link].
-    ///
-    /// [link]: #method.set_ttl
+    /// For more information about this option, see [`TcpListener::set_ttl`].
     ///
     /// # Examples
     ///
@@ -936,8 +898,6 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
     ///     }
     /// }
     /// ```
-    ///
-    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
index 0096b827ca456df7bd19801054c3e89fe31ed0a9..d730b2b87ac2595ed52870d3c3bbc114093d80fd 100644 (file)
 /// an unordered, unreliable protocol; refer to [`TcpListener`] and [`TcpStream`] for TCP
 /// primitives.
 ///
-/// [`bind`]: #method.bind
-/// [`connect`]: #method.connect
+/// [`bind`]: UdpSocket::bind
+/// [`connect`]: UdpSocket::connect
 /// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
-/// [`recv`]: #method.recv
-/// [received from]: #method.recv_from
-/// [`send`]: #method.send
-/// [sent to]: #method.send_to
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
-/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+/// [`recv`]: UdpSocket::recv
+/// [received from]: UdpSocket::recv_from
+/// [`send`]: UdpSocket::send
+/// [sent to]: UdpSocket::send_to
+/// [`TcpListener`]: crate::net::TcpListener
+/// [`TcpStream`]: crate::net::TcpStream
 ///
 /// # Examples
 ///
@@ -65,8 +65,6 @@ impl UdpSocket {
     /// of the addresses succeed in creating a socket, the error returned from
     /// the last attempt (the last address) is returned.
     ///
-    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-    ///
     /// # Examples
     ///
     /// Creates a UDP socket bound to `127.0.0.1:3400`:
@@ -160,8 +158,6 @@ pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
     ///
     /// See issue #34202 for more details.
     ///
-    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -193,7 +189,7 @@ pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize
     ///
     /// If the socket isn't connected, it will return a [`NotConnected`] error.
     ///
-    /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
+    /// [`NotConnected`]: io::ErrorKind::NotConnected
     ///
     /// ```no_run
     /// use std::net::UdpSocket;
@@ -254,12 +250,9 @@ pub fn try_clone(&self) -> io::Result<UdpSocket> {
     /// a result of setting this option. For example Unix typically returns an
     /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
-    /// [`Duration`]: ../../std/time/struct.Duration.html
-    /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
-    /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+    /// [`read`]: io::Read::read
+    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+    /// [`TimedOut`]: io::ErrorKind::TimedOut
     ///
     /// # Examples
     ///
@@ -300,12 +293,9 @@ pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
     /// as a result of setting this option. For example Unix typically returns
     /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
-    /// [`Duration`]: ../../std/time/struct.Duration.html
-    /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
-    /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+    /// [`write`]: io::Write::write
+    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+    /// [`TimedOut`]: io::ErrorKind::TimedOut
     ///
     /// # Examples
     ///
@@ -338,8 +328,7 @@ pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
     ///
     /// If the timeout is [`None`], then [`read`] calls will block indefinitely.
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
+    /// [`read`]: io::Read::read
     ///
     /// # Examples
     ///
@@ -359,8 +348,7 @@ pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
     ///
     /// If the timeout is [`None`], then [`write`] calls will block indefinitely.
     ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
+    /// [`write`]: io::Write::write
     ///
     /// # Examples
     ///
@@ -396,10 +384,7 @@ pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
 
     /// Gets the value of the `SO_BROADCAST` option for this socket.
     ///
-    /// For more information about this option, see
-    /// [`set_broadcast`][link].
-    ///
-    /// [link]: #method.set_broadcast
+    /// For more information about this option, see [`UdpSocket::set_broadcast`].
     ///
     /// # Examples
     ///
@@ -435,10 +420,7 @@ pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
 
     /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
     ///
-    /// For more information about this option, see
-    /// [`set_multicast_loop_v4`][link].
-    ///
-    /// [link]: #method.set_multicast_loop_v4
+    /// For more information about this option, see [`UdpSocket::set_multicast_loop_v4`].
     ///
     /// # Examples
     ///
@@ -477,10 +459,7 @@ pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
 
     /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
     ///
-    /// For more information about this option, see
-    /// [`set_multicast_ttl_v4`][link].
-    ///
-    /// [link]: #method.set_multicast_ttl_v4
+    /// For more information about this option, see [`UdpSocket::set_multicast_ttl_v4`].
     ///
     /// # Examples
     ///
@@ -516,10 +495,7 @@ pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
 
     /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
     ///
-    /// For more information about this option, see
-    /// [`set_multicast_loop_v6`][link].
-    ///
-    /// [link]: #method.set_multicast_loop_v6
+    /// For more information about this option, see [`UdpSocket::set_multicast_loop_v6`].
     ///
     /// # Examples
     ///
@@ -555,9 +531,7 @@ pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
 
     /// Gets the value of the `IP_TTL` option for this socket.
     ///
-    /// For more information about this option, see [`set_ttl`][link].
-    ///
-    /// [link]: #method.set_ttl
+    /// For more information about this option, see [`UdpSocket::set_ttl`].
     ///
     /// # Examples
     ///
@@ -597,10 +571,7 @@ pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Res
 
     /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
     ///
-    /// For more information about this option, see
-    /// [`join_multicast_v4`][link].
-    ///
-    /// [link]: #method.join_multicast_v4
+    /// For more information about this option, see [`UdpSocket::join_multicast_v4`].
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
         self.0.leave_multicast_v4(multiaddr, interface)
@@ -608,10 +579,7 @@ pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) ->
 
     /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
     ///
-    /// For more information about this option, see
-    /// [`join_multicast_v6`][link].
-    ///
-    /// [link]: #method.join_multicast_v6
+    /// For more information about this option, see [`UdpSocket::join_multicast_v6`].
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
         self.0.leave_multicast_v6(multiaddr, interface)
@@ -675,11 +643,9 @@ pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
 
     /// Sends data on the socket to the remote address to which it is connected.
     ///
-    /// The [`connect`] method will connect this socket to a remote address. This
+    /// [`UdpSocket::connect`] will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
     ///
-    /// [`connect`]: #method.connect
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -701,11 +667,9 @@ pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
     /// hold the message bytes. If a message is too long to fit in the supplied buffer,
     /// excess bytes may be discarded.
     ///
-    /// The [`connect`] method will connect this socket to a remote address. This
+    /// [`UdpSocket::connect`] will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
     ///
-    /// [`connect`]: #method.connect
-    ///
     /// # Examples
     ///
     /// ```no_run
@@ -738,11 +702,9 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
     /// Do not use this function to implement busy waiting, instead use `libc::poll` to
     /// synchronize IO events on one or more sockets.
     ///
-    /// The [`connect`] method will connect this socket to a remote address. This
+    /// [`UdpSocket::connect`] will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
     ///
-    /// [`connect`]: #method.connect
-    ///
     /// # Errors
     ///
     /// This method will fail if the socket is not connected. The `connect` method
@@ -779,8 +741,6 @@ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
     /// `FIONBIO`. On Windows calling this method corresponds to calling
     /// `ioctlsocket` `FIONBIO`.
     ///
-    /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
-    ///
     /// # Examples
     ///
     /// Creates a UDP socket bound to `127.0.0.1:7878` and read bytes in
index c6a00e179bd7fb736105294724c98d299159ed40..1eda8690d5d1b0584b4493d6b21a9110a901ad97 100644 (file)
@@ -74,7 +74,14 @@ pub trait MetadataExt {
 impl MetadataExt for Metadata {
     #[allow(deprecated)]
     fn as_raw_stat(&self) -> &raw::stat {
-        unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+        // The methods below use libc::stat, so they work fine when libc is built with FreeBSD 12 ABI.
+        // This method would just return nonsense.
+        #[cfg(freebsd12)]
+        panic!("as_raw_stat not supported with FreeBSD 12 ABI");
+        #[cfg(not(freebsd12))]
+        unsafe {
+            &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat)
+        }
     }
     fn st_dev(&self) -> u64 {
         self.as_inner().as_inner().st_dev as u64
@@ -136,6 +143,11 @@ fn st_gen(&self) -> u32 {
     fn st_flags(&self) -> u32 {
         self.as_inner().as_inner().st_flags as u32
     }
+    #[cfg(freebsd12)]
+    fn st_lspare(&self) -> u32 {
+        panic!("st_lspare not supported with FreeBSD 12 ABI");
+    }
+    #[cfg(not(freebsd12))]
     fn st_lspare(&self) -> u32 {
         self.as_inner().as_inner().st_lspare as u32
     }
index 9a55767d965a658108062d721b39718978d4c5f3..8256b725acfa399877768d57c53b9b6c35915d4b 100644 (file)
@@ -5,7 +5,5 @@ Equivalent to C's `char` type.
 C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
 
 [C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
-[Rust's `char` type]: ../../primitive.char.html
-[`CStr`]: ../../ffi/struct.CStr.html
-[`i8`]: ../../primitive.i8.html
-[`u8`]: ../../primitive.u8.html
+[Rust's `char` type]: char
+[`CStr`]: crate::ffi::CStr
index 6818dada317938d121b63059341104f46ccd372d..57f4534829ec834a1b69ae377b393adc3dfd0519 100644 (file)
@@ -3,5 +3,4 @@ Equivalent to C's `double` type.
 This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
 
 [IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
-[`float`]: type.c_float.html
-[`f64`]: ../../primitive.f64.html
+[`float`]: c_float
index 57d1071d0da1787522b57a635df16ffa35fbe139..61e2abc05189df2e12d7fa1b77894868f3e2d269 100644 (file)
@@ -3,4 +3,3 @@ Equivalent to C's `float` type.
 This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all.
 
 [IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754
-[`f32`]: ../../primitive.f32.html
index a0d25fd21d89f490347f7366ec53b330969534ab..8062ff2307a9537ccf9007c982aa5e0eda09135e 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `signed int` (`int`) type.
 
 This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example.
 
-[`short`]: type.c_short.html
-[`i32`]: ../../primitive.i32.html
-[`i16`]: ../../primitive.i16.html
+[`short`]: c_short
index c620b402819fddfe2cf31863bebb3bdf28ceff1d..cc160783f78b7d5b429f92ac9e8750531ce64063 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `signed long` (`long`) type.
 
 This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`.
 
-[`int`]: type.c_int.html
-[`i32`]: ../../primitive.i32.html
-[`i64`]: ../../primitive.i64.html
+[`int`]: c_int
index ab3d6436568dfc20484d1ea935b1e2fbee2519e9..49c61bd61f4ad71c2c569289b978b182f125c85c 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `signed long long` (`long long`) type.
 
 This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type.
 
-[`long`]: type.c_int.html
-[`i64`]: ../../primitive.i64.html
-[`i128`]: ../../primitive.i128.html
+[`long`]: c_int
index 6aa8b1211d808d82b003cec6194fb8675ab58de6..69879c9f17f4d80af70250424ed18558942cdc5c 100644 (file)
@@ -2,5 +2,4 @@ Equivalent to C's `signed char` type.
 
 This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`].
 
-[`char`]: type.c_char.html
-[`i8`]: ../../primitive.i8.html
+[`char`]: c_char
index be92c6c106d598534a0f8bed771656a2f5aae5ce..3d1e53d1325f31a12fee0825a30a8e89a2c0c857 100644 (file)
@@ -2,5 +2,4 @@ Equivalent to C's `signed short` (`short`) type.
 
 This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example.
 
-[`char`]: type.c_char.html
-[`i16`]: ../../primitive.i16.html
+[`char`]: c_char
index b6ca711f869347a2b1ab44f8542c946eaf72db63..b633bb7f8dacf5bf2ca300d0ab0a793acbbc3a49 100644 (file)
@@ -2,5 +2,4 @@ Equivalent to C's `unsigned char` type.
 
 This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`].
 
-[`char`]: type.c_char.html
-[`u8`]: ../../primitive.u8.html
+[`char`]: c_char
index 6f7013a8ac18dfe20db854a2104d6960eb853c3c..f3abea35937abd712a916313955b86932570fb00 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `unsigned int` type.
 
 This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example.
 
-[`int`]: type.c_int.html
-[`u32`]: ../../primitive.u32.html
-[`u16`]: ../../primitive.u16.html
+[`int`]: c_int
index c350395080e80f429aa1ec71b42235ef9be87b64..4ab304e65777326eeef30e4e950e0296bb38881b 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `unsigned long` type.
 
 This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`.
 
-[`long`]: type.c_long.html
-[`u32`]: ../../primitive.u32.html
-[`u64`]: ../../primitive.u64.html
+[`long`]: c_long
index c41faf74c5c68243f1d84f220e021b3d231008e5..a27d70e17537d440fcddae685df71b4e1d6a9fd8 100644 (file)
@@ -2,6 +2,4 @@ Equivalent to C's `unsigned long long` type.
 
 This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type.
 
-[`long long`]: type.c_longlong.html
-[`u64`]: ../../primitive.u64.html
-[`u128`]: ../../primitive.u128.html
+[`long long`]: c_longlong
index d364abb3c8e0c501237e0b5363ee1482653c8992..6928e51b352c82d2a5aa413f20c402f4ff28dca4 100644 (file)
@@ -2,5 +2,4 @@ Equivalent to C's `unsigned short` type.
 
 This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`].
 
-[`short`]: type.c_short.html
-[`u16`]: ../../primitive.u16.html
+[`short`]: c_short
index e3d529df7de1643732b64071a1fd5bf527d4ffde..afdbdbeac3e54a12e2c5ef85c36c67c258cd31b1 100644 (file)
@@ -2057,9 +2057,14 @@ fn _starts_with(&self, base: &Path) -> bool {
     /// ```
     /// use std::path::Path;
     ///
-    /// let path = Path::new("/etc/passwd");
+    /// let path = Path::new("/etc/resolv.conf");
+    ///
+    /// assert!(path.ends_with("resolv.conf"));
+    /// assert!(path.ends_with("etc/resolv.conf"));
+    /// assert!(path.ends_with("/etc/resolv.conf"));
     ///
-    /// assert!(path.ends_with("passwd"));
+    /// assert!(!path.ends_with("/resolv.conf"));
+    /// assert!(!path.ends_with("conf")); // use .extension() instead
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
index 0d2aca6bbc3eb78505d8fe6ecb17568566a1c8b8..bca1732b84d95677af4fbb4742c3b7d11beea5ab 100644 (file)
@@ -1058,6 +1058,8 @@ mod prim_ref {}
 /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
 /// pointers, make your type `Option<fn()>` with your required signature.
 ///
+/// ### Safety
+///
 /// Plain function pointers are obtained by casting either plain functions, or closures that don't
 /// capture an environment:
 ///
@@ -1095,23 +1097,60 @@ mod prim_ref {}
 /// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
 /// ```
 ///
-/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
-/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
-/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
-/// fn()`, and so on for the various ABIs that Rust supports. Non-`extern` functions have an ABI
-/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
-/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
+/// ### ABI
+///
+/// On top of that, function pointers can vary based on what ABI they use. This
+/// is achieved by adding the `extern` keyword before the type, followed by the
+/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
+/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
+/// type `extern "C" fn()`.
+///
+/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
+/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
+/// ABI.
+///
+/// For more information and a list of supported ABIs, see [the nomicon's
+/// section on foreign calling conventions][nomicon-abi].
 ///
-/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+/// ### Variadic functions
 ///
 /// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
-/// to be called with a variable number of arguments. Normal rust functions, even those with an
+/// to be called with a variable number of arguments. Normal Rust functions, even those with an
 /// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
 /// variadic functions][nomicon-variadic].
 ///
 /// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
 ///
-/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
+/// ### Creating function pointers
+///
+/// When `bar` is the name of a function, then the expression `bar` is *not* a
+/// function pointer. Rather, it denotes a value of an unnameable type that
+/// uniquely identifies the function `bar`. The value is zero-sized because the
+/// type already identifies the function. This has the advantage that "calling"
+/// the value (it implements the `Fn*` traits) does not require dynamic
+/// dispatch.
+///
+/// This zero-sized type *coerces* to a regular function pointer. For example:
+///
+/// ```rust
+/// use std::mem;
+///
+/// fn bar(x: i32) {}
+///
+/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
+/// assert_eq!(mem::size_of_val(&not_bar_ptr), 0);
+///
+/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
+/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
+///
+/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
+/// ```
+///
+/// The last line shows that `&bar` is not a function pointer either. Rather, it
+/// is a reference to the function-specific ZST. `&bar` is basically never what you
+/// want when `bar` is a function.
+///
+/// ### Traits
 ///
 /// Function pointers implement the following traits:
 ///
index 4ba1940fd0ece193521b01b3a57b13c7405c9f17..6d94fa9ebfe6d7316dd5149e7c0068a249f42ab7 100644 (file)
 //! assert_eq!(b"test", output.stdout.as_slice());
 //! ```
 //!
-//! [`abort`]: fn.abort.html
-//! [`exit`]: fn.exit.html
+//! [`spawn`]: Command::spawn
+//! [`output`]: Command::output
 //!
-//! [`Command`]: struct.Command.html
-//! [`spawn`]: struct.Command.html#method.spawn
-//! [`output`]: struct.Command.html#method.output
+//! [`stdout`]: Command::stdout
+//! [`stdin`]: Command::stdin
+//! [`stderr`]: Command::stderr
 //!
-//! [`Child`]: struct.Child.html
-//! [`ChildStdin`]: struct.ChildStdin.html
-//! [`ChildStdout`]: struct.ChildStdout.html
-//! [`ChildStderr`]: struct.ChildStderr.html
-//! [`Stdio`]: struct.Stdio.html
-//!
-//! [`stdout`]: struct.Command.html#method.stdout
-//! [`stdin`]: struct.Command.html#method.stdin
-//! [`stderr`]: struct.Command.html#method.stderr
-//!
-//! [`Write`]: ../io/trait.Write.html
-//! [`Read`]: ../io/trait.Read.html
+//! [`Write`]: io::Write
+//! [`Read`]: io::Read
 
 #![stable(feature = "process", since = "1.0.0")]
 
 /// run, even after the `Child` handle to the child process has gone out of
 /// scope.
 ///
-/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make
+/// Calling [`wait`] (or other functions that wrap around it) will make
 /// the parent process wait until the child has actually exited before
 /// continuing.
 ///
 /// assert!(ecode.success());
 /// ```
 ///
-/// [`Command`]: struct.Command.html
-/// [`Drop`]: ../../core/ops/trait.Drop.html
-/// [`wait`]: #method.wait
+/// [`wait`]: Child::wait
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Child {
     handle: imp::Process,
 
     /// The handle for writing to the child's standard input (stdin), if it has
-    /// been captured.
+    /// been captured. To avoid partially moving
+    /// the `child` and thus blocking yourself from calling
+    /// functions on `child` while using `stdin`,
+    /// you might find it helpful:
+    ///
+    /// ```compile_fail,E0425
+    /// let stdin = child.stdin.take().unwrap();
+    /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub stdin: Option<ChildStdin>,
 
     /// The handle for reading from the child's standard output (stdout), if it
-    /// has been captured.
+    /// has been captured. You might find it helpful to do
+    ///
+    /// ```compile_fail,E0425
+    /// let stdout = child.stdout.take().unwrap();
+    /// ```
+    ///
+    /// to avoid partially moving the `child` and thus blocking yourself from calling
+    /// functions on `child` while using `stdout`.
     #[stable(feature = "process", since = "1.0.0")]
     pub stdout: Option<ChildStdout>,
 
     /// The handle for reading from the child's standard error (stderr), if it
-    /// has been captured.
+    /// has been captured. You might find it helpful to do
+    ///
+    /// ```compile_fail,E0425
+    /// let stderr = child.stderr.take().unwrap();
+    /// ```
+    ///
+    /// to avoid partially moving the `child` and thus blocking yourself from calling
+    /// functions on `child` while using `stderr`.
     #[stable(feature = "process", since = "1.0.0")]
     pub stderr: Option<ChildStderr>,
 }
@@ -227,9 +236,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// file handle will be closed. If the child process was blocked on input prior
 /// to being dropped, it will become unblocked after dropping.
 ///
-/// [`Child`]: struct.Child.html
-/// [`stdin`]: struct.Child.html#structfield.stdin
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stdin`]: Child::stdin
+/// [dropped]: Drop
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdin {
     inner: AnonPipe,
@@ -286,9 +294,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
 /// underlying file handle will be closed.
 ///
-/// [`Child`]: struct.Child.html
-/// [`stdout`]: struct.Child.html#structfield.stdout
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stdout`]: Child::stdout
+/// [dropped]: Drop
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdout {
     inner: AnonPipe,
@@ -347,9 +354,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
 /// underlying file handle will be closed.
 ///
-/// [`Child`]: struct.Child.html
-/// [`stderr`]: struct.Child.html#structfield.stderr
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stderr`]: Child::stderr
+/// [dropped]: Drop
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStderr {
     inner: AnonPipe,
@@ -522,7 +528,7 @@ pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
     ///
     /// To pass multiple arguments see [`args`].
     ///
-    /// [`args`]: #method.args
+    /// [`args`]: Command::args
     ///
     /// # Examples
     ///
@@ -547,7 +553,7 @@ pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
     ///
     /// To pass a single argument see [`arg`].
     ///
-    /// [`arg`]: #method.arg
+    /// [`arg`]: Command::arg
     ///
     /// # Examples
     ///
@@ -700,7 +706,7 @@ pub fn env_clear(&mut self) -> &mut Command {
     ///         .expect("ls command failed to start");
     /// ```
     ///
-    /// [`canonicalize`]: ../fs/fn.canonicalize.html
+    /// [`canonicalize`]: crate::fs::canonicalize
     #[stable(feature = "process", since = "1.0.0")]
     pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
         self.inner.cwd(dir.as_ref().as_ref());
@@ -712,8 +718,8 @@ pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
     /// defaults to [`piped`] when used with `output`.
     ///
-    /// [`inherit`]: struct.Stdio.html#method.inherit
-    /// [`piped`]: struct.Stdio.html#method.piped
+    /// [`inherit`]: Stdio::inherit
+    /// [`piped`]: Stdio::piped
     ///
     /// # Examples
     ///
@@ -738,8 +744,8 @@ pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
     /// defaults to [`piped`] when used with `output`.
     ///
-    /// [`inherit`]: struct.Stdio.html#method.inherit
-    /// [`piped`]: struct.Stdio.html#method.piped
+    /// [`inherit`]: Stdio::inherit
+    /// [`piped`]: Stdio::piped
     ///
     /// # Examples
     ///
@@ -764,8 +770,8 @@ pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
     /// defaults to [`piped`] when used with `output`.
     ///
-    /// [`inherit`]: struct.Stdio.html#method.inherit
-    /// [`piped`]: struct.Stdio.html#method.piped
+    /// [`inherit`]: Stdio::inherit
+    /// [`piped`]: Stdio::piped
     ///
     /// # Examples
     ///
@@ -893,10 +899,8 @@ fn as_inner_mut(&mut self) -> &mut imp::Command {
 /// [`Command`], or the [`wait_with_output`] method of a [`Child`]
 /// process.
 ///
-/// [`Command`]: struct.Command.html
-/// [`Child`]: struct.Child.html
-/// [`output`]: struct.Command.html#method.output
-/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
+/// [`output`]: Command::output
+/// [`wait_with_output`]: Child::wait_with_output
 #[derive(PartialEq, Eq, Clone)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Output {
@@ -939,10 +943,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// Describes what to do with a standard I/O stream for a child process when
 /// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
 ///
-/// [`stdin`]: struct.Command.html#method.stdin
-/// [`stdout`]: struct.Command.html#method.stdout
-/// [`stderr`]: struct.Command.html#method.stderr
-/// [`Command`]: struct.Command.html
+/// [`stdin`]: Command::stdin
+/// [`stdout`]: Command::stdout
+/// [`stderr`]: Command::stderr
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Stdio(imp::Stdio);
 
@@ -1206,10 +1209,8 @@ fn from(file: fs::File) -> Stdio {
 /// status is exposed through the [`status`] method, or the [`wait`] method
 /// of a [`Child`] process.
 ///
-/// [`Command`]: struct.Command.html
-/// [`Child`]: struct.Child.html
-/// [`status`]: struct.Command.html#method.status
-/// [`wait`]: struct.Child.html#method.wait
+/// [`status`]: Command::status
+/// [`wait`]: Child::wait
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ExitStatus(imp::ExitStatus);
@@ -1294,8 +1295,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// For the platform's canonical successful and unsuccessful codes, see
 /// the [`SUCCESS`] and [`FAILURE`] associated items.
 ///
-/// [`SUCCESS`]: #associatedconstant.SUCCESS
-/// [`FAILURE`]: #associatedconstant.FAILURE
+/// [`SUCCESS`]: ExitCode::SUCCESS
+/// [`FAILURE`]: ExitCode::FAILURE
 ///
 /// **Warning**: While various forms of this were discussed in [RFC #1937],
 /// it was ultimately cut from that RFC, and thus this type is more subject
@@ -1349,9 +1350,9 @@ impl Child {
     /// }
     /// ```
     ///
-    /// [`ErrorKind`]: ../io/enum.ErrorKind.html
-    /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
-    /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
+    /// [`ErrorKind`]: io::ErrorKind
+    /// [`InvalidInput`]: io::ErrorKind::InvalidInput
+    /// [`Other`]: io::ErrorKind::Other
     #[stable(feature = "process", since = "1.0.0")]
     pub fn kill(&mut self) -> io::Result<()> {
         self.handle.kill()
@@ -1616,8 +1617,7 @@ pub fn exit(code: i32) -> ! {
 /// }
 /// ```
 ///
-/// [`panic!`]: ../../std/macro.panic.html
-/// [panic hook]: ../../std/panic/fn.set_hook.html
+/// [panic hook]: crate::panic::set_hook
 #[stable(feature = "process_abort", since = "1.17.0")]
 pub fn abort() -> ! {
     crate::sys::abort_internal();
index 6707f790cab0aa6c2a058d441ac827bc6afc7f76..f2a9cb5a0e8795a4126aed38ebc0224b723b8cd9 100644 (file)
@@ -20,17 +20,29 @@ const fn zero() -> Timespec {
 
     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
         if self >= other {
-            Ok(if self.t.tv_nsec >= other.t.tv_nsec {
-                Duration::new(
-                    (self.t.tv_sec - other.t.tv_sec) as u64,
-                    (self.t.tv_nsec - other.t.tv_nsec) as u32,
-                )
+            // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
+            // to optimize it into a branchless form (see also #75545):
+            //
+            // 1. `self.t.tv_sec - other.t.tv_sec` shows up as a common expression
+            //    in both branches, i.e. the `else` must have its `- 1`
+            //    subtraction after the common one, not interleaved with it
+            //    (it used to be `self.t.tv_sec - 1 - other.t.tv_sec`)
+            //
+            // 2. the `Duration::new` call (or any other additional complexity)
+            //    is outside of the `if`-`else`, not duplicated in both branches
+            //
+            // Ideally this code could be rearranged such that it more
+            // directly expresses the lower-cost behavior we want from it.
+            let (secs, nsec) = if self.t.tv_nsec >= other.t.tv_nsec {
+                ((self.t.tv_sec - other.t.tv_sec) as u64, (self.t.tv_nsec - other.t.tv_nsec) as u32)
             } else {
-                Duration::new(
-                    (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+                (
+                    (self.t.tv_sec - other.t.tv_sec - 1) as u64,
                     self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
                 )
-            })
+            };
+
+            Ok(Duration::new(secs, nsec))
         } else {
             match other.sub_timespec(self) {
                 Ok(d) => Err(d),
index b479fbaf34613a422121d674b1f88e522c3395ae..4ff86daf0dd73878ac57ad908b3a542ac961ee9c 100644 (file)
@@ -7,9 +7,7 @@
 use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner};
 
-/// Unix-specific extensions to [`File`].
-///
-/// [`File`]: ../../../../std/fs/struct.File.html
+/// Unix-specific extensions to [`fs::File`].
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Reads a number of bytes starting from a given offset.
@@ -24,7 +22,7 @@ pub trait FileExt {
     /// Note that similar to [`File::read`], it is not an error to return with a
     /// short read.
     ///
-    /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
+    /// [`File::read`]: fs::File::read
     ///
     /// # Examples
     ///
@@ -55,8 +53,8 @@ pub trait FileExt {
     ///
     /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
     ///
-    /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
-    /// [`read_at`]: #tymethod.read_at
+    /// [`Read::read_exact`]: io::Read::read_exact
+    /// [`read_at`]: FileExt::read_at
     ///
     /// # Errors
     ///
@@ -75,8 +73,8 @@ pub trait FileExt {
     /// has read, but it will never read more than would be necessary to
     /// completely fill the buffer.
     ///
-    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+    /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted
+    /// [`ErrorKind::UnexpectedEof`]: io::ErrorKind::UnexpectedEof
     ///
     /// # Examples
     ///
@@ -132,7 +130,7 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
     /// Note that similar to [`File::write`], it is not an error to return a
     /// short write.
     ///
-    /// [`File::write`]: ../../../../std/fs/struct.File.html#method.write
+    /// [`File::write`]: fs::File::write
     ///
     /// # Examples
     ///
@@ -171,8 +169,8 @@ fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
     /// This function will return the first error of
     /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
     ///
-    /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
-    /// [`write_at`]: #tymethod.write_at
+    /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted
+    /// [`write_at`]: FileExt::write_at
     ///
     /// # Examples
     ///
@@ -223,8 +221,6 @@ fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
 }
 
 /// Unix-specific extensions to [`fs::Permissions`].
-///
-/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait PermissionsExt {
     /// Returns the underlying raw `st_mode` bits that contain the standard
@@ -300,8 +296,6 @@ fn from_mode(mode: u32) -> Permissions {
 }
 
 /// Unix-specific extensions to [`fs::OpenOptions`].
-///
-/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
 #[stable(feature = "fs_ext", since = "1.1.0")]
 pub trait OpenOptionsExt {
     /// Sets the mode bits that a new file will be created with.
@@ -369,8 +363,6 @@ fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
 */
 
 /// Unix-specific extensions to [`fs::Metadata`].
-///
-/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
 #[stable(feature = "metadata_ext", since = "1.1.0")]
 pub trait MetadataExt {
     /// Returns the ID of the device containing the file.
@@ -650,12 +642,10 @@ fn attrib(&self) -> u8 {
     }
 }
 
-/// Unix-specific extensions for [`FileType`].
+/// Unix-specific extensions for [`fs::FileType`].
 ///
 /// Adds support for special Unix file types such as block/character devices,
 /// pipes, and sockets.
-///
-/// [`FileType`]: ../../../../std/fs/struct.FileType.html
 #[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
@@ -749,8 +739,6 @@ fn is_socket(&self) -> bool {
 }
 
 /// Unix-specific extension methods for [`fs::DirEntry`].
-///
-/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
 pub trait DirEntryExt {
     /// Returns the underlying `d_ino` field in the contained `dirent`
@@ -811,8 +799,6 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 }
 
 /// Unix-specific extensions to [`fs::DirBuilder`].
-///
-/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
 #[stable(feature = "dir_builder", since = "1.6.0")]
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
index c3710f4b9124d70a2e9326b9808efc2a92ad091f..3ffa5be1b3bf1c64eafd74e09694cb4723822ae5 100644 (file)
@@ -10,8 +10,6 @@
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
 /// Unix-specific extensions to the [`process::Command`] builder.
-///
-/// [`process::Command`]: ../../../../std/process/struct.Command.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait CommandExt {
     /// Sets the child process's user ID. This translates to a
@@ -65,7 +63,7 @@ unsafe fn pre_exec<F>(&mut self, f: F) -> &mut process::Command
     /// This method is stable and usable, but it should be unsafe. To fix
     /// that, it got deprecated in favor of the unsafe [`pre_exec`].
     ///
-    /// [`pre_exec`]: #tymethod.pre_exec
+    /// [`pre_exec`]: CommandExt::pre_exec
     #[stable(feature = "process_exec", since = "1.15.0")]
     #[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
     fn before_exec<F>(&mut self, f: F) -> &mut process::Command
@@ -94,7 +92,6 @@ fn before_exec<F>(&mut self, f: F) -> &mut process::Command
     /// a new child. Like spawn, however, the default behavior for the stdio
     /// descriptors will be to inherited from the current process.
     ///
-    /// [`process::exit`]: ../../../process/fn.exit.html
     ///
     /// # Notes
     ///
@@ -151,8 +148,6 @@ fn arg0<S>(&mut self, arg: S) -> &mut process::Command
 }
 
 /// Unix-specific extensions to [`process::ExitStatus`].
-///
-/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExitStatusExt {
     /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
index 8c56cf1cb3414bb1508114f63ce389b9a4fddc20..ab846adf9423b655320f33c9c0f38cb2e73ccfaa 100644 (file)
@@ -48,12 +48,6 @@ fn main() {
         cmd.arg(arg);
     }
 
-    // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick
-    // it up so we can make rustdoc print this into the docs
-    if let Some(version) = env::var_os("RUSTDOC_CRATE_VERSION") {
-        cmd.arg("--crate-version").arg(version);
-    }
-
     // Needed to be able to run all rustdoc tests.
     if let Some(ref x) = env::var_os("RUSTDOC_RESOURCE_SUFFIX") {
         // This "unstable-options" can be removed when `--resource-suffix` is stabilized
index 4b0905bd6c16c8d14eee46a0c5e45b201b3a89c3..6446fa7550d537da81622f2cd37058b0dd992679 100644 (file)
@@ -745,7 +745,6 @@ pub fn rustdoc_cmd(&self, compiler: Compiler) -> Command {
             .env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
             .env("CFG_RELEASE_CHANNEL", &self.config.channel)
             .env("RUSTDOC_REAL", self.rustdoc(compiler))
-            .env("RUSTDOC_CRATE_VERSION", self.rust_version())
             .env("RUSTC_BOOTSTRAP", "1")
             .arg("-Winvalid_codeblock_attributes");
         if self.config.deny_warnings {
@@ -860,6 +859,10 @@ pub fn cargo(
             rustflags.arg("--cfg=bootstrap");
         }
 
+        if self.config.rust_new_symbol_mangling {
+            rustflags.arg("-Zsymbol-mangling-version=v0");
+        }
+
         // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`,
         // but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See
         // #71458.
@@ -1271,7 +1274,11 @@ pub fn cargo(
         }
 
         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
-        cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
+        // This replaces spaces with newlines because RUSTDOCFLAGS does not
+        // support arguments with regular spaces. Hopefully someday Cargo will
+        // have space support.
+        let rust_version = self.rust_version().replace(' ', "\n");
+        rustdocflags.arg("--crate-version").arg(&rust_version);
 
         // Environment variables *required* throughout the build
         //
@@ -1448,14 +1455,14 @@ fn new(target: TargetSelection) -> Rustflags {
 
     fn env(&mut self, env: &str) {
         if let Ok(s) = env::var(env) {
-            for part in s.split_whitespace() {
+            for part in s.split(' ') {
                 self.arg(part);
             }
         }
     }
 
     fn arg(&mut self, arg: &str) -> &mut Self {
-        assert_eq!(arg.split_whitespace().count(), 1);
+        assert_eq!(arg.split(' ').count(), 1);
         if !self.0.is_empty() {
             self.0.push_str(" ");
         }
index d64ca95d24392ab1221c90d6974eb122bf42d955..70b1c471ac3f0e6f11efc24d4d0b17a17a081354 100644 (file)
@@ -112,6 +112,7 @@ pub struct Config {
     pub rust_verify_llvm_ir: bool,
     pub rust_thin_lto_import_instr_limit: Option<u32>,
     pub rust_remap_debuginfo: bool,
+    pub rust_new_symbol_mangling: bool,
 
     pub build: TargetSelection,
     pub hosts: Vec<TargetSelection>,
@@ -410,6 +411,7 @@ struct Rust {
     test_compare_mode: Option<bool>,
     llvm_libunwind: Option<bool>,
     control_flow_guard: Option<bool>,
+    new_symbol_mangling: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -637,6 +639,7 @@ pub fn parse(args: &[String]) -> Config {
             debuginfo_level_tests = rust.debuginfo_level_tests;
             optimize = rust.optimize;
             ignore_git = rust.ignore_git;
+            set(&mut config.rust_new_symbol_mangling, rust.new_symbol_mangling);
             set(&mut config.rust_optimize_tests, rust.optimize_tests);
             set(&mut config.codegen_tests, rust.codegen_tests);
             set(&mut config.rust_rpath, rust.rpath);
index 48b2cc24d4cd8bfb22b62e84dab700b320e07046..f1bc3d11d8b770cdb25a00446f864579e78ad894 100644 (file)
@@ -178,7 +178,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
             .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
 
-        if !target.contains("netbsd") {
+        if !target.contains("netbsd") && target != "aarch64-apple-darwin" {
             cfg.define("LLVM_ENABLE_ZLIB", "ON");
         } else {
             // FIXME: Enable zlib on NetBSD too
@@ -282,14 +282,6 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
                 "LLVM_CONFIG_PATH",
                 host_bin.join("llvm-config").with_extension(EXE_EXTENSION),
             );
-
-            if target.contains("netbsd") {
-                cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
-            } else if target.contains("freebsd") {
-                cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
-            } else if target.contains("windows") {
-                cfg.define("CMAKE_SYSTEM_NAME", "Windows");
-            }
         }
 
         if let Some(ref suffix) = builder.config.llvm_version_suffix {
@@ -378,6 +370,22 @@ fn configure_cmake(
     }
     cfg.target(&target.triple).host(&builder.config.build.triple);
 
+    if target != builder.config.build {
+        if target.contains("netbsd") {
+            cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
+        } else if target.contains("freebsd") {
+            cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
+        } else if target.contains("windows") {
+            cfg.define("CMAKE_SYSTEM_NAME", "Windows");
+        }
+        // When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in
+        // that case like CMake we cannot easily determine system version either.
+        //
+        // Since, the LLVM itself makes rather limited use of version checks in
+        // CMakeFiles (and then only in tests), and so far no issues have been
+        // reported, the system version is currently left unset.
+    }
+
     let sanitize_cc = |cc: &Path| {
         if target.contains("msvc") {
             OsString::from(cc.to_str().unwrap().replace("\\", "/"))
@@ -786,6 +794,7 @@ fn supported_sanitizers(
         }
         "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
         "x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
+        "x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
         "x86_64-unknown-linux-gnu" => {
             common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
         }
index 11e2564305f0db3b54825cc65d556030e267b83b..ac833a55d4c53bbf2224fa0adf7fffba6b76de73 100644 (file)
@@ -599,7 +599,6 @@ fn run(self, builder: &Builder<'_>) {
             .env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
             .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
             .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
-            .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
             .env("RUSTC_BOOTSTRAP", "1");
         if let Some(linker) = builder.linker(self.compiler.host, true) {
             cmd.env("RUSTC_TARGET_LINKER", linker);
index 766e6531c95071880cb50e0770716d0e514cda2a..bfc768f9935126d63ab7e15813133e19c5809096 100644 (file)
@@ -29,5 +29,5 @@ ENV \
 
 ENV HOSTS=x86_64-unknown-freebsd
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --enable-sanitizers --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
index 6a596b3465f20da7e0b22843b63871fb89c1daf9..cb507dced4248c22c87c95be88e528b938038432 100644 (file)
@@ -19,8 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+RUN mkdir -p /config
+RUN echo "[rust]" > /config/nopt-std-config.toml
+RUN echo "optimize = false" >> /config/nopt-std-config.toml
+
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
-ENV SCRIPT python3 ../x.py --stage 2 test
+ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
+  && python3 ../x.py --stage 2 test
 
 # FIXME(#59637) takes too long on CI right now
 ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
index fa769cac9c1da8ec7a8241049056dc1a193287fe..41e83c69e549f4809ecdeffb54351356101cfb1f 100644 (file)
@@ -18,7 +18,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+RUN mkdir -p /config
+RUN echo "[rust]" > /config/nopt-std-config.toml
+RUN echo "optimize = false" >> /config/nopt-std-config.toml
+
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
   --disable-optimize-tests \
   --set rust.test-compare-mode
-ENV SCRIPT python3 ../x.py --stage 2 test
+ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
+  && python3 ../x.py --stage 2 test
index 5cf4f97fb886394d5754016d3fb99d6e095ccc12..5e6a0340d12a0f35d12956b32dfc93595b5efe5b 100644 (file)
@@ -611,11 +611,7 @@ macro_rules! which_arena_for_type {
 
 #[macro_export]
 macro_rules! declare_arena {
-    // This macro has to take the same input as
-    // `impl_arena_allocatable_decoders` which requires a second version of
-    // each type. We ignore that type until we can fix
-    // `impl_arena_allocatable_decoders`.
-    ([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => {
+    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
         #[derive(Default)]
         pub struct Arena<$tcx> {
             pub dropless: $crate::DroplessArena,
index ab0ab7244dbe4818adda88a98852d4105f88ab17..73c5e33753f2934faf1412940ceb36f3ff893e33 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_serialize = { path = "../librustc_serialize" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
index a0541158bc2c5f500f9f575e482e8dedde8c2ddd..6dff02486ff197a0d58a178b19a0c0d46758fe43 100644 (file)
@@ -53,7 +53,7 @@
 /// ```
 ///
 /// `'outer` is a label.
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Copy, HashStable_Generic)]
 pub struct Label {
     pub ident: Ident,
 }
@@ -66,7 +66,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 /// A "Lifetime" is an annotation of the scope in which variable
 /// can be used, e.g. `'a` in `&'a i32`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, Encodable, Decodable, Copy)]
 pub struct Lifetime {
     pub id: NodeId,
     pub ident: Ident,
@@ -90,7 +90,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// along with a bunch of supporting information.
 ///
 /// E.g., `std::cmp::PartialEq`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Path {
     pub span: Span,
     /// The segments in the path: the things separated by `::`.
@@ -128,7 +128,7 @@ pub fn is_global(&self) -> bool {
 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
 ///
 /// E.g., `std`, `String` or `Box<T>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct PathSegment {
     /// The identifier portion of this path segment.
     pub ident: Ident,
@@ -156,7 +156,7 @@ pub fn path_root(span: Span) -> Self {
 /// The arguments of a path segment.
 ///
 /// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum GenericArgs {
     /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.
     AngleBracketed(AngleBracketedArgs),
@@ -188,7 +188,7 @@ pub fn span(&self) -> Span {
 }
 
 /// Concrete argument in the sequence of generic args.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum GenericArg {
     /// `'a` in `Foo<'a>`
     Lifetime(Lifetime),
@@ -209,7 +209,7 @@ pub fn span(&self) -> Span {
 }
 
 /// A path like `Foo<'a, T>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Encodable, Decodable, Debug, Default)]
 pub struct AngleBracketedArgs {
     /// The overall span.
     pub span: Span,
@@ -219,7 +219,7 @@ pub struct AngleBracketedArgs {
 
 /// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`,
 /// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum AngleBracketedArg {
     /// Argument for a generic parameter.
     Arg(GenericArg),
@@ -240,7 +240,7 @@ fn into(self) -> Option<P<GenericArgs>> {
 }
 
 /// A path like `Foo(A, B) -> C`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ParenthesizedArgs {
     /// Overall span
     pub span: Span,
@@ -269,7 +269,7 @@ pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
 /// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
 ///
 /// Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
 pub enum TraitBoundModifier {
     /// No modifiers
     None,
@@ -290,7 +290,7 @@ pub enum TraitBoundModifier {
 /// `typeck::collect::compute_bounds` matches these against
 /// the "special" built-in traits (see `middle::lang_items`) and
 /// detects `Copy`, `Send` and `Sync`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum GenericBound {
     Trait(PolyTraitRef, TraitBoundModifier),
     Outlives(Lifetime),
@@ -357,7 +357,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum GenericParamKind {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
     Lifetime,
@@ -371,7 +371,7 @@ pub enum GenericParamKind {
     },
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct GenericParam {
     pub id: NodeId,
     pub ident: Ident,
@@ -383,7 +383,7 @@ pub struct GenericParam {
 
 /// Represents lifetime, type and const parameters attached to a declaration of
 /// a function, enum, trait, etc.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Generics {
     pub params: Vec<GenericParam>,
     pub where_clause: WhereClause,
@@ -406,7 +406,7 @@ fn default() -> Generics {
 }
 
 /// A where-clause in a definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct WhereClause {
     /// `true` if we ate a `where` token: this can happen
     /// if we parsed no predicates (e.g. `struct Foo where {}`).
@@ -418,7 +418,7 @@ pub struct WhereClause {
 }
 
 /// A single predicate in a where-clause.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum WherePredicate {
     /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
     BoundPredicate(WhereBoundPredicate),
@@ -441,7 +441,7 @@ pub fn span(&self) -> Span {
 /// A type bound.
 ///
 /// E.g., `for<'c> Foo: Send + Clone + 'c`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct WhereBoundPredicate {
     pub span: Span,
     /// Any generics from a `for` binding.
@@ -455,7 +455,7 @@ pub struct WhereBoundPredicate {
 /// A lifetime predicate.
 ///
 /// E.g., `'a: 'b + 'c`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct WhereRegionPredicate {
     pub span: Span,
     pub lifetime: Lifetime,
@@ -465,7 +465,7 @@ pub struct WhereRegionPredicate {
 /// An equality predicate (unsupported).
 ///
 /// E.g., `T = int`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct WhereEqPredicate {
     pub id: NodeId,
     pub span: Span,
@@ -473,7 +473,7 @@ pub struct WhereEqPredicate {
     pub rhs_ty: P<Ty>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Crate {
     pub module: Mod,
     pub attrs: Vec<Attribute>,
@@ -490,7 +490,7 @@ pub struct Crate {
 /// Possible values inside of compile-time attribute lists.
 ///
 /// E.g., the '..' in `#[name(..)]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum NestedMetaItem {
     /// A full MetaItem, for recursive meta items.
     MetaItem(MetaItem),
@@ -503,7 +503,7 @@ pub enum NestedMetaItem {
 /// A spanned compile-time attribute item.
 ///
 /// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MetaItem {
     pub path: Path,
     pub kind: MetaItemKind,
@@ -513,7 +513,7 @@ pub struct MetaItem {
 /// A compile-time attribute item.
 ///
 /// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum MetaItemKind {
     /// Word meta item.
     ///
@@ -532,7 +532,7 @@ pub enum MetaItemKind {
 /// A block (`{ .. }`).
 ///
 /// E.g., `{ .. }` as in `fn foo() { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Block {
     /// The statements in the block.
     pub stmts: Vec<Stmt>,
@@ -545,7 +545,7 @@ pub struct Block {
 /// A match pattern.
 ///
 /// Patterns appear in match statements and some other contexts, such as `let` and `if let`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Pat {
     pub id: NodeId,
     pub kind: PatKind,
@@ -636,7 +636,7 @@ pub fn is_rest(&self) -> bool {
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
 /// are treated the same as` x: x, y: ref y, z: ref mut z`,
 /// except is_shorthand is true
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FieldPat {
     /// The identifier for the field
     pub ident: Ident,
@@ -649,19 +649,19 @@ pub struct FieldPat {
     pub is_placeholder: bool,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 pub enum BindingMode {
     ByRef(Mutability),
     ByValue(Mutability),
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum RangeEnd {
     Included(RangeSyntax),
     Excluded,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum RangeSyntax {
     /// `...`
     DotDotDot,
@@ -669,7 +669,7 @@ pub enum RangeSyntax {
     DotDotEq,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum PatKind {
     /// Represents a wildcard pattern (`_`).
     Wild,
@@ -736,8 +736,8 @@ pub enum PatKind {
     MacCall(MacCall),
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum Mutability {
     Mut,
     Not,
@@ -770,7 +770,7 @@ pub fn prefix_str(&self) -> &'static str {
 /// The kind of borrow in an `AddrOf` expression,
 /// e.g., `&place` or `&raw const place`.
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum BorrowKind {
     /// A normal borrow, `&$expr` or `&mut $expr`.
     /// The resulting type is either `&'a T` or `&'a mut T`
@@ -782,7 +782,7 @@ pub enum BorrowKind {
     Raw,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 pub enum BinOpKind {
     /// The `+` operator (addition)
     Add,
@@ -881,7 +881,7 @@ pub fn is_by_value(&self) -> bool {
 /// Unary operator.
 ///
 /// Note that `&data` is not an operator, it's an `AddrOf` expression.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy)]
 pub enum UnOp {
     /// The `*` operator for dereferencing
     Deref,
@@ -910,7 +910,7 @@ pub fn to_string(op: UnOp) -> &'static str {
 }
 
 /// A statement
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Stmt {
     pub id: NodeId,
     pub kind: StmtKind,
@@ -944,7 +944,7 @@ pub fn is_expr(&self) -> bool {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum StmtKind {
     /// A local (let) binding.
     Local(P<Local>),
@@ -960,7 +960,7 @@ pub enum StmtKind {
     MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
 }
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
 pub enum MacStmtStyle {
     /// The macro statement had a trailing semicolon (e.g., `foo! { ... };`
     /// `foo!(...);`, `foo![...];`).
@@ -974,7 +974,7 @@ pub enum MacStmtStyle {
 }
 
 /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Local {
     pub id: NodeId,
     pub pat: P<Pat>,
@@ -995,7 +995,7 @@ pub struct Local {
 ///     _ => { println!("no match!") },
 /// }
 /// ```
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Arm {
     pub attrs: Vec<Attribute>,
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
@@ -1010,7 +1010,7 @@ pub struct Arm {
 }
 
 /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Field {
     pub attrs: AttrVec,
     pub id: NodeId,
@@ -1021,13 +1021,13 @@ pub struct Field {
     pub is_placeholder: bool,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 pub enum BlockCheckMode {
     Default,
     Unsafe(UnsafeSource),
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 pub enum UnsafeSource {
     CompilerGenerated,
     UserProvided,
@@ -1038,14 +1038,14 @@ pub enum UnsafeSource {
 /// These are usually found nested inside types (e.g., array lengths)
 /// or expressions (e.g., repeat counts), and also used to define
 /// explicit discriminant values for enum variants.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct AnonConst {
     pub id: NodeId,
     pub value: P<Expr>,
 }
 
 /// An expression.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Expr {
     pub id: NodeId,
     pub kind: ExprKind,
@@ -1204,7 +1204,7 @@ pub fn precedence(&self) -> ExprPrecedence {
 }
 
 /// Limit types of a range (inclusive or exclusive)
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
 pub enum RangeLimits {
     /// Inclusive at the beginning, exclusive at the end
     HalfOpen,
@@ -1212,7 +1212,7 @@ pub enum RangeLimits {
     Closed,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ExprKind {
     /// A `box x` expression.
     Box(P<Expr>),
@@ -1369,7 +1369,7 @@ pub enum ExprKind {
 ///  ^~~~~    ^
 ///  ty       position = 0
 /// ```
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct QSelf {
     pub ty: P<Ty>,
 
@@ -1381,7 +1381,7 @@ pub struct QSelf {
 }
 
 /// A capture clause used in closures and `async` blocks.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum CaptureBy {
     /// `move |x| y + x`.
     Value,
@@ -1391,7 +1391,7 @@ pub enum CaptureBy {
 
 /// The movability of a generator / closure literal:
 /// whether a generator contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
 #[derive(HashStable_Generic)]
 pub enum Movability {
     /// May contain self-references, `!Unpin`.
@@ -1402,7 +1402,7 @@ pub enum Movability {
 
 /// Represents a macro invocation. The `path` indicates which macro
 /// is being invoked, and the `args` are arguments passed to it.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct MacCall {
     pub path: Path,
     pub args: P<MacArgs>,
@@ -1416,7 +1416,7 @@ pub fn span(&self) -> Span {
 }
 
 /// Arguments passed to an attribute or a function-like macro.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum MacArgs {
     /// No arguments - `#[attr]`.
     Empty,
@@ -1477,7 +1477,7 @@ pub fn need_semicolon(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum MacDelimiter {
     Parenthesis,
     Bracket,
@@ -1504,14 +1504,14 @@ pub fn from_token(delim: DelimToken) -> Option<MacDelimiter> {
 }
 
 /// Represents a macro definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct MacroDef {
     pub body: P<MacArgs>,
     /// `true` if macro was defined with `macro_rules`.
     pub macro_rules: bool,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)]
 #[derive(HashStable_Generic)]
 pub enum StrStyle {
     /// A regular string, like `"foo"`.
@@ -1523,7 +1523,7 @@ pub enum StrStyle {
 }
 
 /// An AST literal.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct Lit {
     /// The original literal token as written in source code.
     pub token: token::Lit,
@@ -1535,7 +1535,7 @@ pub struct Lit {
 }
 
 /// Same as `Lit`, but restricted to string literals.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub struct StrLit {
     /// The original literal token as written in source code.
     pub style: StrStyle,
@@ -1562,7 +1562,7 @@ pub fn as_lit(&self) -> Lit {
 }
 
 /// Type of the integer literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
 #[derive(HashStable_Generic)]
 pub enum LitIntType {
     /// e.g. `42_i32`.
@@ -1574,7 +1574,7 @@ pub enum LitIntType {
 }
 
 /// Type of the float literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
 #[derive(HashStable_Generic)]
 pub enum LitFloatType {
     /// A float literal with a suffix (`1f32` or `1E10f32`).
@@ -1586,7 +1586,7 @@ pub enum LitFloatType {
 /// Literal kind.
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
 pub enum LitKind {
     /// A string literal (`"foo"`).
     Str(Symbol, StrStyle),
@@ -1658,7 +1658,7 @@ pub fn is_suffixed(&self) -> bool {
 
 // N.B., If you change this, you'll probably want to change the corresponding
 // type structure in `middle/ty.rs` as well.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct MutTy {
     pub ty: P<Ty>,
     pub mutbl: Mutability,
@@ -1666,14 +1666,14 @@ pub struct MutTy {
 
 /// Represents a function's signature in a trait declaration,
 /// trait implementation, or free function.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FnSig {
     pub header: FnHeader,
     pub decl: P<FnDecl>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum FloatTy {
     F32,
     F64,
@@ -1702,8 +1702,8 @@ pub fn bit_width(self) -> u64 {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum IntTy {
     Isize,
     I8,
@@ -1767,8 +1767,8 @@ pub fn normalize(&self, target_width: u32) -> Self {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum UintTy {
     Usize,
     U8,
@@ -1831,7 +1831,7 @@ pub fn normalize(&self, target_width: u32) -> Self {
 
 /// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
 /// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct AssocTyConstraint {
     pub id: NodeId,
     pub ident: Ident,
@@ -1840,7 +1840,7 @@ pub struct AssocTyConstraint {
 }
 
 /// The kinds of an `AssocTyConstraint`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum AssocTyConstraintKind {
     /// E.g., `A = Bar` in `Foo<A = Bar>`.
     Equality { ty: P<Ty> },
@@ -1848,14 +1848,14 @@ pub enum AssocTyConstraintKind {
     Bound { bounds: GenericBounds },
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Ty {
     pub id: NodeId,
     pub kind: TyKind,
     pub span: Span,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct BareFnTy {
     pub unsafety: Unsafe,
     pub ext: Extern,
@@ -1864,7 +1864,7 @@ pub struct BareFnTy {
 }
 
 /// The various kinds of type recognized by the compiler.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum TyKind {
     /// A variable-length slice (`[T]`).
     Slice(P<Ty>),
@@ -1923,7 +1923,7 @@ pub fn is_unit(&self) -> bool {
 }
 
 /// Syntax used to declare a trait object.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
 pub enum TraitObjectSyntax {
     Dyn,
     None,
@@ -1932,14 +1932,14 @@ pub enum TraitObjectSyntax {
 /// Inline assembly operand explicit register or register class.
 ///
 /// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub enum InlineAsmRegOrRegClass {
     Reg(Symbol),
     RegClass(Symbol),
 }
 
 bitflags::bitflags! {
-    #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+    #[derive(Encodable, Decodable, HashStable_Generic)]
     pub struct InlineAsmOptions: u8 {
         const PURE = 1 << 0;
         const NOMEM = 1 << 1;
@@ -1951,7 +1951,7 @@ pub struct InlineAsmOptions: u8 {
     }
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum InlineAsmTemplatePiece {
     String(String),
     Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
@@ -1995,7 +1995,7 @@ pub fn to_string(s: &[Self]) -> String {
 /// Inline assembly operand.
 ///
 /// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum InlineAsmOperand {
     In {
         reg: InlineAsmRegOrRegClass,
@@ -2028,7 +2028,7 @@ pub enum InlineAsmOperand {
 /// Inline assembly.
 ///
 /// E.g., `asm!("NOP");`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct InlineAsm {
     pub template: Vec<InlineAsmTemplatePiece>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
@@ -2039,7 +2039,7 @@ pub struct InlineAsm {
 /// Inline assembly dialect.
 ///
 /// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
 pub enum LlvmAsmDialect {
     Att,
     Intel,
@@ -2048,7 +2048,7 @@ pub enum LlvmAsmDialect {
 /// LLVM-style inline assembly.
 ///
 /// E.g., `"={eax}"(result)` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct LlvmInlineAsmOutput {
     pub constraint: Symbol,
     pub expr: P<Expr>,
@@ -2059,7 +2059,7 @@ pub struct LlvmInlineAsmOutput {
 /// LLVM-style inline assembly.
 ///
 /// E.g., `llvm_asm!("NOP");`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct LlvmInlineAsm {
     pub asm: Symbol,
     pub asm_str_style: StrStyle,
@@ -2074,7 +2074,7 @@ pub struct LlvmInlineAsm {
 /// A parameter in a function header.
 ///
 /// E.g., `bar: usize` as in `fn foo(bar: usize)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Param {
     pub attrs: AttrVec,
     pub ty: P<Ty>,
@@ -2087,7 +2087,7 @@ pub struct Param {
 /// Alternative representation for `Arg`s describing `self` parameter of methods.
 ///
 /// E.g., `&mut self` as in `fn foo(&mut self)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum SelfKind {
     /// `self`, `mut self`
     Value(Mutability),
@@ -2165,7 +2165,7 @@ pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Par
 ///
 /// Please note that it's different from `FnHeader` structure
 /// which contains metadata about function safety, asyncness, constness and ABI.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FnDecl {
     pub inputs: Vec<Param>,
     pub output: FnRetTy,
@@ -2187,20 +2187,20 @@ pub fn c_variadic(&self) -> bool {
 }
 
 /// Is the trait definition an auto trait?
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum IsAuto {
     Yes,
     No,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug)]
 #[derive(HashStable_Generic)]
 pub enum Unsafe {
     Yes(Span),
     No,
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug)]
 pub enum Async {
     Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
     No,
@@ -2220,7 +2220,7 @@ pub fn opt_return_id(self) -> Option<NodeId> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
 #[derive(HashStable_Generic)]
 pub enum Const {
     Yes(Span),
@@ -2229,13 +2229,13 @@ pub enum Const {
 
 /// Item defaultness.
 /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum Defaultness {
     Default(Span),
     Final,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
@@ -2252,7 +2252,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum FnRetTy {
     /// Returns type is not specified.
     ///
@@ -2275,7 +2275,7 @@ pub fn span(&self) -> Span {
 /// Module declaration.
 ///
 /// E.g., `mod foo;` or `mod foo { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Encodable, Decodable, Debug, Default)]
 pub struct Mod {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2289,7 +2289,7 @@ pub struct Mod {
 /// Foreign module declaration.
 ///
 /// E.g., `extern { .. }` or `extern C { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ForeignMod {
     pub abi: Option<StrLit>,
     pub items: Vec<P<ForeignItem>>,
@@ -2298,17 +2298,17 @@ pub struct ForeignMod {
 /// Global inline assembly.
 ///
 /// Also known as "module-level assembly" or "file-scoped assembly".
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy)]
 pub struct GlobalAsm {
     pub asm: Symbol,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct EnumDef {
     pub variants: Vec<Variant>,
 }
 /// Enum variant.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Variant {
     /// Attributes of the variant.
     pub attrs: Vec<Attribute>,
@@ -2330,7 +2330,7 @@ pub struct Variant {
 }
 
 /// Part of `use` item to the right of its prefix.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum UseTreeKind {
     /// `use prefix` or `use prefix as rename`
     ///
@@ -2345,7 +2345,7 @@ pub enum UseTreeKind {
 
 /// A tree of paths sharing common prefixes.
 /// Used in `use` items both at top-level and inside of braces in import groups.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct UseTree {
     pub prefix: Path,
     pub kind: UseTreeKind,
@@ -2367,7 +2367,7 @@ pub fn ident(&self) -> Ident {
 /// Distinguishes between `Attribute`s that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
 pub enum AttrStyle {
     Outer,
     Inner,
@@ -2380,19 +2380,19 @@ pub struct AttrId {
     }
 }
 
-impl rustc_serialize::Encodable for AttrId {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_unit()
     }
 }
 
-impl rustc_serialize::Decodable for AttrId {
-    fn decode<D: Decoder>(d: &mut D) -> Result<AttrId, D::Error> {
+impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
+    fn decode(d: &mut D) -> Result<AttrId, D::Error> {
         d.read_nil().map(|_| crate::attr::mk_attr_id())
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct AttrItem {
     pub path: Path,
     pub args: MacArgs,
@@ -2402,7 +2402,7 @@ pub struct AttrItem {
 pub type AttrVec = ThinVec<Attribute>;
 
 /// Metadata associated with an item.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Attribute {
     pub kind: AttrKind,
     pub id: AttrId,
@@ -2412,7 +2412,7 @@ pub struct Attribute {
     pub span: Span,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum AttrKind {
     /// A normal attribute.
     Normal(AttrItem),
@@ -2429,13 +2429,13 @@ pub enum AttrKind {
 /// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl.
 /// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the
 /// same as the impl's `NodeId`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct TraitRef {
     pub path: Path,
     pub ref_id: NodeId,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct PolyTraitRef {
     /// The `'a` in `<'a> Foo<&'a T>`.
     pub bound_generic_params: Vec<GenericParam>,
@@ -2456,7 +2456,7 @@ pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self {
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum CrateSugar {
     /// Source is `pub(crate)`.
     PubCrate,
@@ -2467,7 +2467,7 @@ pub enum CrateSugar {
 
 pub type Visibility = Spanned<VisibilityKind>;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum VisibilityKind {
     Public,
     Crate(CrateSugar),
@@ -2484,7 +2484,7 @@ pub fn is_pub(&self) -> bool {
 /// Field of a struct.
 ///
 /// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct StructField {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
@@ -2497,7 +2497,7 @@ pub struct StructField {
 }
 
 /// Fields and constructor ids of enum variants and structs.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum VariantData {
     /// Struct variant.
     ///
@@ -2532,7 +2532,7 @@ pub fn ctor_id(&self) -> Option<NodeId> {
 }
 
 /// An item definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Item<K = ItemKind> {
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
@@ -2569,7 +2569,7 @@ pub fn into_item(self) -> Item {
 }
 
 /// `extern` qualifier on a function item or function type.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub enum Extern {
     None,
     Implicit,
@@ -2586,7 +2586,7 @@ pub fn from_abi(abi: Option<StrLit>) -> Extern {
 ///
 /// All the information between the visibility and the name of the function is
 /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
 pub struct FnHeader {
     pub unsafety: Unsafe,
     pub asyncness: Async,
@@ -2616,7 +2616,7 @@ fn default() -> FnHeader {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ItemKind {
     /// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
     ///
@@ -2755,7 +2755,7 @@ pub fn generics(&self) -> Option<&Generics> {
 /// In an implementation, all items must be provided.
 /// The `Option`s below denote the bodies, where `Some(_)`
 /// means "provided" and conversely `None` means "required".
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum AssocItemKind {
     /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
     /// If `def` is parsed, then the constant is provided, and otherwise required.
@@ -2803,7 +2803,7 @@ fn try_from(item_kind: ItemKind) -> Result<AssocItemKind, ItemKind> {
 }
 
 /// An item in `extern` block.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ForeignItemKind {
     /// A foreign static item (`static FOO: u8`).
     Static(P<Ty>, Mutability, Option<P<Expr>>),
index 7558e9cc3a3afd676fde5742d528273bd41a534f..8ba55bf037b12bd15f1fdd1aeaeba8225442e215 100644 (file)
@@ -3,6 +3,9 @@
 // Are ASTs encodable?
 #[test]
 fn check_asts_encodable() {
-    fn assert_encodable<T: rustc_serialize::Encodable>() {}
+    fn assert_encodable<
+        T: for<'a> rustc_serialize::Encodable<rustc_serialize::json::Encoder<'a>>,
+    >() {
+    }
     assert_encodable::<Crate>();
 }
index 95d4c09dac3110e3c9ef6de7d34e1375e56d5ff2..bd7d85167140dfe4e28a712edf85a4d17dfbf8dc 100644 (file)
@@ -9,7 +9,7 @@
 /// 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, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
 pub struct CrateDisambiguator(Fingerprint);
 
 impl CrateDisambiguator {
index 3f876169d2236e4baddf2c305cf16a7bbaef517d..fb5ce3118262782fc9e264f47a1264fd9f0d7f96 100644 (file)
@@ -18,8 +18,7 @@
 #![feature(unicode_internals)]
 #![recursion_limit = "256"]
 
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
 extern crate rustc_macros;
 
 #[macro_export]
index cd562c48e9115eb24f12bd73bf5eb138d974f533..1035e945538f5b10136b7b4547f8728ed9c6a646 100644 (file)
@@ -1,10 +1,8 @@
-use rustc_serialize::{Decoder, Encoder};
 use rustc_span::ExpnId;
 use std::fmt;
 
 rustc_index::newtype_index! {
     pub struct NodeId {
-        ENCODABLE = custom
         DEBUG_FORMAT = "NodeId({})"
     }
 }
@@ -34,15 +32,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&self.as_u32(), f)
     }
 }
-
-impl rustc_serialize::UseSpecializedEncodable for NodeId {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u32(self.as_u32())
-    }
-}
-
-impl rustc_serialize::UseSpecializedDecodable for NodeId {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
-        d.read_u32().map(NodeId::from_u32)
-    }
-}
index 4597624ef88b08d21f55c6d55bac50f39709494b..e4a3cccb7ead1c9c30efed20cb687f30759fac55 100644 (file)
@@ -114,14 +114,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<T: 'static + Decodable> Decodable for P<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
+impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
+    fn decode(d: &mut D) -> Result<P<T>, D::Error> {
         Decodable::decode(d).map(P)
     }
 }
 
-impl<T: Encodable> Encodable for P<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
@@ -197,14 +197,14 @@ fn into_iter(self) -> Self::IntoIter {
     }
 }
 
-impl<T: Encodable> Encodable for P<[T]> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         Encodable::encode(&**self, s)
     }
 }
 
-impl<T: Decodable> Decodable for P<[T]> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for P<[T]> {
+    fn decode(d: &mut D) -> Result<P<[T]>, D::Error> {
         Ok(P::from_vec(Decodable::decode(d)?))
     }
 }
index bcce881ed48c5deef7423eb8bfa4a8b082c5e1b8..46c4be0a33bf76af3b9ae1e8e287ac4792bda563 100644 (file)
 use std::borrow::Cow;
 use std::{fmt, mem};
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum CommentKind {
     Line,
     Block,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
 #[derive(HashStable_Generic)]
 pub enum BinOpToken {
     Plus,
@@ -39,7 +39,7 @@ pub enum BinOpToken {
 }
 
 /// A delimiter token.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy)]
 #[derive(HashStable_Generic)]
 pub enum DelimToken {
     /// A round parenthesis (i.e., `(` or `)`).
@@ -62,7 +62,7 @@ pub fn is_empty(self) -> bool {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum LitKind {
     Bool, // AST only, must never appear in a `Token`
     Byte,
@@ -77,7 +77,7 @@ pub enum LitKind {
 }
 
 /// A literal token.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct Lit {
     pub kind: LitKind,
     pub symbol: Symbol,
@@ -188,7 +188,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool {
             .contains(&name)
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum TokenKind {
     /* Expression-operator symbols. */
     Eq,
@@ -267,7 +267,7 @@ pub enum TokenKind {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(TokenKind, 16);
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 pub struct Token {
     pub kind: TokenKind,
     pub span: Span,
@@ -688,7 +688,7 @@ fn eq(&self, rhs: &TokenKind) -> bool {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Encodable, Decodable)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
     NtItem(P<ast::Item>),
@@ -711,7 +711,7 @@ pub enum Nonterminal {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(Nonterminal, 40);
 
-#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
 pub enum NonterminalKind {
     Item,
     Block,
index 9d0199078fa6a354eb4ee9f51305aa95fbb4e4fa..151acddae840e567c171362311ce6813f6603c5b 100644 (file)
@@ -35,7 +35,7 @@
 ///
 /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
-#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum TokenTree {
     /// A single token
     Token(Token),
@@ -124,7 +124,7 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
-#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Default, Encodable, Decodable)]
 pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
@@ -133,7 +133,7 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
 #[cfg(target_arch = "x86_64")]
 rustc_data_structures::static_assert_size!(TokenStream, 8);
 
-#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
 pub enum IsJoint {
     Joint,
     NonJoint,
@@ -408,7 +408,7 @@ pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub struct DelimSpan {
     pub open: Span,
     pub close: Span,
index 4428d09902b92d6b8a3360e130737b33eb66b32d..597e5b437fcb15c983912b200c3c7afc4e9d40d8 100644 (file)
@@ -10,8 +10,8 @@
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
-use log::debug;
 use std::ascii;
+use tracing::debug;
 
 pub enum LitError {
     NotLiteral,
index e5bcc571d417637a7c5c64cbe65f3c98b4e57575..2ee94965756a5e0d72fc8bbe084b628f1c49f799 100644 (file)
@@ -222,7 +222,6 @@ pub fn can_continue_expr_unambiguously(&self) -> bool {
             Greater | // `{ 42 } > 3`
             GreaterEqual | // `{ 42 } >= 3`
             AssignOp(_) | // `{ 42 } +=`
-            LAnd | // `{ 42 } &&foo`
             As | // `{ 42 } as usize`
             // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
             // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
index 2c3d1e97df97574bb932723c861c6dd7c603a94e..b65a88cb90e88501721432cced016e00185e3cef 100644 (file)
@@ -50,6 +50,13 @@ pub fn header(&self) -> Option<&'a FnHeader> {
         }
     }
 
+    pub fn ident(&self) -> Option<&Ident> {
+        match self {
+            FnKind::Fn(_, ident, ..) => Some(ident),
+            _ => None,
+        }
+    }
+
     pub fn decl(&self) -> &'a FnDecl {
         match self {
             FnKind::Fn(_, _, sig, _, _) => &sig.decl,
index 5186e62fbf9bc34d866b0225f96122a7c5ed8199..699f5c9778a2f4338dcfd323470b5bab1303a947 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_ast::ast::*;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
@@ -75,6 +75,18 @@ fn visit_item(&mut self, item: &'a Item) {
         }
     }
 
+    fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
+        match fk {
+            FnKind::Fn(FnCtxt::Foreign, _, sig, _, _) => {
+                self.visit_fn_header(&sig.header);
+                visit::walk_fn_decl(self, &sig.decl);
+                // Don't visit the foreign function body even if it has one, since lowering the
+                // body would have no meaning and will have already been caught as a parse error.
+            }
+            _ => visit::walk_fn(self, fk, sp),
+        }
+    }
+
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
             AssocCtxt::Trait => {
index 5f131fae385b08c7d5b3a2c7186f6c5de608d4da..3ddabcc17f8b696a86e088e2cd9fd8430e398993 100644 (file)
@@ -67,7 +67,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
     }
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Encodable, Decodable)]
 pub enum InlineAttr {
     None,
     Hint,
@@ -75,7 +75,7 @@ pub enum InlineAttr {
     Never,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Encodable, Decodable)]
 pub enum OptimizeAttr {
     None,
     Speed,
@@ -130,7 +130,7 @@ pub fn find_unwind_attr(sess: &Session, attrs: &[Attribute]) -> Option<UnwindAtt
 ///
 /// - `#[stable]`
 /// - `#[unstable]`
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub struct Stability {
     pub level: StabilityLevel,
@@ -138,7 +138,7 @@ pub struct Stability {
 }
 
 /// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub struct ConstStability {
     pub level: StabilityLevel,
@@ -150,7 +150,7 @@ pub struct ConstStability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(Encodable, Decodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
@@ -632,7 +632,7 @@ pub fn eval_condition(
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
+#[derive(Encodable, Decodable, Clone, HashStable_Generic)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
     /// The note to issue a reason.
@@ -797,7 +797,7 @@ fn find_deprecation_generic<'a, I>(
     depr
 }
 
-#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
 pub enum ReprAttr {
     ReprInt(IntType),
     ReprC,
@@ -808,7 +808,8 @@ pub enum ReprAttr {
     ReprNoNiche,
 }
 
-#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum IntType {
     SignedInt(ast::IntTy),
     UnsignedInt(ast::UintTy),
index 5754bb48d24e1c4785d2b9f92512243277be0f3f..149a950f7d417ca3977f15c5bacd141ab5863176 100644 (file)
@@ -6,8 +6,7 @@
 
 #![feature(or_patterns)]
 
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
 extern crate rustc_macros;
 
 mod builtin;
index 55eab24b8a5105def8d34e6bfc591bd39c721bff..78cead02b7b7cc6fcdfaf1121a45a4b7032ae6e2 100644 (file)
@@ -149,7 +149,7 @@ fn parse_args<'a>(
                 return Err(err);
             } else {
                 // ...after that delegate to `expect` to also include the other expected tokens.
-                return Err(p.expect(&token::Comma).err().unwrap());
+                let _ = p.expect(&token::Comma)?;
             }
         }
         first = false;
@@ -359,24 +359,18 @@ fn report_invalid_references(&self, numbered_position_args: bool) {
             // for `println!("{7:7$}", 1);`
             refs.sort();
             refs.dedup();
-            let (arg_list, mut sp) = if refs.len() == 1 {
-                let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
-                (
-                    format!("argument {}", refs[0]),
-                    if spans.is_empty() {
-                        MultiSpan::from_span(self.fmtsp)
-                    } else {
-                        MultiSpan::from_spans(spans)
-                    },
-                )
+            let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
+            let sp = if self.arg_spans.is_empty() || spans.is_empty() {
+                MultiSpan::from_span(self.fmtsp)
+            } else {
+                MultiSpan::from_spans(spans)
+            };
+            let arg_list = if refs.len() == 1 {
+                format!("argument {}", refs[0])
             } else {
-                let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect());
                 let reg = refs.pop().unwrap();
-                (format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg,), pos)
+                format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg)
             };
-            if self.arg_spans.is_empty() {
-                sp = MultiSpan::from_span(self.fmtsp);
-            }
 
             e = self.ecx.struct_span_err(
                 sp,
@@ -1067,10 +1061,9 @@ pub fn expand_preparsed_format_args(
         let args_unused = errs_len;
 
         let mut diag = {
-            if errs_len == 1 {
-                let (sp, msg) = errs.into_iter().next().unwrap();
-                let mut diag = cx.ecx.struct_span_err(sp, msg);
-                diag.span_label(sp, msg);
+            if let [(sp, msg)] = &errs[..] {
+                let mut diag = cx.ecx.struct_span_err(*sp, *msg);
+                diag.span_label(*sp, *msg);
                 diag
             } else {
                 let mut diag = cx.ecx.struct_span_err(
index 024834bfe2aa558a9f252f7420b831dfd557d7a4..0c749657001a60b4ab31e27858b22eb74537343a 100644 (file)
@@ -215,7 +215,7 @@ impl CodegenCx<'ll, 'tcx> {
         debug!("get_static: sym={} instance={:?}", sym, instance);
 
         let g = if let Some(def_id) = def_id.as_local() {
-            let id = self.tcx.hir().as_local_hir_id(def_id);
+            let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
             let llty = self.layout_of(ty).llvm_type(self);
             // FIXME: refactor this to work without accessing the HIR
             let (g, attrs) = match self.tcx.hir().get(id) {
index 90831f0bcfbeebe6ce2c4f15d549b6e57ae80985..da567293d7be08905430cee69e23bf8e21c5a347 100644 (file)
@@ -8,7 +8,7 @@
 use log::debug;
 use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
 use rustc_codegen_ssa::traits::{
-    BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods,
+    BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods,
 };
 use rustc_data_structures::fx::FxHashMap;
 use rustc_llvm::RustString;
@@ -44,6 +44,16 @@ fn coverageinfo_finalize(&self) {
 }
 
 impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
+    /// Calls llvm::createPGOFuncNameVar() with the given function instance's mangled function name.
+    /// The LLVM API returns an llvm::GlobalVariable containing the function name, with the specific
+    /// variable name and linkage required by LLVM InstrProf source-based coverage instrumentation.
+    fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value {
+        let llfn = self.cx.get_fn(instance);
+        let mangled_fn_name = CString::new(self.tcx.symbol_name(instance).name)
+            .expect("error converting function name to C string");
+        unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
+    }
+
     fn add_counter_region(
         &mut self,
         instance: Instance<'tcx>,
index dfd5104a31f6d0ae735aba57aa8c84b476f0b85b..14aec1ff5e19e66e633f8e1115692ecc75fa3023 100644 (file)
@@ -215,19 +215,19 @@ fn codegen_intrinsic_call(
                 self.call(llfn, &[], None)
             }
             sym::count_code_region => {
-                let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
-                let mangled_fn = tcx.symbol_name(caller_instance);
-                let (mangled_fn_name, _len_val) = self.const_str(Symbol::intern(mangled_fn.name));
-                let num_counters = self.const_u32(coverageinfo.num_counters);
                 use coverage::count_code_region_args::*;
+                let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
+
+                let fn_name = self.create_pgo_func_name_var(caller_instance);
                 let hash = args[FUNCTION_SOURCE_HASH].immediate();
+                let num_counters = self.const_u32(coverageinfo.num_counters);
                 let index = args[COUNTER_ID].immediate();
                 debug!(
                     "translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \
-                    instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
-                    mangled_fn.name, hash, num_counters, index,
+                    instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
+                    fn_name, hash, num_counters, index,
                 );
-                self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
+                self.instrprof_increment(fn_name, hash, num_counters, index)
             }
             sym::va_start => self.va_start(args[0].immediate()),
             sym::va_end => self.va_end(args[0].immediate()),
index f094ad868947fa32242c0a699ca98d73f31b7231..63b0aa64bd3d8dca8029397c0393b7e5cb5c76f0 100644 (file)
@@ -1786,6 +1786,8 @@ pub fn LLVMRustCoverageWriteMappingToBuffer(
         BufferOut: &RustString,
     );
 
+    pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
+    -> &'a Value;
     pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64;
 
     #[allow(improper_ctypes)]
index b631c10334cd13954e95e0885e1dca2d74c52a7c..f0b50459837e93d3bb8793ad0800e64144e69f29 100644 (file)
@@ -73,7 +73,8 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
                 llvm_c_strs.push(s);
             }
         };
-        add("rustc", true); // fake program name
+        // Set the llvm "program name" to make usage and invalid argument messages more clear.
+        add("rustc -Cllvm-args=\"...\" with", true);
         if sess.time_llvm_passes() {
             add("-time-passes", false);
         }
index 8fa0de37648f3649ec68f15a2068804b2c1b52f6..ff9dac372ab956911fd6fcf3124318ef4af12f38 100644 (file)
@@ -33,5 +33,6 @@ rustc_fs_util = { path = "../librustc_fs_util" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_target = { path = "../librustc_target" }
 rustc_session = { path = "../librustc_session" }
index d725a60118e3c794e5324262c9cea920aa052431..bfcf979d1254865292d66958bcb165a9635f4719 100644 (file)
@@ -769,9 +769,22 @@ fn escape_string(s: &[u8]) -> String {
 }
 
 fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
-    if crate_type != CrateType::Executable {
+    // 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
+    // executables only.
+    let needs_runtime = match crate_type {
+        CrateType::Executable => true,
+        CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
+            sess.target.target.options.is_like_osx
+        }
+        CrateType::Rlib | CrateType::Staticlib => false,
+    };
+
+    if !needs_runtime {
         return;
     }
+
     let sanitizer = sess.opts.debugging_opts.sanitizer;
     if sanitizer.contains(SanitizerSet::ADDRESS) {
         link_sanitizer_runtime(sess, linker, "asan");
@@ -809,6 +822,7 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
         "aarch64-fuchsia"
         | "aarch64-unknown-linux-gnu"
         | "x86_64-fuchsia"
+        | "x86_64-unknown-freebsd"
         | "x86_64-unknown-linux-gnu" => {
             let filename = format!("librustc{}_rt.{}.a", channel, name);
             let path = default_tlib.join(&filename);
index f9a782af24cda7c74b3cb725e69fecd296669db8..5100ef8ad4fd7cb5ab7590c6284c19c0bc59debd 100644 (file)
@@ -35,7 +35,7 @@ pub fn disable_localization(linker: &mut Command) {
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 pub struct LinkerInfo {
     exports: FxHashMap<CrateType, Vec<String>>,
 }
index 7d742e7a7afd2b35a613fb20f1b9569f2133507b..51cc1ada432dc7bf9b47c29bf4086db92a5544be 100644 (file)
@@ -61,7 +61,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
     let mut reachable_non_generics: DefIdMap<_> = tcx
         .reachable_set(LOCAL_CRATE)
         .iter()
-        .filter_map(|&hir_id| {
+        .filter_map(|&def_id| {
             // We want to ignore some FFI functions that are not exposed from
             // this crate. Reachable FFI functions can be lumped into two
             // categories:
@@ -75,9 +75,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
             //
             // As a result, if this id is an FFI item (foreign item) then we only
             // let it through if it's included statically.
-            match tcx.hir().get(hir_id) {
+            match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
                 Node::ForeignItem(..) => {
-                    let def_id = tcx.hir().local_def_id(hir_id);
                     tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
                 }
 
@@ -87,7 +86,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
                     ..
                 })
                 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
-                    let def_id = tcx.hir().local_def_id(hir_id);
                     let generics = tcx.generics_of(def_id);
                     if !generics.requires_monomorphization(tcx)
                         // Functions marked with #[inline] are codegened with "internal"
@@ -190,7 +188,9 @@ fn exported_symbols_provider_local(
         }
     }
 
-    if tcx.sess.opts.cg.profile_generate.enabled() {
+    if tcx.sess.opts.debugging_opts.instrument_coverage
+        || tcx.sess.opts.cg.profile_generate.enabled()
+    {
         // These are weak symbols that point to the profile version and the
         // profile name, which need to be treated as exported so LTO doesn't nix
         // them.
@@ -203,17 +203,6 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if tcx.sess.opts.debugging_opts.instrument_coverage {
-        // Similar to PGO profiling, preserve symbols used by LLVM InstrProf coverage profiling.
-        const COVERAGE_WEAK_SYMBOLS: [&str; 3] =
-            ["__llvm_profile_filename", "__llvm_coverage_mapping", "__llvm_covmap"];
-
-        symbols.extend(COVERAGE_WEAK_SYMBOLS.iter().map(|sym| {
-            let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
-            (exported_symbol, SymbolExportLevel::C)
-        }));
-    }
-
     if tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY) {
         // Similar to profiling, preserve weak msan symbol during LTO.
         const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
@@ -370,7 +359,7 @@ fn upstream_drop_glue_for_provider<'tcx>(
 
 fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if let Some(def_id) = def_id.as_local() {
-        !tcx.reachable_set(LOCAL_CRATE).contains(&tcx.hir().as_local_hir_id(def_id))
+        !tcx.reachable_set(LOCAL_CRATE).contains(&def_id)
     } else {
         bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
     }
index 85260d30a3d7c36292b30580c427e8d392df94ba..6bfbda0f1d7f29d1c21ff75c8e610ee5e1cf8303 100644 (file)
@@ -16,6 +16,8 @@
 //! The backend-agnostic functions of this crate use functions defined in various traits that
 //! have to be implemented by each backends.
 
+#[macro_use]
+extern crate rustc_macros;
 #[macro_use]
 extern crate log;
 #[macro_use]
@@ -74,7 +76,7 @@ pub fn into_compiled_module(
     }
 }
 
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
 pub struct CompiledModule {
     pub name: String,
     pub kind: ModuleKind,
@@ -87,7 +89,7 @@ pub struct CachedModuleCodegen {
     pub source: WorkProduct,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)]
 pub enum ModuleKind {
     Regular,
     Metadata,
@@ -110,7 +112,7 @@ pub struct MemFlags: u8 {
 /// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
 /// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
 /// and the corresponding properties without referencing information outside of a `CrateInfo`.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
@@ -128,7 +130,7 @@ pub struct CrateInfo {
     pub dependency_formats: Lrc<Dependencies>,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 pub struct CodegenResults {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
index d166a27b5a982784e8f4c2083725e787b0916ee4..d8a530d98faa7df9f0228b1b11a10af891e030c1 100644 (file)
@@ -1,6 +1,7 @@
 use crate::traits::*;
 use rustc_hir::def_id::CrateNum;
 use rustc_index::vec::IndexVec;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
 use rustc_session::config::DebugInfo;
@@ -216,6 +217,13 @@ pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
             LocalRef::Operand(None) => return,
 
             LocalRef::Operand(Some(operand)) => {
+                // Don't spill operands onto the stack in naked functions.
+                // See: https://github.com/rust-lang/rust/issues/42779
+                let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
+                if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+                    return;
+                }
+
                 // "Spill" the value onto the stack, for debuginfo,
                 // without forcing non-debuginfo uses of the local
                 // to also load from the stack every single time.
index 2b5878f46bc43bfc7540b45468f6657e5c7e07ee..5602599b0c25b579aaaef4fb560344444dd7504f 100644 (file)
@@ -7,6 +7,8 @@ pub trait CoverageInfoMethods: BackendTypes {
 }
 
 pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
+    fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value;
+
     fn add_counter_region(
         &mut self,
         instance: Instance<'tcx>,
index 36c32e600311252bfe5e4629951f747f824568c2..1926dbf06e726aa50e37a9b001d3873602bb0d47 100644 (file)
@@ -17,6 +17,7 @@ jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
 once_cell = { version = "1", features = ["parking_lot"] }
 rustc_serialize = { path = "../librustc_serialize" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_graphviz = { path = "../librustc_graphviz" }
 cfg-if = "0.1.2"
 crossbeam-utils = { version = "0.7", features = ["nightly"] }
index 282626611d50bd92bd0f2d08928ee97410330f2b..f8d631ce01e78139b7dd6c11abc9229a51b76813 100644 (file)
@@ -1,5 +1,8 @@
 use crate::stable_hasher;
-use rustc_serialize::opaque::{Decoder, EncodeResult, Encoder};
+use rustc_serialize::{
+    opaque::{self, EncodeResult},
+    Decodable, Encodable,
+};
 use std::mem;
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
@@ -49,14 +52,14 @@ pub fn to_hex(&self) -> String {
         format!("{:x}{:x}", self.0, self.1)
     }
 
-    pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
+    pub fn encode_opaque(&self, encoder: &mut opaque::Encoder) -> EncodeResult {
         let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
 
         encoder.emit_raw_bytes(&bytes);
         Ok(())
     }
 
-    pub fn decode_opaque(decoder: &mut Decoder<'_>) -> Result<Fingerprint, String> {
+    pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
         let mut bytes = [0; 16];
 
         decoder.read_raw_bytes(&mut bytes)?;
@@ -83,18 +86,45 @@ fn finish(hasher: stable_hasher::StableHasher) -> Self {
 
 impl_stable_hash_via_hash!(Fingerprint);
 
-impl rustc_serialize::UseSpecializedEncodable for Fingerprint {}
+impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        s.encode_fingerprint(self)
+    }
+}
 
-impl rustc_serialize::UseSpecializedDecodable for Fingerprint {}
+impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
+        d.decode_fingerprint()
+    }
+}
 
-impl rustc_serialize::SpecializedEncoder<Fingerprint> for Encoder {
-    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+pub trait FingerprintEncoder: rustc_serialize::Encoder {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>;
+}
+
+pub trait FingerprintDecoder: rustc_serialize::Decoder {
+    fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error>;
+}
+
+impl<E: rustc_serialize::Encoder> FingerprintEncoder for E {
+    default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> {
+        panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::<E>());
+    }
+}
+
+impl FingerprintEncoder for opaque::Encoder {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
         f.encode_opaque(self)
     }
 }
 
-impl<'a> rustc_serialize::SpecializedDecoder<Fingerprint> for Decoder<'a> {
-    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
+    default fn decode_fingerprint(&mut self) -> Result<Fingerprint, D::Error> {
+        panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>());
+    }
+}
+impl FingerprintDecoder for opaque::Decoder<'_> {
+    fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
         Fingerprint::decode_opaque(self)
     }
 }
index 3884fc051056edff3bbbee3da634077916797320..017511cc50d20fd1498ea16a208e2e76f17d91d8 100644 (file)
@@ -29,6 +29,8 @@
 extern crate log;
 #[macro_use]
 extern crate cfg_if;
+#[macro_use]
+extern crate rustc_macros;
 
 #[inline(never)]
 #[cold]
index 652268dcee8842847167f78daec1cfe8ddbffa87..856eb73e6297a79ac5cc48051fb241080baab0c9 100644 (file)
 /// stores data in a more compact way. It also supports accessing contiguous
 /// ranges of elements as a slice, and slices of already sorted elements can be
 /// inserted efficiently.
-#[derive(
-    Clone,
-    PartialEq,
-    Eq,
-    PartialOrd,
-    Ord,
-    Hash,
-    Default,
-    Debug,
-    RustcEncodable,
-    RustcDecodable
-)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
 pub struct SortedMap<K: Ord, V> {
     data: Vec<(K, V)>,
 }
index 476eb9e14f98f34313346ba153f82ac620683a97..02103de2e8df913d15a8ca458cce1b3e4d7d39c8 100644 (file)
@@ -48,14 +48,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl Encodable for Svh {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for Svh {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u64(self.as_u64().to_le())
     }
 }
 
-impl Decodable for Svh {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Svh, D::Error> {
+impl<D: Decoder> Decodable<D> for Svh {
+    fn decode(d: &mut D) -> Result<Svh, D::Error> {
         d.read_u64().map(u64::from_le).map(Svh::new)
     }
 }
index 43002178eb9717478e23ca88a3ffad7647adda14..4d673fd5cf98307ddc40b1e96779a6cbabb5e819 100644 (file)
@@ -3,7 +3,7 @@
 /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
 /// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
 /// which uses only a single (null) pointer.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
 pub struct ThinVec<T>(Option<Box<Vec<T>>>);
 
 impl<T> ThinVec<T> {
index 7d137a55033f7ac89ee6e3a038c3f78a1c451b5f..fe60a99dde07205f2b88c1d5a35c9c5df1d15292 100644 (file)
@@ -1,8 +1,6 @@
 use crate::fx::FxIndexSet;
-use crate::stable_hasher::{HashStable, StableHasher};
 use crate::sync::Lock;
 use rustc_index::bit_set::BitMatrix;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
@@ -42,10 +40,10 @@ fn default() -> Self {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
 struct Index(usize);
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 struct Edge {
     source: Index,
     target: Index,
@@ -402,66 +400,3 @@ fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix<usize, usize>) {
         candidates.truncate(j - dead);
     }
 }
-
-impl<T> Encodable for TransitiveRelation<T>
-where
-    T: Clone + Encodable + Debug + Eq + Hash + Clone,
-{
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct("TransitiveRelation", 2, |s| {
-            s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
-            s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
-            Ok(())
-        })
-    }
-}
-
-impl<T> Decodable for TransitiveRelation<T>
-where
-    T: Clone + Decodable + Debug + Eq + Hash + Clone,
-{
-    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
-        d.read_struct("TransitiveRelation", 2, |d| {
-            Ok(TransitiveRelation {
-                elements: d.read_struct_field("elements", 0, |d| Decodable::decode(d))?,
-                edges: d.read_struct_field("edges", 1, |d| Decodable::decode(d))?,
-                closure: Lock::new(None),
-            })
-        })
-    }
-}
-
-impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
-where
-    T: HashStable<CTX> + Eq + Debug + Clone + Hash,
-{
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        // We are assuming here that the relation graph has been built in a
-        // deterministic way and we can just hash it the way it is.
-        let TransitiveRelation {
-            ref elements,
-            ref edges,
-            // "closure" is just a copy of the data above
-            closure: _,
-        } = *self;
-
-        elements.hash_stable(hcx, hasher);
-        edges.hash_stable(hcx, hasher);
-    }
-}
-
-impl<CTX> HashStable<CTX> for Edge {
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        let Edge { ref source, ref target } = *self;
-
-        source.hash_stable(hcx, hasher);
-        target.hash_stable(hcx, hasher);
-    }
-}
-
-impl<CTX> HashStable<CTX> for Index {
-    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
-        let Index(idx) = *self;
-        idx.hash_stable(hcx, hasher);
-    }
-}
index 6474a69b216a91e98e784614b766752b485211ad..46331c63113f9e6925b2f442fc112515125dfe5b 100644 (file)
@@ -12,7 +12,7 @@ crate-type = ["dylib"]
 [dependencies]
 lazy_static = "1.0"
 libc = "0.2"
-log = { package = "tracing", version = "0.1.18", features = ["release_max_level_info"]  }
+tracing = { version = "0.1.18", features = ["release_max_level_info"]  }
 tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
index cc954cee9077d8df50e6cd1e52810f42506a15f5..cd94ccc7ad73c238a71b16b911101e492df747c1 100644 (file)
@@ -9,7 +9,7 @@
 #![recursion_limit = "256"]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate lazy_static;
 
@@ -348,8 +348,10 @@ pub fn run_compiler(
             queries.global_ctxt()?;
 
             // Drop AST after creating GlobalCtxt to free memory
-            let _timer = sess.prof.generic_activity("drop_ast");
-            mem::drop(queries.expansion()?.take());
+            {
+                let _timer = sess.prof.generic_activity("drop_ast");
+                mem::drop(queries.expansion()?.take());
+            }
 
             if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json {
                 return early_exit();
@@ -1224,13 +1226,13 @@ pub fn install_ice_hook() {
 }
 
 /// This allows tools to enable rust logging without having to magically match rustc's
-/// log crate version.
+/// tracing crate version.
 pub fn init_rustc_env_logger() {
     init_env_logger("RUSTC_LOG")
 }
 
 /// This allows tools to enable rust logging without having to magically match rustc's
-/// log crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
 /// other than `RUSTC_LOG`.
 pub fn init_env_logger(env: &str) {
     // Don't register a dispatcher if there's no filter to print anything
index 794456451ef33eeea41a0f1e71811b9122290e7e..9cfefb1de632ba96313a0a738d1b14c15e146c14 100644 (file)
@@ -37,8 +37,7 @@ fn i_want_static_closure<F>(a: F)
 
 fn print_string(s: Mutex<MyString<'static>>) {
 
-    i_want_static_closure(move || {     // error: this closure has lifetime 'a
-                                        //        rather than 'static
+    i_want_static_closure(move || {     // ok!
         println!("{}", s.lock().unwrap().data);
     });
 }
index 86945f83b55240a30af21ecd8c5460a666dbbb80..9736da80c2b7b178396f85e680e7ff358a15215c 100644 (file)
@@ -1,11 +1,19 @@
-`fn main()` or the specified start function is not allowed to be
-async. You might be seeing this error because your async runtime
-library is not set up correctly.
+The entry point of the program was marked as `async`.
 
 Erroneous code example:
 
 ```compile_fail,E0752
-async fn main() -> Result<i32, ()> {
-    Ok(1)
+async fn main() -> Result<(), ()> { // error!
+    Ok(())
+}
+```
+
+`fn main()` or the specified start function is not allowed to be `async`. Not
+having a correct async runtime library setup may cause this error. To fix it,
+declare the entry point without `async`:
+
+```
+fn main() -> Result<(), ()> { // ok!
+    Ok(())
 }
 ```
index d0f04c3fe7647187ade03a61f40bee27e06ec084..7c794bcd98f2c56d1c95f9848bc8d8dc29ab0879 100644 (file)
@@ -10,9 +10,10 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_span = { path = "../librustc_span" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 unicode-width = "0.1.4"
 atty = "0.2"
index acaa26c6ad2fc609b72adbc4c8f79761e3ab902e..cd4b5d56f36e6e7190a075aee564a8bc31e3ebb5 100644 (file)
@@ -9,7 +9,7 @@
 use std::fmt;
 
 #[must_use]
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
@@ -24,14 +24,14 @@ pub struct Diagnostic {
     pub sort_span: Span,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DiagnosticId {
     Error(String),
     Lint(String),
 }
 
 /// For example a note attached to an error.
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct SubDiagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
index 22bf8fe34aa155543c72fa41ad11d746ec1c8ee3..dc52e29fa9bb903fcdc4a3f3774d1bd25a6a8ea0 100644 (file)
@@ -1,11 +1,11 @@
 use crate::{Applicability, Handler, Level, StashKey};
 use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString};
 
-use log::debug;
 use rustc_span::{MultiSpan, Span};
 use std::fmt::{self, Debug};
 use std::ops::{Deref, DerefMut};
 use std::thread::panicking;
+use tracing::debug;
 
 /// Used for emitting structured error messages and other diagnostic information.
 ///
index cca8b47c78122a2cd319123e73e607b16c0bbb3d..5a654e83aed8e1408178006f34f60dd11b70a0fc 100644 (file)
@@ -18,7 +18,6 @@
     pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
 };
 
-use log::*;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -30,6 +29,7 @@
 use std::path::Path;
 use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream};
 use termcolor::{Buffer, Color, WriteColor};
+use tracing::*;
 
 /// Default column width, used in tests and when terminal dimensions cannot be determined.
 const DEFAULT_COLUMN_WIDTH: usize = 140;
index 24186198fd2b15b11c1d8ccd7e9b04b8347a6ebb..750d36d3d891a2804c116894187c1764c38a8dba 100644 (file)
@@ -145,7 +145,7 @@ fn should_show_explain(&self) -> bool {
 
 // The following data types are provided just for serialisation.
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct Diagnostic {
     /// The primary error message.
     message: String,
@@ -159,7 +159,7 @@ struct Diagnostic {
     rendered: Option<String>,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct DiagnosticSpan {
     file_name: String,
     byte_start: u32,
@@ -186,7 +186,7 @@ struct DiagnosticSpan {
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct DiagnosticSpanLine {
     text: String,
 
@@ -196,7 +196,7 @@ struct DiagnosticSpanLine {
     highlight_end: usize,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct DiagnosticSpanMacroExpansion {
     /// span where macro was applied to generate this code; note that
     /// this may itself derive from a macro (if
@@ -210,7 +210,7 @@ struct DiagnosticSpanMacroExpansion {
     def_site_span: DiagnosticSpan,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct DiagnosticCode {
     /// The code itself.
     code: String,
@@ -218,7 +218,7 @@ struct DiagnosticCode {
     explanation: Option<&'static str>,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct ArtifactNotification<'a> {
     /// The path of the artifact.
     artifact: &'a Path,
index dcfcdbc63f29f95650d0cd2392dbab94fbf61a4e..e69e868c8ede5fa413a3588540e81f13ee47a94e 100644 (file)
 
 use std::str;
 
-#[derive(RustcDecodable, Debug, PartialEq, Eq)]
+#[derive(Decodable, Debug, PartialEq, Eq)]
 struct TestData {
     spans: Vec<SpanTestData>,
 }
 
-#[derive(RustcDecodable, Debug, PartialEq, Eq)]
+#[derive(Decodable, Debug, PartialEq, Eq)]
 struct SpanTestData {
     pub byte_start: u32,
     pub byte_end: u32,
index 73d71063b23620931cd13ac56ea15e0c8b8e6df9..d4f0a9d83ef4e2364e8d570835b05dab921205a7 100644 (file)
@@ -6,9 +6,12 @@
 #![feature(crate_visibility_modifier)]
 #![feature(nll)]
 
+#[macro_use]
+extern crate rustc_macros;
+
 pub use emitter::ColorConfig;
 
-use log::debug;
+use tracing::debug;
 use Level::*;
 
 use emitter::{is_case_difference, Emitter, EmitterWriter};
@@ -50,7 +53,7 @@
 /// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion
 /// to determine whether it should be automatically applied or if the user should be consulted
 /// before applying the suggestion.
-#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub enum Applicability {
     /// The suggestion is definitely what the user intended. This suggestion should be
     /// automatically applied.
@@ -69,7 +72,7 @@ pub enum Applicability {
     Unspecified,
 }
 
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
 pub enum SuggestionStyle {
     /// Hide the suggested code when displaying this suggestion inline.
     HideCodeInline,
@@ -94,7 +97,7 @@ fn hide_inline(&self) -> bool {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct CodeSuggestion {
     /// Each substitute can have multiple variants due to multiple
     /// applicable suggestions
@@ -129,13 +132,13 @@ pub struct CodeSuggestion {
     pub applicability: Applicability,
 }
 
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 /// See the docs on `CodeSuggestion::substitutions`
 pub struct Substitution {
     pub parts: Vec<SubstitutionPart>,
 }
 
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub struct SubstitutionPart {
     pub span: Span,
     pub snippet: String,
@@ -943,7 +946,7 @@ fn panic_if_treat_err_as_bug(&self) {
     }
 }
 
-#[derive(Copy, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, PartialEq, Clone, Hash, Debug, Encodable, Decodable)]
 pub enum Level {
     Bug,
     Fatal,
@@ -1012,7 +1015,7 @@ macro_rules! pluralize {
 
 // Useful type to use with `Result<>` indicate that an error has already
 // been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, Hash, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
 pub struct ErrorReported;
 
 rustc_data_structures::impl_stable_hash_via_hash!(ErrorReported);
index 0660590a72570b040602d2b14acd21472b4832cd..160bf57779970a58ab0b6369a5736534c634c5e4 100644 (file)
@@ -173,7 +173,7 @@ pub struct StyledString {
     pub style: Style,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub enum Style {
     MainHeaderMsg,
     HeaderMsg,
index bdf039c36abf6c60e610a1f56db80cfeaac0b9f6..55a1862971b677cb4798ce4678e7cfd2c5d3001f 100644 (file)
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 rustc_serialize = { path = "../librustc_serialize" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_span = { path = "../librustc_span" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_ast_passes = { path = "../librustc_ast_passes" }
@@ -20,6 +20,7 @@ rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_session = { path = "../librustc_session" }
index 1e3ab2c5ec2db36ea8d5f890dac75952b8dc5f90..7f631cb71afa86b9ff56b04acc2aadccb5c1854f 100644 (file)
@@ -8,6 +8,9 @@
 #![feature(proc_macro_span)]
 #![feature(try_blocks)]
 
+#[macro_use]
+extern crate rustc_macros;
+
 extern crate proc_macro as pm;
 
 mod placeholders;
index 6f2daaa81c02f5a6b1bd9669539afbce2d7edb83..9920e0650a7f7a1742b2c3c9a30854bb0daec8e5 100644 (file)
@@ -19,7 +19,7 @@
 
 /// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note
 /// that the delimiter itself might be `NoDelim`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
 struct Delimited {
     delim: token::DelimToken,
     tts: Vec<TokenTree>,
@@ -37,7 +37,7 @@ fn close_tt(&self, span: DelimSpan) -> TokenTree {
     }
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
 struct SequenceRepetition {
     /// The sequence of token trees
     tts: Vec<TokenTree>,
@@ -49,7 +49,7 @@ struct SequenceRepetition {
     num_captures: usize,
 }
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 struct KleeneToken {
     span: Span,
     op: KleeneOp,
@@ -63,7 +63,7 @@ fn new(op: KleeneOp, span: Span) -> KleeneToken {
 
 /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
 /// for token sequences.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
 enum KleeneOp {
     /// Kleene star (`*`) for zero or more repetitions
     ZeroOrMore,
@@ -75,7 +75,7 @@ enum KleeneOp {
 
 /// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)`
 /// are "first-class" token trees. Useful for parsing macros.
-#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
 enum TokenTree {
     Token(Token),
     Delimited(DelimSpan, Lrc<Delimited>),
index 15b2c14a2576c44ccd76af165dae3d34d3cada6f..808d77842cb22caa30240835de41909cde480801 100644 (file)
 use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent};
 use rustc_span::Span;
 
-use log::debug;
 use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use std::{mem, slice};
+use tracing::debug;
 
 crate struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
index 4a404e176e148de43a4c580a186901d794064a9b..a473a8edcdd5d6d4abe02074c8950d63a1ccdd62 100644 (file)
@@ -18,5 +18,5 @@ rustc_span = { path = "../librustc_span" }
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_ast = { path = "../librustc_ast" }
 lazy_static = "1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
index f439db715310cc1ac204ffffd302786b81e53aaf..6ba396666070ab4fbca05381ee111235acf3549e 100644 (file)
@@ -12,41 +12,41 @@ macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
             // HIR types
-            [few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
-            [] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
-            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
-            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
-            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
-            [] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
-            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
-            [few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
-            [] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
-            [] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
-            [] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
-            [] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
-            [] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
-            [] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
-            [] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
-            [] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
-            [] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
-            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
-            [few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
-            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
-            [] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
-            [few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
-            [] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
-            [] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
-            [] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
-            [] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
-            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
-            [] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
-            [] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
-            [] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
-            [] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
-            [] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
-            [] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
-            [] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
-            [] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
+            [few] hir_krate: rustc_hir::Crate<$tcx>,
+            [] arm: rustc_hir::Arm<$tcx>,
+            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
+            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+            [] attribute: rustc_ast::ast::Attribute,
+            [] block: rustc_hir::Block<$tcx>,
+            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
+            [few] global_asm: rustc_hir::GlobalAsm,
+            [] generic_arg: rustc_hir::GenericArg<$tcx>,
+            [] generic_args: rustc_hir::GenericArgs<$tcx>,
+            [] generic_bound: rustc_hir::GenericBound<$tcx>,
+            [] generic_param: rustc_hir::GenericParam<$tcx>,
+            [] expr: rustc_hir::Expr<$tcx>,
+            [] field: rustc_hir::Field<$tcx>,
+            [] field_pat: rustc_hir::FieldPat<$tcx>,
+            [] fn_decl: rustc_hir::FnDecl<$tcx>,
+            [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+            [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
+            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
+            [] local: rustc_hir::Local<$tcx>,
+            [few] macro_def: rustc_hir::MacroDef<$tcx>,
+            [] param: rustc_hir::Param<$tcx>,
+            [] pat: rustc_hir::Pat<$tcx>,
+            [] path: rustc_hir::Path<$tcx>,
+            [] path_segment: rustc_hir::PathSegment<$tcx>,
+            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
+            [] qpath: rustc_hir::QPath<$tcx>,
+            [] stmt: rustc_hir::Stmt<$tcx>,
+            [] struct_field: rustc_hir::StructField<$tcx>,
+            [] trait_item_ref: rustc_hir::TraitItemRef,
+            [] ty: rustc_hir::Ty<$tcx>,
+            [] type_binding: rustc_hir::TypeBinding<$tcx>,
+            [] variant: rustc_hir::Variant<$tcx>,
+            [] where_predicate: rustc_hir::WherePredicate<$tcx>,
         ], $tcx);
     )
 }
index 618f3e99c3f04a3a38617585c1f33bd51e551f80..c4877be3f6415bb2c21b288e3327351805bdf0d6 100644 (file)
@@ -9,7 +9,7 @@
 use std::fmt::Debug;
 
 /// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum CtorOf {
     /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
@@ -18,7 +18,7 @@ pub enum CtorOf {
     Variant,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum CtorKind {
     /// Constructor function automatically created by a tuple struct/variant.
@@ -29,7 +29,7 @@ pub enum CtorKind {
     Fictive,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum NonMacroAttrKind {
     /// Single-segment attribute defined by the language (`#[inline]`)
@@ -42,7 +42,7 @@ pub enum NonMacroAttrKind {
     Registered,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum DefKind {
     // Type namespace
@@ -191,7 +191,7 @@ pub fn ns(&self) -> Option<Namespace> {
 }
 
 /// The resolution of a path or export.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum Res<Id = hir::HirId> {
     Def(DefKind, DefId),
index 79b70682739326b1ea18c4254e7cbc83fbade8d1..628fc93141114b63fb16ebeb8984f8b907445392 100644 (file)
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{sym, Symbol};
 
-use log::debug;
 use std::fmt::Write;
 use std::hash::Hash;
+use tracing::debug;
 
 /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
 /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
 /// stores the `DefIndex` of its parent.
 /// There is one `DefPathTable` for each crate.
-#[derive(Clone, Default, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Default, Decodable, Encodable)]
 pub struct DefPathTable {
     index_to_key: IndexVec<DefIndex, DefKey>,
     def_path_hashes: IndexVec<DefIndex, DefPathHash>,
@@ -92,7 +92,7 @@ pub struct Definitions {
 /// A unique identifier that we can use to lookup a definition
 /// precisely. It combines the index of the definition's parent (if
 /// any) with a `DisambiguatedDefPathData`.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
 pub struct DefKey {
     /// The parent path.
     pub parent: Option<DefIndex>,
@@ -143,13 +143,13 @@ fn root_parent_stable_hash(
 /// between them. This introduces some artificial ordering dependency
 /// but means that if you have, e.g., two impls for the same type in
 /// the same module, they do get distinct `DefId`s.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
 pub struct DisambiguatedDefPathData {
     pub data: DefPathData,
     pub disambiguator: u32,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
 pub struct DefPath {
     /// The path leading from the crate root to the item.
     pub data: Vec<DisambiguatedDefPathData>,
@@ -244,7 +244,7 @@ pub fn to_filename_friendly_no_crate(&self) -> String {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DefPathData {
     // Root: these should only be used for the root nodes, because
     // they are treated specially by the `def_path` function.
@@ -306,11 +306,6 @@ pub fn def_path(&self, id: LocalDefId) -> DefPath {
         })
     }
 
-    #[inline]
-    pub fn as_local_hir_id(&self, def_id: LocalDefId) -> hir::HirId {
-        self.local_def_id_to_hir_id(def_id)
-    }
-
     #[inline]
     pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
         self.def_id_to_hir_id[id].unwrap()
index 6474dc318d329f73854c2c0526b8f075589c7f0b..928235adac30c15685203a59fa7a696e958f35b7 100644 (file)
@@ -23,7 +23,7 @@
 use std::collections::{BTreeMap, BTreeSet};
 use std::fmt;
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, HashStable_Generic)]
 pub struct Lifetime {
     pub hir_id: HirId,
     pub span: Span,
@@ -37,7 +37,7 @@ pub struct Lifetime {
     pub name: LifetimeName,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
 #[derive(HashStable_Generic)]
 pub enum ParamName {
     /// Some user-given name like `T` or `'x`.
@@ -83,7 +83,7 @@ pub fn normalize_to_macros_2_0(&self) -> ParamName {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
 #[derive(HashStable_Generic)]
 pub enum LifetimeName {
     /// User-given names or fresh (synthetic) names.
@@ -182,7 +182,7 @@ pub fn is_static(&self) -> bool {
 /// A `Path` is essentially Rust's notion of a name; for instance,
 /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
 /// along with a bunch of supporting information.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Path<'hir> {
     pub span: Span,
     /// The resolution for the path.
@@ -199,7 +199,7 @@ pub fn is_global(&self) -> bool {
 
 /// A segment of a path: an identifier, an optional lifetime, and a set of
 /// types.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct PathSegment<'hir> {
     /// The identifier portion of this path segment.
     #[stable_hasher(project(name))]
@@ -242,13 +242,13 @@ pub fn generic_args(&self) -> &GenericArgs<'hir> {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub struct ConstArg {
     pub value: AnonConst,
     pub span: Span,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum GenericArg<'hir> {
     Lifetime(Lifetime),
     Type(Ty<'hir>),
@@ -288,7 +288,7 @@ pub fn descr(&self) -> &'static str {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct GenericArgs<'hir> {
     /// The generic arguments for this path segment.
     pub args: &'hir [GenericArg<'hir>],
@@ -348,7 +348,7 @@ pub fn own_counts(&self) -> GenericParamCount {
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
 /// modifier is `Maybe`. Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum TraitBoundModifier {
     None,
@@ -360,7 +360,7 @@ pub enum TraitBoundModifier {
 /// `typeck::collect::compute_bounds` matches these against
 /// the "special" built-in traits (see `middle::lang_items`) and
 /// detects `Copy`, `Send` and `Sync`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum GenericBound<'hir> {
     Trait(PolyTraitRef<'hir>, TraitBoundModifier),
     Outlives(Lifetime),
@@ -384,7 +384,7 @@ pub fn span(&self) -> Span {
 
 pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
 
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
 pub enum LifetimeParamKind {
     // Indicates that the lifetime definition was explicitly declared (e.g., in
     // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
@@ -403,7 +403,7 @@ pub enum LifetimeParamKind {
     Error,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum GenericParamKind<'hir> {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
     Lifetime {
@@ -418,7 +418,7 @@ pub enum GenericParamKind<'hir> {
     },
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct GenericParam<'hir> {
     pub hir_id: HirId,
     pub name: ParamName,
@@ -448,7 +448,7 @@ pub struct GenericParamCount {
 
 /// Represents lifetimes and type parameters attached to a declaration
 /// of a function, enum, trait, etc.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Generics<'hir> {
     pub params: &'hir [GenericParam<'hir>],
     pub where_clause: WhereClause<'hir>,
@@ -501,14 +501,14 @@ pub fn spans(&self) -> MultiSpan {
 
 /// Synthetic type parameters are converted to another form during lowering; this allows
 /// us to track the original form they had, and is useful for error messages.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum SyntheticTyParamKind {
     ImplTrait,
 }
 
 /// A where-clause in a definition.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct WhereClause<'hir> {
     pub predicates: &'hir [WherePredicate<'hir>],
     // Only valid if predicates aren't empty.
@@ -535,7 +535,7 @@ pub fn tail_span_for_suggestion(&self) -> Span {
 }
 
 /// A single predicate in a where-clause.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum WherePredicate<'hir> {
     /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
     BoundPredicate(WhereBoundPredicate<'hir>),
@@ -556,7 +556,7 @@ pub fn span(&self) -> Span {
 }
 
 /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct WhereBoundPredicate<'hir> {
     pub span: Span,
     /// Any generics from a `for` binding.
@@ -568,7 +568,7 @@ pub struct WhereBoundPredicate<'hir> {
 }
 
 /// A lifetime predicate (e.g., `'a: 'b + 'c`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct WhereRegionPredicate<'hir> {
     pub span: Span,
     pub lifetime: Lifetime,
@@ -576,7 +576,7 @@ pub struct WhereRegionPredicate<'hir> {
 }
 
 /// An equality predicate (e.g., `T = int`); currently unsupported.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct WhereEqPredicate<'hir> {
     pub hir_id: HirId,
     pub span: Span,
@@ -584,7 +584,7 @@ pub struct WhereEqPredicate<'hir> {
     pub rhs_ty: &'hir Ty<'hir>,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub struct ModuleItems {
     // Use BTreeSets here so items are in the same order as in the
     // list of all items in Crate
@@ -594,7 +594,7 @@ pub struct ModuleItems {
 }
 
 /// A type representing only the top-level module.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub struct CrateItem<'hir> {
     pub module: Mod<'hir>,
     pub attrs: &'hir [Attribute],
@@ -607,7 +607,7 @@ pub struct CrateItem<'hir> {
 /// For more details, see the [rustc dev guide].
 ///
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub struct Crate<'hir> {
     pub item: CrateItem<'hir>,
     pub exported_macros: &'hir [MacroDef<'hir>],
@@ -715,7 +715,7 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
 /// A macro definition, in this crate or imported from another.
 ///
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct MacroDef<'hir> {
     pub ident: Ident,
     pub vis: Visibility<'hir>,
@@ -728,7 +728,7 @@ pub struct MacroDef<'hir> {
 /// A block of statements `{ .. }`, which may have a label (in this case the
 /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
 /// the `rules` being anything but `DefaultBlock`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Block<'hir> {
     /// Statements in a block.
     pub stmts: &'hir [Stmt<'hir>],
@@ -746,7 +746,7 @@ pub struct Block<'hir> {
     pub targeted_by_break: bool,
 }
 
-#[derive(Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Pat<'hir> {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -824,7 +824,7 @@ pub fn walk_always(&self, mut it: impl FnMut(&Pat<'_>)) {
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
 /// are treated the same as` x: x, y: ref y, z: ref mut z`,
 /// except `is_shorthand` is true.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct FieldPat<'hir> {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -840,7 +840,7 @@ pub struct FieldPat<'hir> {
 /// Explicit binding annotations given in the HIR for a binding. Note
 /// that this is not the final binding *mode* that we infer after type
 /// inference.
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum BindingAnnotation {
     /// No binding annotation given: this means that the final binding mode
     /// will depend on whether we have skipped through a `&` reference
@@ -861,7 +861,7 @@ pub enum BindingAnnotation {
     RefMut,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum RangeEnd {
     Included,
     Excluded,
@@ -876,7 +876,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum PatKind<'hir> {
     /// Represents a wildcard pattern (i.e., `_`).
     Wild,
@@ -932,7 +932,7 @@ pub enum PatKind<'hir> {
     Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum BinOpKind {
     /// The `+` operator (addition).
     Add,
@@ -1066,7 +1066,7 @@ fn into(self) -> ast::BinOpKind {
 
 pub type BinOp = Spanned<BinOpKind>;
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum UnOp {
     /// The `*` operator (deferencing).
     UnDeref,
@@ -1095,7 +1095,7 @@ pub fn is_by_value(self) -> bool {
 }
 
 /// A statement.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Stmt<'hir> {
     pub hir_id: HirId,
     pub kind: StmtKind<'hir>,
@@ -1103,7 +1103,7 @@ pub struct Stmt<'hir> {
 }
 
 /// The contents of a statement.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum StmtKind<'hir> {
     /// A local (`let`) binding.
     Local(&'hir Local<'hir>),
@@ -1129,7 +1129,7 @@ pub fn attrs(&self) -> &'hir [Attribute] {
 }
 
 /// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Local<'hir> {
     pub pat: &'hir Pat<'hir>,
     /// Type annotation, if any (otherwise the type will be inferred).
@@ -1146,7 +1146,7 @@ pub struct Local<'hir> {
 
 /// Represents a single arm of a `match` expression, e.g.
 /// `<pat> (if <guard>) => <body>`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Arm<'hir> {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -1160,12 +1160,12 @@ pub struct Arm<'hir> {
     pub body: &'hir Expr<'hir>,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum Guard<'hir> {
     If(&'hir Expr<'hir>),
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Field<'hir> {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -1175,7 +1175,7 @@ pub struct Field<'hir> {
     pub is_shorthand: bool,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
@@ -1183,13 +1183,13 @@ pub enum BlockCheckMode {
     PopUnsafeBlock(UnsafeSource),
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum UnsafeSource {
     CompilerGenerated,
     UserProvided,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)]
 pub struct BodyId {
     pub hir_id: HirId,
 }
@@ -1215,7 +1215,7 @@ pub struct BodyId {
 ///
 /// All bodies have an **owner**, which can be accessed via the HIR
 /// map using `body_owner_def_id()`.
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub struct Body<'hir> {
     pub params: &'hir [Param<'hir>],
     pub value: Expr<'hir>,
@@ -1233,7 +1233,7 @@ pub fn generator_kind(&self) -> Option<GeneratorKind> {
 }
 
 /// The type of source expression that caused this generator to be created.
-#[derive(Clone, PartialEq, Eq, HashStable_Generic, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
 pub enum GeneratorKind {
     /// An explicit `async` block or the body of an async function.
     Async(AsyncGeneratorKind),
@@ -1256,7 +1256,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///
 /// This helps error messages but is also used to drive coercions in
 /// type-checking (see #60424).
-#[derive(Clone, PartialEq, Eq, HashStable_Generic, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
 pub enum AsyncGeneratorKind {
     /// An explicit `async` block written by the user.
     Block,
@@ -1357,14 +1357,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// These are usually found nested inside types (e.g., array lengths)
 /// or expressions (e.g., repeat counts), and also used to define
 /// explicit discriminant values for enum variants.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
 pub struct AnonConst {
     pub hir_id: HirId,
     pub body: BodyId,
 }
 
 /// An expression.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug)]
 pub struct Expr<'hir> {
     pub hir_id: HirId,
     pub kind: ExprKind<'hir>,
@@ -1543,7 +1543,7 @@ fn is_lit(sm: &SourceMap, span: &Span) -> bool {
     false
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum ExprKind<'hir> {
     /// A `box x` expression.
     Box(&'hir Expr<'hir>),
@@ -1660,7 +1660,7 @@ pub enum ExprKind<'hir> {
 /// To resolve the path to a `DefId`, call [`qpath_res`].
 ///
 /// [`qpath_res`]: ../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum QPath<'hir> {
     /// Path to a definition, optionally "fully-qualified" with a `Self`
     /// type, if the path points to an associated item in a trait.
@@ -1680,7 +1680,7 @@ pub enum QPath<'hir> {
 }
 
 /// Hints at the original code for a let statement.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
 pub enum LocalSource {
     /// A `match _ { .. }`.
     Normal,
@@ -1702,7 +1702,7 @@ pub enum LocalSource {
 }
 
 /// Hints at the original code for a `match _ { .. }`.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum MatchSource {
     /// A `match _ { .. }`.
@@ -1739,7 +1739,7 @@ pub fn name(self) -> &'static str {
 }
 
 /// The loop type that yielded an `ExprKind::Loop`.
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum LoopSource {
     /// A `loop { .. }` loop.
     Loop,
@@ -1761,7 +1761,7 @@ pub fn name(self) -> &'static str {
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
 pub enum LoopIdError {
     OutsideLoopScope,
     UnlabeledCfInWhileCondition,
@@ -1780,7 +1780,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
 pub struct Destination {
     // This is `Some(_)` iff there is an explicit user-specified `label
     pub label: Option<Label>,
@@ -1791,7 +1791,7 @@ pub struct Destination {
 }
 
 /// The yield kind that caused an `ExprKind::Yield`.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum YieldSource {
     /// An `<expr>.await`.
     Await { expr: Option<HirId> },
@@ -1829,7 +1829,7 @@ fn from(kind: GeneratorKind) -> Self {
 
 // N.B., if you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct MutTy<'hir> {
     pub ty: &'hir Ty<'hir>,
     pub mutbl: Mutability,
@@ -1837,7 +1837,7 @@ pub struct MutTy<'hir> {
 
 /// Represents a function's signature in a trait declaration,
 /// trait implementation, or a free function.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct FnSig<'hir> {
     pub header: FnHeader,
     pub decl: &'hir FnDecl<'hir>,
@@ -1846,7 +1846,7 @@ pub struct FnSig<'hir> {
 // The bodies for items are stored "out of line", in a separate
 // hashmap in the `Crate`. Here we just record the node-id of the item
 // so it can fetched later.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct TraitItemId {
     pub hir_id: HirId,
 }
@@ -1855,7 +1855,7 @@ pub struct TraitItemId {
 /// possibly including a default implementation. A trait item is
 /// either required (meaning it doesn't have an implementation, just a
 /// signature) or provided (meaning it has a default implementation).
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub struct TraitItem<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -1866,7 +1866,7 @@ pub struct TraitItem<'hir> {
 }
 
 /// Represents a trait method's body (or just argument names).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub enum TraitFn<'hir> {
     /// No default body in the trait, just a signature.
     Required(&'hir [Ident]),
@@ -1876,7 +1876,7 @@ pub enum TraitFn<'hir> {
 }
 
 /// Represents a trait method or associated constant or type
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum TraitItemKind<'hir> {
     /// An associated constant with an optional value (otherwise `impl`s must contain a value).
     Const(&'hir Ty<'hir>, Option<BodyId>),
@@ -1890,13 +1890,13 @@ pub enum TraitItemKind<'hir> {
 // The bodies for items are stored "out of line", in a separate
 // hashmap in the `Crate`. Here we just record the node-id of the item
 // so it can fetched later.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
 pub struct ImplItemId {
     pub hir_id: HirId,
 }
 
 /// Represents anything within an `impl` block.
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub struct ImplItem<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -1909,7 +1909,7 @@ pub struct ImplItem<'hir> {
 }
 
 /// Represents various kinds of content within an `impl`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum ImplItemKind<'hir> {
     /// An associated constant of the given type, set to the constant result
     /// of the expression.
@@ -1947,7 +1947,7 @@ pub fn namespace(&self) -> Namespace {
 ///    Binding(...),
 /// }
 /// ```
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct TypeBinding<'hir> {
     pub hir_id: HirId,
     #[stable_hasher(project(name))]
@@ -1957,7 +1957,7 @@ pub struct TypeBinding<'hir> {
 }
 
 // Represents the two kinds of type bindings.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum TypeBindingKind<'hir> {
     /// E.g., `Foo<Bar: Send>`.
     Constraint { bounds: &'hir [GenericBound<'hir>] },
@@ -1974,7 +1974,7 @@ pub fn ty(&self) -> &Ty<'_> {
     }
 }
 
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug)]
 pub struct Ty<'hir> {
     pub hir_id: HirId,
     pub kind: TyKind<'hir>,
@@ -1982,7 +1982,7 @@ pub struct Ty<'hir> {
 }
 
 /// Not represented directly in the AST; referred to by name through a `ty_path`.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum PrimTy {
     Int(IntTy),
@@ -1993,7 +1993,7 @@ pub enum PrimTy {
     Char,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct BareFnTy<'hir> {
     pub unsafety: Unsafety,
     pub abi: Abi,
@@ -2002,7 +2002,7 @@ pub struct BareFnTy<'hir> {
     pub param_names: &'hir [Ident],
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct OpaqueTy<'hir> {
     pub generics: Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
@@ -2011,7 +2011,7 @@ pub struct OpaqueTy<'hir> {
 }
 
 /// From whence the opaque type came.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum OpaqueTyOrigin {
     /// `-> impl Trait`
     FnReturn,
@@ -2024,7 +2024,7 @@ pub enum OpaqueTyOrigin {
 }
 
 /// The various kinds of types recognized by the compiler.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum TyKind<'hir> {
     /// A variable length slice (i.e., `[T]`).
     Slice(&'hir Ty<'hir>),
@@ -2063,7 +2063,7 @@ pub enum TyKind<'hir> {
     Err,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum InlineAsmOperand<'hir> {
     In {
         reg: InlineAsmRegOrRegClass,
@@ -2105,7 +2105,7 @@ pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct InlineAsm<'hir> {
     pub template: &'hir [InlineAsmTemplatePiece],
     pub operands: &'hir [InlineAsmOperand<'hir>],
@@ -2113,7 +2113,7 @@ pub struct InlineAsm<'hir> {
     pub line_spans: &'hir [Span],
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
 pub struct LlvmInlineAsmOutput {
     pub constraint: Symbol,
     pub is_rw: bool,
@@ -2122,8 +2122,9 @@ pub struct LlvmInlineAsmOutput {
 }
 
 // NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
-// it needs to be `Clone` and use plain `Vec<T>` instead of arena-allocated slice.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
+// it needs to be `Clone` and `Decodable` and use plain `Vec<T>` instead of
+// arena-allocated slice.
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
 pub struct LlvmInlineAsmInner {
     pub asm: Symbol,
     pub asm_str_style: StrStyle,
@@ -2135,7 +2136,7 @@ pub struct LlvmInlineAsmInner {
     pub dialect: LlvmAsmDialect,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct LlvmInlineAsm<'hir> {
     pub inner: LlvmInlineAsmInner,
     pub outputs_exprs: &'hir [Expr<'hir>],
@@ -2143,7 +2144,7 @@ pub struct LlvmInlineAsm<'hir> {
 }
 
 /// Represents a parameter in a function header.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Param<'hir> {
     pub attrs: &'hir [Attribute],
     pub hir_id: HirId,
@@ -2153,7 +2154,7 @@ pub struct Param<'hir> {
 }
 
 /// Represents the header (not the body) of a function declaration.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct FnDecl<'hir> {
     /// The types of the function's parameters.
     ///
@@ -2166,7 +2167,7 @@ pub struct FnDecl<'hir> {
 }
 
 /// Represents what type of implicit self a function has, if any.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
 pub enum ImplicitSelfKind {
     /// Represents a `fn x(self);`.
     Imm,
@@ -2191,24 +2192,14 @@ pub fn has_implicit_self(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
 #[derive(HashStable_Generic)]
 pub enum IsAsync {
     Async,
     NotAsync,
 }
 
-#[derive(
-    Copy,
-    Clone,
-    PartialEq,
-    RustcEncodable,
-    RustcDecodable,
-    Debug,
-    HashStable_Generic,
-    Eq,
-    Hash
-)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum Defaultness {
     Default { has_value: bool },
     Final,
@@ -2234,7 +2225,7 @@ pub fn is_default(&self) -> bool {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum FnRetTy<'hir> {
     /// Return type is not specified.
     ///
@@ -2255,7 +2246,7 @@ pub fn span(&self) -> Span {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Encodable, Debug)]
 pub struct Mod<'hir> {
     /// A span from the first token past `{` to the last token until `}`.
     /// For `mod foo;`, the inner span ranges from the first token
@@ -2264,23 +2255,23 @@ pub struct Mod<'hir> {
     pub item_ids: &'hir [ItemId],
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct ForeignMod<'hir> {
     pub abi: Abi,
     pub items: &'hir [ForeignItem<'hir>],
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub struct GlobalAsm {
     pub asm: Symbol,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct EnumDef<'hir> {
     pub variants: &'hir [Variant<'hir>],
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct Variant<'hir> {
     /// Name of the variant.
     #[stable_hasher(project(name))]
@@ -2297,7 +2288,7 @@ pub struct Variant<'hir> {
     pub span: Span,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum UseKind {
     /// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
     /// Also produced for each element of a list `use`, e.g.
@@ -2319,7 +2310,7 @@ pub enum UseKind {
 /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
 /// trait being referred to but just a unique `HirId` that serves as a key
 /// within the resolution map.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct TraitRef<'hir> {
     pub path: &'hir Path<'hir>,
     // Don't hash the `ref_id`. It is tracked via the thing it is used to access.
@@ -2338,7 +2329,7 @@ pub fn trait_def_id(&self) -> Option<DefId> {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct PolyTraitRef<'hir> {
     /// The `'a` in `for<'a> Foo<&'a T>`.
     pub bound_generic_params: &'hir [GenericParam<'hir>],
@@ -2351,7 +2342,7 @@ pub struct PolyTraitRef<'hir> {
 
 pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
 
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub enum VisibilityKind<'hir> {
     Public,
     Crate(CrateSugar),
@@ -2384,7 +2375,7 @@ pub fn descr(&self) -> &'static str {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct StructField<'hir> {
     pub span: Span,
     #[stable_hasher(project(name))]
@@ -2404,7 +2395,7 @@ pub fn is_positional(&self) -> bool {
 }
 
 /// Fields and constructor IDs of enum variants and structs.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum VariantData<'hir> {
     /// A struct variant.
     ///
@@ -2441,7 +2432,7 @@ pub fn ctor_hir_id(&self) -> Option<HirId> {
 // The bodies for items are stored "out of line", in a separate
 // hashmap in the `Crate`. Here we just record the node-id of the item
 // so it can fetched later.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, Encodable, Debug)]
 pub struct ItemId {
     pub id: HirId,
 }
@@ -2449,7 +2440,7 @@ pub struct ItemId {
 /// An item
 ///
 /// The name might be a dummy name in case of anonymous items
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
 pub struct Item<'hir> {
     pub ident: Ident,
     pub hir_id: HirId,
@@ -2460,7 +2451,7 @@ pub struct Item<'hir> {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum Unsafety {
     Unsafe,
     Normal,
@@ -2485,13 +2476,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
 pub enum Constness {
     Const,
     NotConst,
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
     pub constness: Constness,
@@ -2508,7 +2499,7 @@ pub fn is_const(&self) -> bool {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum ItemKind<'hir> {
     /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
@@ -2590,7 +2581,7 @@ pub fn generics(&self) -> Option<&Generics<'_>> {
 /// type or method, and whether it is public). This allows other
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
 pub struct TraitItemRef {
     pub id: TraitItemId,
     #[stable_hasher(project(name))]
@@ -2606,7 +2597,7 @@ pub struct TraitItemRef {
 /// type or method, and whether it is public). This allows other
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct ImplItemRef<'hir> {
     pub id: ImplItemId,
     #[stable_hasher(project(name))]
@@ -2617,14 +2608,14 @@ pub struct ImplItemRef<'hir> {
     pub defaultness: Defaultness,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
 pub enum AssocItemKind {
     Const,
     Fn { has_self: bool },
     Type,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub struct ForeignItem<'hir> {
     #[stable_hasher(project(name))]
     pub ident: Ident,
@@ -2636,7 +2627,7 @@ pub struct ForeignItem<'hir> {
 }
 
 /// An item within an `extern` block.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
 pub enum ForeignItemKind<'hir> {
     /// A foreign function.
     Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>),
@@ -2647,7 +2638,7 @@ pub enum ForeignItemKind<'hir> {
 }
 
 /// A variable captured by a closure.
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
 pub struct Upvar {
     // First span where it is accessed (there can be multiple).
     pub span: Span,
@@ -2658,7 +2649,7 @@ pub struct Upvar {
 // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
 // has length > 0 if the trait is found through an chain of imports, starting with the
 // import/use statement in the scope where the trait is used.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
+#[derive(Encodable, Decodable, Clone, Debug)]
 pub struct TraitCandidate {
     pub def_id: DefId,
     pub import_ids: SmallVec<[LocalDefId; 1]>,
index d782c3dd70a2c53c139020cc4f5dc0f9c1c72b6e..fea850c12d9b0102d0423850ba384e6f50d6f3f4 100644 (file)
@@ -11,7 +11,8 @@
 /// the `local_id` part of the `HirId` changing, which is a very useful property in
 /// incremental compilation where we have to persist things through changes to
 /// the code base.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Encodable, Decodable)]
 pub struct HirId {
     pub owner: LocalDefId,
     pub local_id: ItemLocalId,
index 7f473a458481f853975d3bef708668b4442101ed..b09657bd9b4a41962e74de68678e5593f0df30cb 100644 (file)
@@ -45,7 +45,7 @@ macro_rules! language_item_table {
 
         enum_from_u32! {
             /// A representation of all the valid language items in Rust.
-            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
             pub enum LangItem {
                 $($variant,)*
             }
@@ -165,6 +165,7 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     BoolImplItem,                  sym::bool,               bool_impl,               Target::Impl;
     CharImplItem,                  sym::char,               char_impl,               Target::Impl;
     StrImplItem,                   sym::str,                str_impl,                Target::Impl;
+    ArrayImplItem,                 sym::array,              array_impl,              Target::Impl;
     SliceImplItem,                 sym::slice,              slice_impl,              Target::Impl;
     SliceU8ImplItem,               sym::slice_u8,           slice_u8_impl,           Target::Impl;
     StrAllocImplItem,              sym::str_alloc,          str_alloc_impl,          Target::Impl;
index 52131cb3d3d4cab03a12ae46f2ef769aaa9b93f0..a64565b20e7f48d30bf16b0f9a8f9e82776554de 100644 (file)
@@ -7,9 +7,11 @@
 #![feature(const_panic)]
 #![feature(in_band_lifetimes)]
 #![feature(or_patterns)]
-#![feature(min_specialization)]
 #![recursion_limit = "256"]
 
+#[macro_use]
+extern crate rustc_macros;
+
 #[macro_use]
 extern crate rustc_data_structures;
 
index 60a87078d63cfdad911cdced0cb076e3e8ed64f7..1f7e3725412a2b88be9bafae2777f759933fdec9 100644 (file)
@@ -11,13 +11,14 @@ doctest = false
 
 [dependencies]
 rustc_graphviz = { path = "../librustc_graphviz" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rand = "0.7"
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_ast = { path = "../librustc_ast" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_span = { path = "../librustc_span" }
 rustc_fs_util = { path = "../librustc_fs_util" }
 rustc_session = { path = "../librustc_session" }
index 7fd4b3c2554f36722a79198705dc89831a28da7e..ad18913805467fd071d0556281e288cb9c999085 100644 (file)
@@ -8,7 +8,7 @@
 #[macro_use]
 extern crate rustc_middle;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 
 mod assert_dep_graph;
 pub mod assert_module_sources;
index ea0fd4eb7ee737b96d29fd07d9d2d844ecfa782a..81e5410978d5df55b4afa6da578d71ba429bb321 100644 (file)
@@ -1,8 +1,9 @@
 //! The data that we will serialize and deserialize.
 
+use rustc_macros::{Decodable, Encodable};
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
 pub struct SerializedWorkProduct {
     /// node that produced the work-product
     pub id: WorkProductId,
index 00b23760182a229510d25480298bc0abd9ca292f..8aaf1cb9cbc58057037bafedcf082b5810fc2af1 100644 (file)
@@ -10,5 +10,6 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-rustc_serialize = { path = "../librustc_serialize" }
 arrayvec = "0.5.1"
+rustc_serialize = { path = "../librustc_serialize" }
+rustc_macros = { path = "../librustc_macros" }
index e4b7c24a24989b3e9adffb533740013db24f773d..c43d1a6830d1d8818887754f8b0b468d832eb2f5 100644 (file)
@@ -7,6 +7,8 @@
 use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Range, Shl};
 use std::slice;
 
+use rustc_macros::{Decodable, Encodable};
+
 #[cfg(test)]
 mod tests;
 
@@ -26,7 +28,7 @@
 /// will panic if the bitsets have differing domain sizes.
 ///
 /// [`GrowableBitSet`]: struct.GrowableBitSet.html
-#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Eq, PartialEq, Decodable, Encodable)]
 pub struct BitSet<T: Idx> {
     domain_size: usize,
     words: Vec<Word>,
@@ -700,7 +702,7 @@ pub fn contains(&self, elem: T) -> bool {
 ///
 /// All operations that involve a row and/or column index will panic if the
 /// index exceeds the relevant bound.
-#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Eq, PartialEq, Decodable, Encodable)]
 pub struct BitMatrix<R: Idx, C: Idx> {
     num_rows: usize,
     num_columns: usize,
@@ -1108,7 +1110,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range
 /// representable by `T` are considered set.
-#[derive(Copy, Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Copy, Clone, Eq, PartialEq, Decodable, Encodable)]
 pub struct FiniteBitSet<T: FiniteBitSetTy>(pub T);
 
 impl<T: FiniteBitSetTy> FiniteBitSet<T> {
index c5dedab979326ab6a6c2657c2db775e317de759c..2420f82c0418d57be4a3c916b34420f6886ec8fd 100644 (file)
@@ -320,14 +320,14 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
                    derive [$($derives:ident,)+]
                    $($tokens:tt)*) => (
         $crate::newtype_index!(
-            @derives      [$($derives,)+ RustcEncodable,]
+            @derives      [$($derives,)+]
             @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
-        $crate::newtype_index!(@decodable $type);
+        $crate::newtype_index!(@serializable $type);
     );
 
     // The case where no derives are added, but encodable is overridden. Don't
@@ -357,22 +357,27 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
      @debug_format [$debug_format:tt]
                    $($tokens:tt)*) => (
         $crate::newtype_index!(
-            @derives      [RustcEncodable,]
+            @derives      []
             @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
             @debug_format [$debug_format]
                           $($tokens)*);
-        $crate::newtype_index!(@decodable $type);
+        $crate::newtype_index!(@serializable $type);
     );
 
-    (@decodable $type:ident) => (
-        impl ::rustc_serialize::Decodable for $type {
-            fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
+    (@serializable $type:ident) => (
+        impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for $type {
+            fn decode(d: &mut D) -> Result<Self, D::Error> {
                 d.read_u32().map(Self::from_u32)
             }
         }
+        impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for $type {
+            fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+                e.emit_u32(self.private)
+            }
+        }
     );
 
     // Rewrite final without comma to one that includes comma
@@ -483,14 +488,20 @@ pub struct IndexVec<I: Idx, T> {
 // not the phantom data.
 unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
 
-impl<I: Idx, T: Encodable> Encodable for IndexVec<I, T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         Encodable::encode(&self.raw, s)
     }
 }
 
-impl<I: Idx, T: Decodable> Decodable for IndexVec<I, T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for &IndexVec<I, T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+        Encodable::encode(&self.raw, s)
+    }
+}
+
+impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
         Decodable::decode(d).map(|v| IndexVec { raw: v, _marker: PhantomData })
     }
 }
@@ -669,6 +680,17 @@ pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
         }
     }
 
+    /// Returns mutable references to three distinct elements or panics otherwise.
+    #[inline]
+    pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
+        let (ai, bi, ci) = (a.index(), b.index(), c.index());
+        assert!(ai != bi && bi != ci && ci != ai);
+        let len = self.raw.len();
+        assert!(ai < len && bi < len && ci < len);
+        let ptr = self.raw.as_mut_ptr();
+        unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
+    }
+
     pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
         IndexVec { raw: self.raw, _marker: PhantomData }
     }
index 9d56fa223a9cb83dbe558715efe5b7539c72dbf0..e1698d66323c382f3be101faa4aedfdaacff1a1e 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_graphviz = { path = "../librustc_graphviz" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
index 063246f79fe362ff41c69a637fcca09d3e32260d..2b2c42207e48b6b62117b10b0023ae53a3dfac0b 100644 (file)
@@ -144,7 +144,7 @@ fn msg_span_from_early_bound_and_free_regions(
     let sm = tcx.sess.source_map();
 
     let scope = region.free_region_binding_scope(tcx);
-    let node = tcx.hir().as_local_hir_id(scope.expect_local());
+    let node = tcx.hir().local_def_id_to_hir_id(scope.expect_local());
     let tag = match tcx.hir().find(node) {
         Some(Node::Block(_) | Node::Expr(_)) => "body",
         Some(Node::Item(it)) => item_scope_tag(&it),
@@ -1707,7 +1707,7 @@ pub fn construct_generic_bound_failure(
             .in_progress_typeck_results
             .map(|typeck_results| typeck_results.borrow().hir_owner)
             .map(|owner| {
-                let hir_id = hir.as_local_hir_id(owner);
+                let hir_id = hir.local_def_id_to_hir_id(owner);
                 let parent_id = hir.get_parent_item(hir_id);
                 (
                     // Parent item could be a `mod`, so we check the HIR before calling:
@@ -1733,7 +1733,7 @@ pub fn construct_generic_bound_failure(
                         // Get the `hir::Param` to verify whether it already has any bounds.
                         // We do this to avoid suggesting code that ends up as `T: 'a'b`,
                         // instead we suggest `T: 'a + 'b` in that case.
-                        let id = hir.as_local_hir_id(def_id);
+                        let id = hir.local_def_id_to_hir_id(def_id);
                         let mut has_bounds = false;
                         if let Node::GenericParam(param) = hir.get(id) {
                             has_bounds = !param.bounds.is_empty();
@@ -1786,7 +1786,10 @@ pub fn construct_generic_bound_failure(
             .and_then(|(_, g)| g.params.first())
             .and_then(|param| param.def_id.as_local())
             .map(|def_id| {
-                (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
+                (
+                    hir.span(hir.local_def_id_to_hir_id(def_id)).shrink_to_lo(),
+                    format!("{}, ", new_lt),
+                )
             });
 
         let labeled_user_string = match bound_kind {
index 20617bb8bd8fc2aa84cfffef9be05b2960e0c3d3..eb1521f0565767a22c0ef2fb6899b1e75409547d 100644 (file)
@@ -28,7 +28,7 @@ pub(super) fn find_anon_type(
         br: &ty::BoundRegion,
     ) -> Option<(&hir::Ty<'tcx>, &hir::FnDecl<'tcx>)> {
         if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
-            let hir_id = self.tcx().hir().as_local_hir_id(anon_reg.def_id);
+            let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
             let fndecl = match self.tcx().hir().get(hir_id) {
                 Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
                 | Node::TraitItem(&hir::TraitItem {
index 1ddf88c030660e318958322fbc9cb9bac06d93e3..788eabf296d7663c824544857c2c6d17db26a30e 100644 (file)
@@ -67,7 +67,8 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
         match assoc_item.kind {
             ty::AssocKind::Fn => {
                 let hir = self.tcx().hir();
-                if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| hir.as_local_hir_id(id))
+                if let Some(hir_id) =
+                    assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id))
                 {
                     if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
                         visitor.visit_fn_decl(decl);
index 28e9dd90cfd674531eafece5122db6f3410fa2f5..6e2d49f1ad792d4363f6dc150a51bdd08c1a67b7 100644 (file)
@@ -49,7 +49,7 @@ pub(super) fn find_param_with_region(
         };
 
         let hir = &self.tcx().hir();
-        let hir_id = hir.as_local_hir_id(id.as_local()?);
+        let hir_id = hir.local_def_id_to_hir_id(id.as_local()?);
         let body_id = hir.maybe_body_owned_by(hir_id)?;
         let body = hir.body(body_id);
         let owner_id = hir.body_owner(body_id);
index d975038b010b9dabdd320349117a621a5fc8ad49..ffe5fb172bea3ec4096a6e9d65e8a50414a46420 100644 (file)
@@ -7,17 +7,14 @@
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, Lift, Region, TyCtxt};
 
-/// Combines a `region::ScopeTree` (which governs relationships between
-/// scopes) and a `FreeRegionMap` (which governs relationships between
-/// free regions) to yield a complete relation between concrete
-/// regions.
+/// Combines a `FreeRegionMap` and a `TyCtxt`.
 ///
 /// This stuff is a bit convoluted and should be refactored, but as we
 /// transition to NLL, it'll all go away anyhow.
 pub struct RegionRelations<'a, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
 
-    /// The context used to fetch the region maps.
+    /// The context used for debug messages
     pub context: DefId,
 
     /// Free-region relationships.
@@ -34,7 +31,7 @@ pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default, HashStable)]
+#[derive(Clone, Debug, Default)]
 pub struct FreeRegionMap<'tcx> {
     // Stores the relation `a < b`, where `a` and `b` are regions.
     //
index bacb7fa153e43b1a0cca8d8f5272ec5c71d749f5..f135bde7f8337a0b12f488f5fd52ec2cfd583233 100644 (file)
@@ -33,7 +33,7 @@
 #[macro_use]
 extern crate rustc_data_structures;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
index 5c7edc10dd5c79a596893fba36eee084ab462e32..b9837c6ade9a7fd4fd677870c8dc2074eb5a005d 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 libc = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rayon = { version = "0.3.0", package = "rustc-rayon" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../librustc_ast" }
index 4dccf273dd90fc69f6b17a343222a7aa13323da9..122d6e3543cae6878ca530e6be05297ad399ff06 100644 (file)
@@ -198,7 +198,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
 }
 
 pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
-    log::trace!("run_compiler");
+    tracing::trace!("run_compiler");
     let stderr = config.stderr.take();
     util::setup_callbacks_and_run_in_thread_pool_with_globals(
         config.opts.edition,
index 701fca8e4b53488f80fcbc1184c1acaa8caa5201..daa7444fb9edbaaca80342d8dabfefab5f8a90b6 100644 (file)
@@ -2,7 +2,6 @@
 use crate::proc_macro_decls;
 use crate::util;
 
-use log::{info, warn};
 use once_cell::sync::Lazy;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self, ast, visit};
@@ -39,6 +38,7 @@
 use rustc_span::{FileName, RealFileName};
 use rustc_trait_selection::traits;
 use rustc_typeck as typeck;
+use tracing::{info, warn};
 
 use rustc_serialize::json;
 use tempfile::Builder as TempFileBuilder;
@@ -104,7 +104,7 @@ pub fn configure_and_expand(
     krate: ast::Crate,
     crate_name: &str,
 ) -> Result<(ast::Crate, BoxedResolver)> {
-    log::trace!("configure_and_expand");
+    tracing::trace!("configure_and_expand");
     // Currently, we ignore the name resolution data structures for the purposes of dependency
     // tracking. Instead we will run name resolution and include its output in the hash of each
     // item, much like we do for macro expansion. In other words, the hash reflects not just
@@ -229,7 +229,7 @@ fn configure_and_expand_inner<'a>(
     resolver_arenas: &'a ResolverArenas<'a>,
     metadata_loader: &'a MetadataLoaderDyn,
 ) -> Result<(ast::Crate, Resolver<'a>)> {
-    log::trace!("configure_and_expand_inner");
+    tracing::trace!("configure_and_expand_inner");
     pre_expansion_lint(sess, lint_store, &krate);
 
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
@@ -342,7 +342,7 @@ fn configure_and_expand_inner<'a>(
     });
 
     if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
-        log::debug!("replacing bodies with loop {{}}");
+        tracing::debug!("replacing bodies with loop {{}}");
         util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
     }
 
index d1a22c69ee0419656360495aef20f7114917765a..2f32737cca00a18dcbf835c9f7b315e9d4216c85 100644 (file)
@@ -168,7 +168,7 @@ pub fn crate_name(&self) -> Result<&Query<String>> {
     pub fn expansion(
         &self,
     ) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
-        log::trace!("expansion");
+        tracing::trace!("expansion");
         self.expansion.compute(|| {
             let crate_name = self.crate_name()?.peek().clone();
             let (krate, lint_store) = self.register_plugins()?.take();
index e403a60ff323b3b38e3b793bb3740a810e392d2e..36eaad16079b8cf4e9e5d3417b655536c768674b 100644 (file)
@@ -1,4 +1,3 @@
-use log::info;
 use rustc_ast::ast::{AttrVec, BlockCheckMode};
 use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
 use rustc_ast::ptr::P;
@@ -33,6 +32,7 @@
 use std::sync::{Arc, Mutex, Once};
 #[cfg(not(parallel_compiler))]
 use std::{panic, thread};
+use tracing::info;
 
 /// Adds `target_feature = "..."` cfgs for a variety of platform
 /// specific features (SSE, NEON etc.).
index 3ba1566023d2842a376971a4bdd4fef03abbcbc9..d779f15f19aab17d0cb171c782b4a6aa17ef03ad 100644 (file)
@@ -9,7 +9,7 @@ name = "rustc_lint"
 path = "lib.rs"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 unicode-security = "0.0.5"
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
index c42794e00b41e0c3426169af4d7c6d1ef346b243..3859d0f163ad5c52798eb35c2604ec8392289f96 100644 (file)
@@ -51,8 +51,8 @@
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
-use log::{debug, trace};
 use std::fmt::Write;
+use tracing::{debug, trace};
 
 // hardwired lints from librustc_middle
 pub use rustc_session::lint::builtin::*;
@@ -440,7 +440,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
                 // reported for missing docs.
                 let real_trait = trait_ref.path.res.def_id();
                 if let Some(def_id) = real_trait.as_local() {
-                    let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
+                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
                     if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) {
                         if let hir::VisibilityKind::Inherited = item.vis.node {
                             for impl_item_ref in items {
@@ -614,7 +614,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
             cx.tcx.for_each_impl(debug, |d| {
                 if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
                     if let Some(def_id) = ty_def.did.as_local() {
-                        impls.insert(cx.tcx.hir().as_local_hir_id(def_id));
+                        impls.insert(cx.tcx.hir().local_def_id_to_hir_id(def_id));
                     }
                 }
             });
index d891466611ad379611cd2ce32db66ec2761e8ec8..017d4e31e4a711a18a0c77e55eeb7a1444f63c05 100644 (file)
@@ -23,8 +23,8 @@
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
-use log::debug;
 use std::slice;
+use tracing::debug;
 
 macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
     $cx.pass.$f(&$cx.context, $($args),*);
index f43c197d2d201ace7a1fa4ea8d44bbdfa71991b6..6c497d02285199a1f51a5e2da88d751d6d89f5c1 100644 (file)
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
-use log::debug;
 use std::any::Any;
 use std::cell::Cell;
 use std::slice;
+use tracing::debug;
 
 /// Extract the `LintStore` from the query context.
 /// This function exists because we've erased `LintStore` as `dyn Any` in the context.
@@ -379,7 +379,7 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
         param_env: ty::ParamEnv::empty(),
         access_levels,
         lint_store: unerased_lint_store(tcx),
-        last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id),
+        last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id),
         generics: None,
         only_module: true,
     };
index 5c53e435fd76c82e92a76c999081628a405177bc..5891abcfd9cd186c6aa11fa13409c01edc87f9d2 100644 (file)
@@ -19,8 +19,8 @@
 use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
-use log::debug;
 use std::cmp;
+use tracing::debug;
 
 declare_lint! {
     UNUSED_COMPARISONS,
index ecc8a192f18ea9566ba9c49b8aec4f02b01348ae..95e51b47be34b4040b17fd194b29f187b24a1c45 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
-use log::debug;
+use tracing::debug;
 
 declare_lint! {
     pub UNUSED_MUST_USE,
index 6b30ae42a19408f74ece7e4aee69306264592b1e..7fb3b0e7ea6accba63fc307028c7426286fcfe05 100644 (file)
@@ -8,6 +8,7 @@
 mod hash_stable;
 mod lift;
 mod query;
+mod serialize;
 mod symbols;
 mod type_foldable;
 
@@ -27,5 +28,11 @@ pub fn symbols(input: TokenStream) -> TokenStream {
     hash_stable::hash_stable_generic_derive
 );
 
+decl_derive!([Decodable] => serialize::decodable_derive);
+decl_derive!([Encodable] => serialize::encodable_derive);
+decl_derive!([TyDecodable] => serialize::type_decodable_derive);
+decl_derive!([TyEncodable] => serialize::type_encodable_derive);
+decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
+decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
 decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
 decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
diff --git a/src/librustc_macros/src/serialize.rs b/src/librustc_macros/src/serialize.rs
new file mode 100644 (file)
index 0000000..dbeb3c7
--- /dev/null
@@ -0,0 +1,290 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::parse_quote;
+
+pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    let decoder_ty = quote! { __D };
+    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        s.add_impl_generic(parse_quote! { 'tcx });
+    }
+    s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx>});
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    decodable_body(s, decoder_ty)
+}
+
+pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        s.add_impl_generic(parse_quote! { 'tcx });
+    }
+    s.add_impl_generic(parse_quote! { '__a });
+    let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    decodable_body(s, decoder_ty)
+}
+
+pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    let decoder_ty = quote! { __D };
+    s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_serialize::Decoder});
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    decodable_body(s, decoder_ty)
+}
+
+fn decodable_body(
+    s: synstructure::Structure<'_>,
+    decoder_ty: TokenStream,
+) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+    let ty_name = s.ast().ident.to_string();
+    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) },
+                )
+            }
+        }
+        variants => {
+            let match_inner: TokenStream = variants
+                .iter()
+                .enumerate()
+                .map(|(idx, vi)| {
+                    let construct = vi.construct(|field, index| decode_field(field, index, false));
+                    quote! { #idx => { ::std::result::Result::Ok(#construct) } }
+                })
+                .collect();
+            let names: TokenStream = variants
+                .iter()
+                .map(|vi| {
+                    let variant_name = vi.ast().ident.to_string();
+                    quote!(#variant_name,)
+                })
+                .collect();
+            let message = format!(
+                "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                ty_name,
+                variants.len()
+            );
+            quote! {
+                ::rustc_serialize::Decoder::read_enum(
+                    __decoder,
+                    #ty_name,
+                    |__decoder| {
+                        ::rustc_serialize::Decoder::read_enum_variant(
+                            __decoder,
+                            &[#names],
+                            |__decoder, __variant_idx| {
+                                match __variant_idx {
+                                    #match_inner
+                                    _ => return ::std::result::Result::Err(
+                                        ::rustc_serialize::Decoder::error(__decoder, #message)),
+                                }
+                            })
+                    }
+                )
+            }
+        }
+    };
+
+    s.bound_impl(
+        quote!(::rustc_serialize::Decodable<#decoder_ty>),
+        quote! {
+            fn decode(
+                __decoder: &mut #decoder_ty,
+            ) -> ::std::result::Result<Self, <#decoder_ty as ::rustc_serialize::Decoder>::Error> {
+                #decode_body
+            }
+        },
+    )
+}
+
+fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
+    let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
+        quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
+    } else {
+        quote! { ::rustc_serialize::Decodable::decode }
+    };
+    let (decode_method, opt_field_name) = if is_struct {
+        let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
+        (
+            proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()),
+            quote! { #field_name, },
+        )
+    } else {
+        (
+            proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()),
+            quote! {},
+        )
+    };
+
+    quote! {
+        match ::rustc_serialize::Decoder::#decode_method(
+            __decoder, #opt_field_name #index, #decode_inner_method) {
+            ::std::result::Result::Ok(__res) => __res,
+            ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
+        }
+    }
+}
+
+pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        s.add_impl_generic(parse_quote! {'tcx});
+    }
+    let encoder_ty = quote! { __E };
+    s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx>});
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    encodable_body(s, encoder_ty, false)
+}
+
+pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+        s.add_impl_generic(parse_quote! {'tcx});
+    }
+    s.add_impl_generic(parse_quote! { '__a });
+    let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    encodable_body(s, encoder_ty, true)
+}
+
+pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+    let encoder_ty = quote! { __E };
+    s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder});
+    s.add_bounds(synstructure::AddBounds::Generics);
+
+    encodable_body(s, encoder_ty, false)
+}
+
+fn encodable_body(
+    mut s: synstructure::Structure<'_>,
+    encoder_ty: TokenStream,
+    allow_unreachable_code: bool,
+) -> proc_macro2::TokenStream {
+    if let syn::Data::Union(_) = s.ast().data {
+        panic!("cannot derive on union")
+    }
+
+    s.bind_with(|binding| {
+        // Handle the lack of a blanket reference impl.
+        if let syn::Type::Reference(_) = binding.ast().ty {
+            synstructure::BindStyle::Move
+        } else {
+            synstructure::BindStyle::Ref
+        }
+    });
+
+    let ty_name = s.ast().ident.to_string();
+    let encode_body = match s.variants() {
+        [_] => {
+            let mut field_idx = 0usize;
+            let encode_inner = s.each_variant(|vi| {
+                vi.bindings()
+                    .iter()
+                    .map(|binding| {
+                        let bind_ident = &binding.binding;
+                        let field_name = binding
+                            .ast()
+                            .ident
+                            .as_ref()
+                            .map_or_else(|| field_idx.to_string(), |i| i.to_string());
+                        let result = quote! {
+                            match ::rustc_serialize::Encoder::emit_struct_field(
+                                __encoder,
+                                #field_name,
+                                #field_idx,
+                                |__encoder|
+                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                            ) {
+                                ::std::result::Result::Ok(()) => (),
+                                ::std::result::Result::Err(__err)
+                                    => return ::std::result::Result::Err(__err),
+                            }
+                        };
+                        field_idx += 1;
+                        result
+                    })
+                    .collect::<TokenStream>()
+            });
+            quote! {
+                ::rustc_serialize::Encoder::emit_struct(__encoder, #ty_name, #field_idx, |__encoder| {
+                    ::std::result::Result::Ok(match *self { #encode_inner })
+                })
+            }
+        }
+        _ => {
+            let mut variant_idx = 0usize;
+            let encode_inner = s.each_variant(|vi| {
+                let variant_name = vi.ast().ident.to_string();
+                let mut field_idx = 0usize;
+
+                let encode_fields: TokenStream = vi
+                    .bindings()
+                    .iter()
+                    .map(|binding| {
+                        let bind_ident = &binding.binding;
+                        let result = quote! {
+                            match ::rustc_serialize::Encoder::emit_enum_variant_arg(
+                                __encoder,
+                                #field_idx,
+                                |__encoder|
+                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                            ) {
+                                ::std::result::Result::Ok(()) => (),
+                                ::std::result::Result::Err(__err)
+                                    => return ::std::result::Result::Err(__err),
+                            }
+                        };
+                        field_idx += 1;
+                        result
+                    })
+                    .collect();
+
+                let result = quote! { ::rustc_serialize::Encoder::emit_enum_variant(
+                    __encoder,
+                   #variant_name,
+                   #variant_idx,
+                   #field_idx,
+                   |__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
+                ) };
+                variant_idx += 1;
+                result
+            });
+            quote! {
+                ::rustc_serialize::Encoder::emit_enum(__encoder, #ty_name, |__encoder| {
+                    match *self {
+                        #encode_inner
+                    }
+                })
+            }
+        }
+    };
+
+    let lints = if allow_unreachable_code {
+        quote! { #![allow(unreachable_code)] }
+    } else {
+        quote! {}
+    };
+
+    s.bound_impl(
+        quote!(::rustc_serialize::Encodable<#encoder_ty>),
+        quote! {
+            fn encode(
+                &self,
+                __encoder: &mut #encoder_ty,
+            ) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> {
+                #lints
+                #encode_body
+            }
+        },
+    )
+}
index 2e9b3a2a2562f276ee8fcd99ca7b9fe06d962f04..352665f0ab199e2d216e31f2b4e0b9d129e340d2 100644 (file)
@@ -167,7 +167,7 @@ macro_rules! keywords {
             }
         }
 
-        macro_rules! symbols {
+        macro_rules! define_symbols {
             () => {
                 #symbols_stream
 
index 2c0e2aa39fd595dcedf398ae40acb5803591258f..af6aacfd64b44e4b65e8a4c5b3f9698a47d0eb16 100644 (file)
@@ -12,7 +12,7 @@ doctest = false
 [dependencies]
 flate2 = "1.0"
 libc = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 memmap = "0.7"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_middle = { path = "../librustc_middle" }
@@ -23,6 +23,7 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_hir_pretty = { path = "../librustc_hir_pretty" }
 rustc_target = { path = "../librustc_target" }
 rustc_index = { path = "../librustc_index" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../librustc_serialize" }
 stable_deref_trait = "1.0.0"
 rustc_ast = { path = "../librustc_ast" }
index e15655e3794f53d71c5d6faca100935c0b830ea8..9827b22233137277e6102d3ab3caf526b4235635 100644 (file)
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
-use log::{debug, info};
 use proc_macro::bridge::client::ProcMacro;
 use std::path::Path;
 use std::{cmp, env, fs};
+use tracing::{debug, info};
 
 #[derive(Clone)]
 pub struct CStore {
index bb5ae4d0557c9866a221ae6d7053b519c2397f9b..f7454da90a396c465034f9b9a98efc4dbd1be152 100644 (file)
@@ -159,11 +159,11 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
         let name = tcx.crate_name(cnum);
         let src = tcx.used_crate_source(cnum);
         if src.dylib.is_some() {
-            log::info!("adding dylib: {}", name);
+            tracing::info!("adding dylib: {}", name);
             add_library(tcx, cnum, RequireDynamic, &mut formats);
             let deps = tcx.dylib_dependency_formats(cnum);
             for &(depnum, style) in deps.iter() {
-                log::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
+                tracing::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
                 add_library(tcx, depnum, style, &mut formats);
             }
         }
@@ -191,7 +191,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
             && tcx.dep_kind(cnum) == CrateDepKind::Explicit
         {
             assert!(src.rlib.is_some() || src.rmeta.is_some());
-            log::info!("adding staticlib: {}", tcx.crate_name(cnum));
+            tracing::info!("adding staticlib: {}", tcx.crate_name(cnum));
             add_library(tcx, cnum, RequireStatic, &mut formats);
             ret[cnum.as_usize() - 1] = Linkage::Static;
         }
index 059ae340bcfe968821f5f36d99a46165a365a837..e50fa34554d51acbed0fc7e135651bc6d912f045 100644 (file)
@@ -15,6 +15,8 @@
 
 extern crate proc_macro;
 
+#[macro_use]
+extern crate rustc_macros;
 #[macro_use]
 extern crate rustc_middle;
 #[macro_use]
index 8828b318d1ea6bb6d5fcac44707ee06f4b044391..bdd20a4bf6fafa57b24083aedcfeb3b23494dacc 100644 (file)
 use rustc_target::spec::{Target, TargetTriple};
 
 use flate2::read::DeflateDecoder;
-use log::{debug, info, warn};
 use std::io::{Read, Result as IoResult, Write};
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt, fs};
+use tracing::{debug, info, warn};
 
 #[derive(Clone)]
 crate struct CrateLocator<'a> {
index 8aea9a9f5885061312aa0c18e9710bf22bf57cb9..1e4556f5fc8efbba5aa452895d3cfdc3153b4b45 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_ast::ast;
 use rustc_attr as attr;
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
@@ -15,7 +15,7 @@
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathTable;
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::lang_items;
 use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use rustc_middle::mir::{self, interpret, Body, Promoted};
+use rustc_middle::mir::{self, Body, Promoted};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util::common::record_time;
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
+use rustc_serialize::{opaque, Decodable, Decoder};
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnDataDecodeMode;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{self, hygiene::MacroKind, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
 
-use log::debug;
 use proc_macro::bridge::client::ProcMacro;
 use std::cell::Cell;
 use std::io;
 use std::mem;
 use std::num::NonZeroUsize;
 use std::path::Path;
+use tracing::debug;
 
 pub use cstore_impl::{provide, provide_extern};
 use rustc_span::hygiene::HygieneDecodeContext;
@@ -229,7 +229,7 @@ fn tcx(self) -> Option<TyCtxt<'tcx>> {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> {
     fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
         let mut dcx = metadata.decoder(self.position.get());
         dcx.lazy_state = LazyState::NodeStart(self.position);
@@ -237,7 +237,7 @@ fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
     }
 }
 
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> {
     fn decode<M: Metadata<'a, 'tcx>>(
         self,
         metadata: M,
@@ -278,6 +278,8 @@ fn read_lazy_with_meta<T: ?Sized + LazyMeta>(
 }
 
 impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
+    const CLEAR_CROSS_CRATE: bool = true;
+
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx.expect("missing TyCtxt in DecodeContext")
@@ -351,68 +353,92 @@ fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
         if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] }
     }
-}
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
-        self.read_lazy_with_meta(())
+    fn decode_alloc_id(&mut self) -> Result<rustc_middle::mir::interpret::AllocId, Self::Error> {
+        if let Some(alloc_decoding_session) = self.alloc_decoding_session {
+            alloc_decoding_session.decode_alloc_id(self)
+        } else {
+            bug!("Attempting to decode interpret::AllocId without CrateMetadata")
+        }
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
-        let len = self.read_usize()?;
-        if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for CrateNum {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<CrateNum, String> {
+        let cnum = CrateNum::from_u32(d.read_u32()?);
+        Ok(d.map_encoded_cnum_to_current(cnum))
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
-where
-    Option<T>: FixedSizeEncoding,
-{
-    fn specialized_decode(&mut self) -> Result<Lazy<Table<I, T>>, Self::Error> {
-        let len = self.read_usize()?;
-        self.read_lazy_with_meta(len)
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefIndex, String> {
+        Ok(DefIndex::from_u32(d.read_u32()?))
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<DefId> for DecodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
-        let krate = CrateNum::decode(self)?;
-        let index = DefIndex::decode(self)?;
-
-        Ok(DefId { krate, index })
+impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> {
+    fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
+        Fingerprint::decode_opaque(&mut self.opaque)
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
-        Ok(DefIndex::from_u32(self.read_u32()?))
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
+        let cdata = decoder.cdata();
+        let sess = decoder.sess.unwrap();
+        let cname = cdata.root.name;
+        rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| {
+            debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
+            Ok(cdata
+                .root
+                .syntax_contexts
+                .get(&cdata, id)
+                .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
+                .decode((&cdata, sess)))
+        })
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        Ok(DefId::decode(self)?.expect_local())
-    }
-}
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
+        let local_cdata = decoder.cdata();
+        let sess = decoder.sess.unwrap();
+        let expn_cnum = Cell::new(None);
+        let get_ctxt = |cnum| {
+            expn_cnum.set(Some(cnum));
+            if cnum == LOCAL_CRATE {
+                &local_cdata.hygiene_context
+            } else {
+                &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
+            }
+        };
 
-impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        if let Some(alloc_decoding_session) = self.alloc_decoding_session {
-            alloc_decoding_session.decode_alloc_id(self)
-        } else {
-            bug!("Attempting to decode interpret::AllocId without CrateMetadata")
-        }
+        rustc_span::hygiene::decode_expn_id(
+            decoder,
+            ExpnDataDecodeMode::Metadata(get_ctxt),
+            |_this, index| {
+                let cnum = expn_cnum.get().unwrap();
+                // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
+                // are stored in the owning crate, to avoid duplication.
+                let crate_data = if cnum == LOCAL_CRATE {
+                    local_cdata
+                } else {
+                    local_cdata.cstore.get_crate_data(cnum)
+                };
+                Ok(crate_data
+                    .root
+                    .expn_data
+                    .get(&crate_data, index)
+                    .unwrap()
+                    .decode((&crate_data, sess)))
+            },
+        )
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
-        let tag = u8::decode(self)?;
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> {
+        let tag = u8::decode(decoder)?;
 
         if tag == TAG_INVALID_SPAN {
             return Ok(DUMMY_SP);
@@ -420,12 +446,12 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
 
         debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
 
-        let lo = BytePos::decode(self)?;
-        let len = BytePos::decode(self)?;
-        let ctxt = SyntaxContext::decode(self)?;
+        let lo = BytePos::decode(decoder)?;
+        let len = BytePos::decode(decoder)?;
+        let ctxt = SyntaxContext::decode(decoder)?;
         let hi = lo + len;
 
-        let sess = if let Some(sess) = self.sess {
+        let sess = if let Some(sess) = decoder.sess {
             sess
         } else {
             bug!("Cannot decode Span without Session.")
@@ -460,22 +486,22 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         // we can call `imported_source_files` for the proper crate, and binary search
         // through the returned slice using our span.
         let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
-            self.cdata().imported_source_files(sess)
+            decoder.cdata().imported_source_files(sess)
         } else {
             // When we encode a proc-macro crate, all `Span`s should be encoded
             // with `TAG_VALID_SPAN_LOCAL`
-            if self.cdata().root.is_proc_macro_crate() {
+            if decoder.cdata().root.is_proc_macro_crate() {
                 // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
                 // since we don't have `cnum_map` populated.
-                let cnum = u32::decode(self)?;
+                let cnum = u32::decode(decoder)?;
                 panic!(
                     "Decoding of crate {:?} tried to access proc-macro dep {:?}",
-                    self.cdata().root.name,
+                    decoder.cdata().root.name,
                     cnum
                 );
             }
             // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
-            let cnum = CrateNum::decode(self)?;
+            let cnum = CrateNum::decode(decoder)?;
             debug!(
                 "SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
                 cnum
@@ -485,16 +511,16 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
             // We just set it to 0, to ensure that we don't try to access something out
             // of bounds for our initial 'guess'
-            self.last_source_file_index = 0;
+            decoder.last_source_file_index = 0;
 
-            let foreign_data = self.cdata().cstore.get_crate_data(cnum);
+            let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
             foreign_data.imported_source_files(sess)
         };
 
         let source_file = {
             // Optimize for the case that most spans within a translated item
             // originate from the same source_file.
-            let last_source_file = &imported_source_files[self.last_source_file_index];
+            let last_source_file = &imported_source_files[decoder.last_source_file_index];
 
             if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos
             {
@@ -507,7 +533,7 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
                 // Don't try to cache the index for foreign spans,
                 // as this would require a map from CrateNums to indices
                 if tag == TAG_VALID_SPAN_LOCAL {
-                    self.last_source_file_index = index;
+                    decoder.last_source_file_index = index;
                 }
                 &imported_source_files[index]
             }
@@ -540,19 +566,37 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
-        Fingerprint::decode_opaque(&mut self.opaque)
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+        ty::codec::RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+    for Lazy<T>
+{
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+        decoder.read_lazy_with_meta(())
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+    for Lazy<[T]>
+{
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+        let len = decoder.read_usize()?;
+        if len == 0 { Ok(Lazy::empty()) } else { decoder.read_lazy_with_meta(len) }
+    }
+}
+
+impl<'a, 'tcx, I: Idx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+    for Lazy<Table<I, T>>
 where
-    mir::ClearCrossCrate<T>: UseSpecializedDecodable,
+    Option<T>: FixedSizeEncoding,
 {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
-        Ok(mir::ClearCrossCrate::Clear)
+    fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+        let len = decoder.read_usize()?;
+        decoder.read_lazy_with_meta(len)
     }
 }
 
@@ -1840,57 +1884,3 @@ fn macro_kind(raw: &ProcMacro) -> MacroKind {
         ProcMacro::Bang { .. } => MacroKind::Bang,
     }
 }
-
-impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
-        let cdata = self.cdata();
-        let sess = self.sess.unwrap();
-        let cname = cdata.root.name;
-        rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
-            debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
-            Ok(cdata
-                .root
-                .syntax_contexts
-                .get(&cdata, id)
-                .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
-                .decode((&cdata, sess)))
-        })
-    }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<ExpnId> for DecodeContext<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
-        let local_cdata = self.cdata();
-        let sess = self.sess.unwrap();
-        let expn_cnum = Cell::new(None);
-        let get_ctxt = |cnum| {
-            expn_cnum.set(Some(cnum));
-            if cnum == LOCAL_CRATE {
-                &local_cdata.hygiene_context
-            } else {
-                &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
-            }
-        };
-
-        rustc_span::hygiene::decode_expn_id(
-            self,
-            ExpnDataDecodeMode::Metadata(get_ctxt),
-            |_this, index| {
-                let cnum = expn_cnum.get().unwrap();
-                // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
-                // are stored in the owning crate, to avoid duplication.
-                let crate_data = if cnum == LOCAL_CRATE {
-                    local_cdata
-                } else {
-                    local_cdata.cstore.get_crate_data(cnum)
-                };
-                Ok(crate_data
-                    .root
-                    .expn_data
-                    .get(&crate_data, index)
-                    .unwrap()
-                    .decode((&crate_data, sess)))
-            },
-        )
-    }
-}
index 6723e236a1fe981e0fb9a9b022eb457231183eb9..0343fbeb0fad8df9c3f05325b36689f7c676d527 100644 (file)
@@ -1,9 +1,8 @@
 use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
 use crate::rmeta::*;
 
-use log::{debug, trace};
 use rustc_ast::ast;
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{join, Lrc};
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
 };
-use rustc_middle::mir::{self, interpret};
+use rustc_middle::mir::interpret;
 use rustc_middle::traits::specialization_graph;
-use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
+use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
-use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
+use rustc_serialize::{opaque, Encodable, Encoder};
 use rustc_session::config::CrateType;
 use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext};
 use rustc_span::source_map::Spanned;
@@ -37,8 +36,9 @@
 use std::hash::Hash;
 use std::num::NonZeroUsize;
 use std::path::Path;
+use tracing::{debug, trace};
 
-struct EncodeContext<'a, 'tcx> {
+pub(super) struct EncodeContext<'a, 'tcx> {
     opaque: opaque::Encoder,
     tcx: TyCtxt<'tcx>,
 
@@ -107,100 +107,87 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> {
     }
 }
 
-impl<'a, 'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
-        self.emit_lazy_distance(*lazy)
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+    for Lazy<T>
+{
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        e.emit_lazy_distance(*self)
     }
 }
 
-impl<'a, 'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
-        self.emit_usize(lazy.meta)?;
-        if lazy.meta == 0 {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+    for Lazy<[T]>
+{
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        e.emit_usize(self.meta)?;
+        if self.meta == 0 {
             return Ok(());
         }
-        self.emit_lazy_distance(*lazy)
+        e.emit_lazy_distance(*self)
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'a, 'tcx>
+impl<'a, 'tcx, I: Idx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+    for Lazy<Table<I, T>>
 where
     Option<T>: FixedSizeEncoding,
 {
-    fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::Error> {
-        self.emit_usize(lazy.meta)?;
-        self.emit_lazy_distance(*lazy)
-    }
-}
-
-impl<'a, 'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
-        self.emit_u32(cnum.as_u32())
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        e.emit_usize(self.meta)?;
+        e.emit_lazy_distance(*self)
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<DefId> for EncodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
-        let DefId { krate, index } = *def_id;
-
-        krate.encode(self)?;
-        index.encode(self)
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        s.emit_u32(self.as_u32())
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<SyntaxContext> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, ctxt: &SyntaxContext) -> Result<(), Self::Error> {
-        rustc_span::hygiene::raw_encode_syntax_context(*ctxt, &self.hygiene_ctxt, self)
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<ExpnId> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
         rustc_span::hygiene::raw_encode_expn_id(
-            *expn,
-            &self.hygiene_ctxt,
+            *self,
+            &s.hygiene_ctxt,
             ExpnDataEncodeMode::Metadata,
-            self,
+            s,
         )
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
-        self.emit_u32(def_index.as_u32())
-    }
-}
-
-impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
-        if span.is_dummy() {
-            return TAG_INVALID_SPAN.encode(self);
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        if self.is_dummy() {
+            return TAG_INVALID_SPAN.encode(s);
         }
 
-        let span = span.data();
+        let span = self.data();
 
         // The Span infrastructure should make sure that this invariant holds:
         debug_assert!(span.lo <= span.hi);
 
-        if !self.source_file_cache.0.contains(span.lo) {
-            let source_map = self.tcx.sess.source_map();
+        if !s.source_file_cache.0.contains(span.lo) {
+            let source_map = s.tcx.sess.source_map();
             let source_file_index = source_map.lookup_source_file_idx(span.lo);
-            self.source_file_cache =
+            s.source_file_cache =
                 (source_map.files()[source_file_index].clone(), source_file_index);
         }
 
-        if !self.source_file_cache.0.contains(span.hi) {
+        if !s.source_file_cache.0.contains(span.hi) {
             // Unfortunately, macro expansion still sometimes generates Spans
             // that malformed in this way.
-            return TAG_INVALID_SPAN.encode(self);
+            return TAG_INVALID_SPAN.encode(s);
         }
 
-        let source_files = self.required_source_files.as_mut().expect("Already encoded SourceMap!");
+        let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!");
         // Record the fact that we need to encode the data for this `SourceFile`
-        source_files.insert(self.source_file_cache.1);
+        source_files.insert(s.source_file_cache.1);
 
         // There are two possible cases here:
         // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
@@ -218,7 +205,7 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         // if we're a proc-macro crate.
         // This allows us to avoid loading the dependencies of proc-macro crates: all of
         // the information we need to decode `Span`s is stored in the proc-macro crate.
-        let (tag, lo, hi) = if self.source_file_cache.0.is_imported() && !self.is_proc_macro {
+        let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro {
             // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
             // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
             // are relative to the source map information for the 'foreign' crate whose CrateNum
@@ -230,26 +217,26 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
             // Span that can be used without any additional trouble.
             let external_start_pos = {
                 // Introduce a new scope so that we drop the 'lock()' temporary
-                match &*self.source_file_cache.0.external_src.lock() {
+                match &*s.source_file_cache.0.external_src.lock() {
                     ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
                     src => panic!("Unexpected external source {:?}", src),
                 }
             };
-            let lo = (span.lo - self.source_file_cache.0.start_pos) + external_start_pos;
-            let hi = (span.hi - self.source_file_cache.0.start_pos) + external_start_pos;
+            let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos;
+            let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos;
 
             (TAG_VALID_SPAN_FOREIGN, lo, hi)
         } else {
             (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
         };
 
-        tag.encode(self)?;
-        lo.encode(self)?;
+        tag.encode(s)?;
+        lo.encode(s)?;
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
         let len = hi - lo;
-        len.encode(self)?;
+        len.encode(s)?;
 
         // Don't serialize any `SyntaxContext`s from a proc-macro crate,
         // since we don't load proc-macro dependencies during serialization.
@@ -282,101 +269,85 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         // IMPORTANT: If this is ever changed, be sure to update
         // `rustc_span::hygiene::raw_encode_expn_id` to handle
         // encoding `ExpnData` for proc-macro crates.
-        if self.is_proc_macro {
-            SyntaxContext::root().encode(self)?;
+        if s.is_proc_macro {
+            SyntaxContext::root().encode(s)?;
         } else {
-            span.ctxt.encode(self)?;
+            span.ctxt.encode(s)?;
         }
 
         if tag == TAG_VALID_SPAN_FOREIGN {
-            // This needs to be two lines to avoid holding the `self.source_file_cache`
-            // while calling `cnum.encode(self)`
-            let cnum = self.source_file_cache.0.cnum;
-            cnum.encode(self)?;
+            // This needs to be two lines to avoid holding the `s.source_file_cache`
+            // while calling `cnum.encode(s)`
+            let cnum = s.source_file_cache.0.cnum;
+            cnum.encode(s)?;
         }
 
         Ok(())
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'a, 'tcx> {
-    #[inline]
-    fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
-        self.specialized_encode(&def_id.to_def_id())
+impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+        f.encode_opaque(&mut self.opaque)
     }
 }
 
-impl<'a, 'b, 'c, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'c, 'tcx>
-where
-    &'a ty::TyS<'b>: UseSpecializedEncodable,
-{
-    fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
-        debug_assert!(self.tcx.lift(ty).is_some());
-        let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
-        ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
+impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
+    const CLEAR_CROSS_CRATE: bool = true;
+
+    fn position(&self) -> usize {
+        self.opaque.position()
     }
-}
 
-impl<'a, 'b, 'tcx> SpecializedEncoder<ty::Predicate<'b>> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> {
-        debug_assert!(self.tcx.lift(predicate).is_some());
-        let predicate =
-            unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) };
-        ty_codec::encode_with_shorthand(self, predicate, |encoder| {
-            &mut encoder.predicate_shorthands
-        })
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
     }
-}
 
-impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
-        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
-        index.encode(self)
+    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
+        &mut self.type_shorthands
     }
-}
 
-impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> {
-    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
-        f.encode_opaque(&mut self.opaque)
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<rustc_middle::ty::Predicate<'tcx>, usize> {
+        &mut self.predicate_shorthands
     }
-}
 
-impl<'a, 'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'a, 'tcx>
-where
-    mir::ClearCrossCrate<T>: UseSpecializedEncodable,
-{
-    fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
-        Ok(())
+    fn encode_alloc_id(
+        &mut self,
+        alloc_id: &rustc_middle::mir::interpret::AllocId,
+    ) -> Result<(), Self::Error> {
+        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
+
+        index.encode(self)
     }
 }
 
-impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
-    fn position(&self) -> usize {
-        self.opaque.position()
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        (**self).encode(s)
     }
 }
 
 /// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
-trait EncodeContentsForLazy<T: ?Sized + LazyMeta> {
+trait EncodeContentsForLazy<'a, 'tcx, T: ?Sized + LazyMeta> {
     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
 }
 
-impl<T: Encodable> EncodeContentsForLazy<T> for &T {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for &T {
     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
         self.encode(ecx).unwrap()
     }
 }
 
-impl<T: Encodable> EncodeContentsForLazy<T> for T {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for T {
     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
         self.encode(ecx).unwrap()
     }
 }
 
-impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
+impl<'a, 'tcx, I, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, [T]> for I
 where
     I: IntoIterator,
-    I::Item: EncodeContentsForLazy<T>,
+    I::Item: EncodeContentsForLazy<'a, 'tcx, T>,
 {
     fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
         self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
@@ -421,7 +392,10 @@ fn emit_lazy_distance<T: ?Sized + LazyMeta>(
         self.emit_usize(distance)
     }
 
-    fn lazy<T: ?Sized + LazyMeta>(&mut self, value: impl EncodeContentsForLazy<T>) -> Lazy<T> {
+    fn lazy<T: ?Sized + LazyMeta>(
+        &mut self,
+        value: impl EncodeContentsForLazy<'a, 'tcx, T>,
+    ) -> Lazy<T> {
         let pos = NonZeroUsize::new(self.position()).unwrap();
 
         assert_eq!(self.lazy_state, LazyState::NoNode);
@@ -733,7 +707,7 @@ fn encode_enum_variant_info(&mut self, def: &ty::AdtDef, index: VariantIdx) {
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
-        let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
+        let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
         let enum_vis = &tcx.hir().expect_item(enum_id).vis;
 
         record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
@@ -780,7 +754,7 @@ fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
 
         // Variant constructors have the same visibility as the parent enums, unless marked as
         // non-exhaustive, in which case they are lowered to `pub(crate)`.
-        let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
+        let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
         let enum_vis = &tcx.hir().expect_item(enum_id).vis;
         let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx);
         if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public {
@@ -819,11 +793,11 @@ fn encode_info_for_mod(
         let data = ModData {
             reexports: match tcx.module_exports(local_def_id) {
                 Some(exports) => {
-                    let hir_map = self.tcx.hir();
+                    let hir = self.tcx.hir();
                     self.lazy(
                         exports
                             .iter()
-                            .map(|export| export.map_id(|id| hir_map.as_local_hir_id(id))),
+                            .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))),
                     )
                 }
                 _ => Lazy::empty(),
@@ -855,7 +829,7 @@ fn encode_field(
         let def_id = field.did;
         debug!("EncodeContext::encode_field({:?})", def_id);
 
-        let variant_id = tcx.hir().as_local_hir_id(variant.def_id.expect_local());
+        let variant_id = tcx.hir().local_def_id_to_hir_id(variant.def_id.expect_local());
         let variant_data = tcx.hir().expect_variant_data(variant_id);
 
         record!(self.tables.kind[def_id] <- EntryKind::Field);
@@ -883,7 +857,7 @@ fn encode_struct_ctor(&mut self, adt_def: &ty::AdtDef, def_id: DefId) {
             is_non_exhaustive: variant.is_field_list_non_exhaustive(),
         };
 
-        let struct_id = tcx.hir().as_local_hir_id(adt_def.did.expect_local());
+        let struct_id = tcx.hir().local_def_id_to_hir_id(adt_def.did.expect_local());
         let struct_vis = &tcx.hir().expect_item(struct_id).vis;
         let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
         for field in &variant.fields {
@@ -945,7 +919,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         let ast_item = tcx.hir().expect_trait_item(hir_id);
         let trait_item = tcx.associated_item(def_id);
 
@@ -1034,7 +1008,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
 
-        let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         let ast_item = self.tcx.hir().expect_impl_item(hir_id);
         let impl_item = self.tcx.associated_item(def_id);
 
@@ -1438,7 +1412,7 @@ fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
 
         // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
         // including on the signature, which is inferred in `typeck.
-        let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let ty = self.tcx.typeck(def_id).node_type(hir_id);
 
         record!(self.tables.kind[def_id.to_def_id()] <- match ty.kind {
@@ -1465,7 +1439,7 @@ fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
 
     fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
         debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
-        let id = self.tcx.hir().as_local_hir_id(def_id);
+        let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let body_id = self.tcx.hir().body_owned_by(id);
         let const_data = self.encode_rendered_const_for_body(body_id);
         let qualifs = self.tcx.mir_const_qualif(def_id);
index 1c287be9f6bbcc238f7b83c38b0858b3f77473f0..b15c20e515f495f2d7454ceee44706ae554a2cd0 100644 (file)
 use std::marker::PhantomData;
 use std::num::NonZeroUsize;
 
+use decoder::DecodeContext;
 pub use decoder::{provide, provide_extern};
 crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
+use encoder::EncodeContext;
 use rustc_span::hygiene::SyntaxContextData;
 
 mod decoder;
@@ -141,9 +143,6 @@ fn clone(&self) -> Self {
     }
 }
 
-impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {}
-impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedDecodable for Lazy<T> {}
-
 /// Encoding / decoding state for `Lazy`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 enum LazyState {
@@ -172,7 +171,7 @@ macro_rules! Lazy {
 type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
 type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
 crate struct CrateRoot<'tcx> {
     name: Symbol,
     triple: TargetTriple,
@@ -221,7 +220,7 @@ macro_rules! Lazy {
     symbol_mangling_version: SymbolManglingVersion,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 crate struct CrateDep {
     pub name: Symbol,
     pub hash: Svh,
@@ -230,7 +229,7 @@ macro_rules! Lazy {
     pub extra_filename: String,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
 crate struct TraitImpls {
     trait_id: (u32, DefIndex),
     impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>,
@@ -239,7 +238,7 @@ macro_rules! Lazy {
 /// Define `LazyTables` and `TableBuilders` at the same time.
 macro_rules! define_tables {
     ($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
-        #[derive(RustcEncodable, RustcDecodable)]
+        #[derive(MetadataEncodable, MetadataDecodable)]
         crate struct LazyTables<'tcx> {
             $($name: Lazy!(Table<DefIndex, $T>)),+
         }
@@ -288,7 +287,7 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
 }
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
 enum EntryKind {
     AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
     Const(mir::ConstQualifs, Lazy<RenderedConst>),
@@ -324,23 +323,23 @@ enum EntryKind {
 
 /// Contains a constant which has been rendered to a String.
 /// Used by rustdoc.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 struct RenderedConst(String);
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
 struct ModData {
     reexports: Lazy<[Export<hir::HirId>]>,
     expansion: ExpnId,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
 struct FnData {
     asyncness: hir::IsAsync,
     constness: hir::Constness,
     param_names: Lazy<[Ident]>,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
 struct VariantData {
     ctor_kind: CtorKind,
     discr: ty::VariantDiscr,
@@ -349,7 +348,7 @@ struct VariantData {
     is_non_exhaustive: bool,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
 struct TraitData {
     unsafety: hir::Unsafety,
     paren_sugar: bool,
@@ -358,7 +357,7 @@ struct TraitData {
     specialization_kind: ty::trait_def::TraitSpecializationKind,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
 struct ImplData {
     polarity: ty::ImplPolarity,
     defaultness: hir::Defaultness,
@@ -372,7 +371,7 @@ struct ImplData {
 /// Describes whether the container of an associated item
 /// is a trait or an impl and whether, in a trait, it has
 /// a default, or an in impl, whether it's marked "default".
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable)]
 enum AssocContainer {
     TraitRequired,
     TraitWithDefault,
@@ -404,14 +403,14 @@ fn defaultness(&self) -> hir::Defaultness {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
 struct AssocFnData {
     fn_data: FnData,
     container: AssocContainer,
     has_self: bool,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
 struct GeneratorData<'tcx> {
     layout: mir::GeneratorLayout<'tcx>,
 }
index e1d0a0dbf2ffa2c77d37bfb554300622a7d425c7..28858e146e48930b8100c26ccc78bdd94f7e07dc 100644 (file)
@@ -1,11 +1,11 @@
 use crate::rmeta::*;
 
-use log::debug;
 use rustc_index::vec::Idx;
-use rustc_serialize::{opaque::Encoder, Encodable};
+use rustc_serialize::opaque::Encoder;
 use std::convert::TryInto;
 use std::marker::PhantomData;
 use std::num::NonZeroUsize;
+use tracing::debug;
 
 /// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
 /// Used mainly for Lazy positions and lengths.
@@ -78,7 +78,7 @@ fn write_to_bytes(self, b: &mut [u8]) {
 // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
 // generic `Lazy<T>` impl, but in the general case we might not need / want to
 // fit every `usize` in `u32`.
-impl<T: Encodable> FixedSizeEncoding for Option<Lazy<T>> {
+impl<T> FixedSizeEncoding for Option<Lazy<T>> {
     fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN);
 
     fn from_bytes(b: &[u8]) -> Self {
@@ -93,7 +93,7 @@ fn write_to_bytes(self, b: &mut [u8]) {
     }
 }
 
-impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
+impl<T> FixedSizeEncoding for Option<Lazy<[T]>> {
     fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2);
 
     fn from_bytes(b: &[u8]) -> Self {
index 03431cb5a885ed4310ac549a8ffe46387f4cc7b5..311126361bc5b1c8cff6a22dff1f851bcc3c760e 100644 (file)
@@ -12,7 +12,7 @@ doctest = false
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
 bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc-rayon-core = "0.3.0"
 polonius-engine = "0.12.0"
 rustc_apfloat = { path = "../librustc_apfloat" }
index f2259e5e9f857bece5a479903f03b361cf0ccb45..99889c74da0ec1c7187ec733d8c3b3a1594030c2 100644 (file)
 macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
-            [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
+            [] layouts: rustc_target::abi::Layout,
             // AdtDef are interned and compared by address
-            [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
-            [] steal_mir:
-                rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>,
-                rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>;
-            [decode] mir: rustc_middle::mir::Body<$tcx>, rustc_middle::mir::Body<'_x>;
+            [] adt_def: rustc_middle::ty::AdtDef,
+            [] steal_mir: rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>,
+            [decode] mir: rustc_middle::mir::Body<$tcx>,
             [] steal_promoted:
                 rustc_middle::ty::steal::Steal<
                     rustc_index::vec::IndexVec<
@@ -25,127 +23,86 @@ macro_rules! arena_types {
                         rustc_middle::mir::Body<$tcx>
                     >
                 >,
-                rustc_middle::ty::steal::Steal<
-                    rustc_index::vec::IndexVec<
-                        rustc_middle::mir::Promoted,
-                        rustc_middle::mir::Body<$tcx>
-                    >
-                >;
             [decode] promoted:
                 rustc_index::vec::IndexVec<
                     rustc_middle::mir::Promoted,
                     rustc_middle::mir::Body<$tcx>
                 >,
-                rustc_index::vec::IndexVec<
-                    rustc_middle::mir::Promoted,
-                    rustc_middle::mir::Body<'_x>
-                >;
-            [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>, rustc_middle::ty::TypeckResults<'_x>;
+            [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>,
             [decode] borrowck_result:
                 rustc_middle::mir::BorrowCheckResult<$tcx>,
-                rustc_middle::mir::BorrowCheckResult<'_x>;
-            [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, rustc_middle::mir::UnsafetyCheckResult;
-            [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
+            [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
+            [] const_allocs: rustc_middle::mir::interpret::Allocation,
             // Required for the incremental on-disk cache
-            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
-            [] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree;
+            [few] mir_keys: rustc_hir::def_id::DefIdSet,
+            [] region_scope_tree: rustc_middle::middle::region::ScopeTree,
             [] dropck_outlives:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::DropckOutlivesResult<'tcx>
                     >
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y,
-                        rustc_middle::traits::query::DropckOutlivesResult<'_z>
-                    >
-                >;
             [] normalize_projection_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::NormalizationResult<'tcx>
                     >
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y,
-                        rustc_middle::traits::query::NormalizationResult<'_z>
-                    >
-                >;
             [] implied_outlives_bounds:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         Vec<rustc_middle::traits::query::OutlivesBound<'tcx>>
                     >
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y,
-                        Vec<rustc_middle::traits::query::OutlivesBound<'_z>>
-                    >
-                >;
             [] type_op_subtype:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, ()>
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y, ()>
-                >;
             [] type_op_normalize_poly_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>>
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>>
-                >;
             [] type_op_normalize_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>>
-                >;
             [] type_op_normalize_predicate:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>>
-                >;
             [] type_op_normalize_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
                 >,
-                rustc_middle::infer::canonical::Canonical<'_x,
-                    rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>>
-                >;
-            [few] all_traits: Vec<rustc_hir::def_id::DefId>, Vec<rustc_hir::def_id::DefId>;
-            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels;
-            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule;
-            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>, Vec<rustc_middle::middle::cstore::ForeignModule>;
-            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
-            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
-            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
-            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
-            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
-            [] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
+            [few] all_traits: Vec<rustc_hir::def_id::DefId>,
+            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
+            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule,
+            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>,
+            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
+            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
+            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
+            [] attribute: rustc_ast::ast::Attribute,
+            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
+            [] hir_id_set: rustc_hir::HirIdSet,
 
             // Interned types
-            [] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
-            [] predicates: rustc_middle::ty::PredicateInner<$tcx>, rustc_middle::ty::PredicateInner<'_x>;
+            [] tys: rustc_middle::ty::TyS<$tcx>,
+            [] predicates: rustc_middle::ty::PredicateInner<$tcx>,
 
             // HIR query types
-            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;
-            [few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions;
-            [] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>;
-            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>;
+            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
+            [few] hir_definitions: rustc_hir::definitions::Definitions,
+            [] hir_owner: rustc_middle::hir::Owner<$tcx>,
+            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
-            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
+            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
 
             // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
-            [decode] span: rustc_span::Span, rustc_span::Span;
-            [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>;
+            [decode] span: rustc_span::Span,
+            [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>,
         ], $tcx);
     )
 }
index 98eed4045a34ad6d32443b359fb57511fe17cef4..a61b9af9bace43368b821c711dd4d577d520ee17 100644 (file)
@@ -110,8 +110,7 @@ macro_rules! define_dep_nodes {
         $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
       ,)*
     ) => (
-        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
-                 RustcEncodable, RustcDecodable)]
+        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
         #[allow(non_camel_case_types)]
         pub enum DepKind {
             $($variant),*
index 682b335c5d071775f7e583930ebea1475e546483..6697524279874d1eabfc7ca1bed55248e50c0852 100644 (file)
@@ -185,6 +185,6 @@ fn profiler(&self) -> &SelfProfilerRef {
 }
 
 fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     def_id == hir_id.owner
 }
index af48c9e94ff82a0167a8478ab18200311a7d22af..be9e38aca65d10feeceb8e1d50b7fb208ef86ea5 100644 (file)
@@ -13,7 +13,7 @@
 /// within.
 pub type ExportMap<Id> = FxHashMap<LocalDefId, Vec<Export<Id>>>;
 
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct Export<Id> {
     /// The name of the target.
     pub ident: Ident,
index 250f4d5187f2fa7c920d53844276134f8abbdef2..0794caca1baa5c7dda813cfae68330409ac11405 100644 (file)
@@ -173,11 +173,6 @@ pub fn opt_local_def_id(&self, hir_id: HirId) -> Option<LocalDefId> {
         self.tcx.definitions.opt_hir_id_to_local_def_id(hir_id)
     }
 
-    #[inline]
-    pub fn as_local_hir_id(&self, def_id: LocalDefId) -> HirId {
-        self.tcx.definitions.as_local_hir_id(def_id)
-    }
-
     #[inline]
     pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
         self.tcx.definitions.local_def_id_to_hir_id(def_id)
@@ -450,7 +445,7 @@ pub fn krate_attrs(&self) -> &'hir [ast::Attribute] {
     }
 
     pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
-        let hir_id = self.as_local_hir_id(module);
+        let hir_id = self.local_def_id_to_hir_id(module);
         match self.get_entry(hir_id).node {
             Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
             Node::Crate(item) => (&item.module, item.span, hir_id),
@@ -483,7 +478,7 @@ pub fn get(&self, id: HirId) -> Node<'hir> {
     }
 
     pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
-        id.as_local().map(|id| self.get(self.as_local_hir_id(id)))
+        id.as_local().map(|id| self.get(self.local_def_id_to_hir_id(id)))
     }
 
     pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
@@ -872,7 +867,7 @@ pub fn span(&self, hir_id: HirId) -> Span {
     }
 
     pub fn span_if_local(&self, id: DefId) -> Option<Span> {
-        id.as_local().map(|id| self.span(self.as_local_hir_id(id)))
+        id.as_local().map(|id| self.span(self.local_def_id_to_hir_id(id)))
     }
 
     pub fn res_span(&self, res: Res) -> Option<Span> {
index b014f3c8eb7949635854fa1618581e7e5b4a660a..ae3b30217cc4aae7010e98397e77f82379f30fac 100644 (file)
@@ -66,20 +66,20 @@ pub fn parent_module(self, id: HirId) -> LocalDefId {
 pub fn provide(providers: &mut Providers) {
     providers.parent_module_from_def_id = |tcx, id| {
         let hir = tcx.hir();
-        hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id)))
+        hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
     };
     providers.hir_crate = |tcx, _| tcx.untracked_crate;
     providers.index_hir = map::index_hir;
     providers.hir_module_items = |tcx, id| {
         let hir = tcx.hir();
-        let module = hir.as_local_hir_id(id);
+        let module = hir.local_def_id_to_hir_id(id);
         &tcx.untracked_crate.modules[&module]
     };
     providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
     providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
     providers.fn_arg_names = |tcx, id| {
         let hir = tcx.hir();
-        let hir_id = hir.as_local_hir_id(id.expect_local());
+        let hir_id = hir.local_def_id_to_hir_id(id.expect_local());
         if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
             tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
         } else if let Node::TraitItem(&TraitItem {
index d85165bcccfdc99cf38fc11348f60787bdc0a9b3..bcb56fae1709d94e2ca05ba1e0b4bed411260d1f 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_hir::HirId;
 use rustc_target::abi::VariantIdx;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub enum PlaceBase {
     /// A temporary variable
     Rvalue,
@@ -16,7 +16,7 @@ pub enum PlaceBase {
     Upvar(ty::UpvarId),
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub enum ProjectionKind {
     /// A dereference of a pointer, reference or `Box<T>` of the given type
     Deref,
@@ -36,7 +36,7 @@ pub enum ProjectionKind {
     Subslice,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub struct Projection<'tcx> {
     /// Type after the projection is being applied.
     pub ty: Ty<'tcx>,
@@ -48,7 +48,7 @@ pub struct Projection<'tcx> {
 /// A `Place` represents how a value is located in memory.
 ///
 /// This is an HIR version of `mir::Place`
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub struct Place<'tcx> {
     /// The type of the `PlaceBase`
     pub base_ty: Ty<'tcx>,
@@ -61,7 +61,7 @@ pub struct Place<'tcx> {
 /// A `PlaceWithHirId` represents how a value is located in memory.
 ///
 /// This is an HIR version of `mir::Place`
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub struct PlaceWithHirId<'tcx> {
     /// `HirId` of the expression or pattern producing this value.
     pub hir_id: HirId,
index 9433d282ad297d04b4768ef6a8cb95ff17e7a1a1..1e15ae49a0c384e1a25ad4fcc6dd9ed5e56b3a16 100644 (file)
 use crate::ty::{self, BoundVar, List, Region, TyCtxt};
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
-use rustc_serialize::UseSpecializedDecodable;
 use smallvec::SmallVec;
 use std::ops::Index;
 
 /// A "canonicalized" type `V` is one where all free inference
 /// variables have been rewritten to "canonical vars". These are
 /// numbered starting from 0 in order of first appearance.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub struct Canonical<'tcx, V> {
     pub max_universe: ty::UniverseIndex,
@@ -43,8 +42,6 @@ pub struct Canonical<'tcx, V> {
 
 pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>;
 
-impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
-
 /// A set of values corresponding to the canonical variables from some
 /// `Canonical`. You can give these values to
 /// `canonical_value.substitute` to substitute them into the canonical
@@ -54,7 +51,7 @@ impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
 /// vectors with the original values that were replaced by canonical
 /// variables. You will need to supply it later to instantiate the
 /// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub struct CanonicalVarValues<'tcx> {
     pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
@@ -90,7 +87,7 @@ fn default() -> Self {
 /// canonical value. This is sufficient information for code to create
 /// a copy of the canonical value in some other inference context,
 /// with fresh inference variables replacing the canonical values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
 pub struct CanonicalVarInfo {
     pub kind: CanonicalVarKind,
 }
@@ -115,7 +112,7 @@ pub fn is_existential(&self) -> bool {
 /// Describes the "kind" of the canonical variable. This is a "kind"
 /// in the type-theory sense of the term -- i.e., a "meta" type system
 /// that analyzes type-like values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
 pub enum CanonicalVarKind {
     /// Some kind of type inference variable.
     Ty(CanonicalTyVarKind),
@@ -160,7 +157,7 @@ pub fn universe(self) -> ty::UniverseIndex {
 /// 22.) can only be instantiated with integral/float types (e.g.,
 /// usize or f32). In order to faithfully reproduce a type, we need to
 /// know what set of types a given type variable can be unified with.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
 pub enum CanonicalTyVarKind {
     /// General type variable `?T` that can be unified with arbitrary types.
     General(ty::UniverseIndex),
index 4c06472ceb8739fdadfb68d0f3548ceb6ce7669c..ec1dcd29ef2d8180328b85073d5288af75c0253c 100644 (file)
@@ -60,7 +60,7 @@
 #[macro_use]
 extern crate rustc_data_structures;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate smallvec;
 
index d2749f8529bed5b34baf7aa92ef5cff4b93d17ab..62a6198b9b402108b931b8bacfe1bc802ac5d871 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_session::config::SanitizerSet;
 use rustc_span::symbol::Symbol;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
 pub struct CodegenFnAttrs {
     pub flags: CodegenFnAttrFlags,
     /// Parsed representation of the `#[inline]` attribute
@@ -37,7 +37,7 @@ pub struct CodegenFnAttrs {
 }
 
 bitflags! {
-    #[derive(RustcEncodable, RustcDecodable, HashStable)]
+    #[derive(TyEncodable, TyDecodable, HashStable)]
     pub struct CodegenFnAttrFlags: u32 {
         /// `#[cold]`: a hint to LLVM that this function, when called, is never on
         /// the hot path.
index 0a34c06adf063bae570f3c72b4b1c98d2bd15ddd..6a8f6c3e202038eb66cfb8c14441e95d1068bf9a 100644 (file)
@@ -25,7 +25,7 @@
 
 /// Where a crate came from on the local filesystem. One of these three options
 /// must be non-None.
-#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, HashStable, Encodable, Decodable)]
 pub struct CrateSource {
     pub dylib: Option<(PathBuf, PathKind)>,
     pub rlib: Option<(PathBuf, PathKind)>,
@@ -38,7 +38,7 @@ pub fn paths(&self) -> impl Iterator<Item = &PathBuf> {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
+#[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
 #[derive(HashStable)]
 pub enum CrateDepKind {
     /// A dependency that is only used for its macros.
@@ -60,7 +60,7 @@ pub fn macros_only(self) -> bool {
     }
 }
 
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 pub enum LibSource {
     Some(PathBuf),
     MetadataOnly,
@@ -80,13 +80,13 @@ pub fn option(&self) -> Option<PathBuf> {
     }
 }
 
-#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)]
 pub enum LinkagePreference {
     RequireDynamic,
     RequireStatic,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
 pub struct NativeLib {
     pub kind: NativeLibKind,
     pub name: Option<Symbol>,
@@ -95,7 +95,7 @@ pub struct NativeLib {
     pub wasm_import_module: Option<Symbol>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
 pub struct ForeignModule {
     pub foreign_items: Vec<DefId>,
     pub def_id: DefId,
@@ -145,7 +145,7 @@ pub enum ExternCrateSource {
     Path,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 pub struct EncodedMetadata {
     pub raw_data: Vec<u8>,
 }
index 16ce315368a05d139330346b3b894ee8529d07b9..e079843bfbc3c9dbfbf372f6e664576a373ace02 100644 (file)
@@ -19,7 +19,7 @@
 /// This is local to the tcx, and is generally relevant to one session.
 pub type Dependencies = Vec<(CrateType, DependencyList)>;
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, Encodable, Decodable)]
 pub enum Linkage {
     NotLinked,
     IncludedFromDylib,
index 569af70c5b5fc5063290ad4678bcb846317b7d54..276e45ce99b29a7490b0ace989b6f5b232a4dd0d 100644 (file)
@@ -8,7 +8,7 @@
 /// kind of crate, including cdylibs which export very few things.
 /// `Rust` will only be exported if the crate produced is a Rust
 /// dylib.
-#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum SymbolExportLevel {
     C,
     Rust,
@@ -21,7 +21,7 @@ pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
     }
 }
 
-#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum ExportedSymbol<'tcx> {
     NonGeneric(DefId),
     Generic(DefId, SubstsRef<'tcx>),
index 943a065a8b5e8ef0fed990a8e4bd799bb8fd2eee..4c6ac82060485c9bb0ccb040cc76c6df75c634a3 100644 (file)
@@ -80,7 +80,7 @@
 // placate the same deriving in `ty::FreeRegion`, but we may want to
 // actually attach a more meaningful ordering to scopes than the one
 // generated via deriving here.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct Scope {
     pub id: hir::ItemLocalId,
@@ -104,7 +104,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum ScopeData {
     Node,
@@ -324,7 +324,7 @@ pub struct ScopeTree {
     pub body_expr_count: FxHashMap<hir::BodyId, usize>,
 }
 
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub struct YieldData {
     /// The `Span` of the yield.
     pub span: Span,
index c21ba1b3bd2db7342785dbf8c0271dd43e60fe3b..3d0144e9c8a9903e4b2d0f4545da5a6f5487fa2a 100644 (file)
@@ -11,7 +11,7 @@
 /// The origin of a named lifetime definition.
 ///
 /// This is used to prevent the usage of in-band lifetimes in `Fn`/`fn` syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum LifetimeDefOrigin {
     // Explicit binders like `fn foo<'a>(x: &'a u8)` or elided like `impl Foo<&u32>`
     ExplicitOrElided,
@@ -35,7 +35,7 @@ pub fn from_param(param: &GenericParam<'_>) -> Self {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum Region {
     Static,
     EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin),
@@ -47,7 +47,7 @@ pub enum Region {
 /// A set containing, at most, one known element.
 /// If two distinct values are inserted into a set, then it
 /// becomes `Many`, which can be used to detect ambiguities.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum Set1<T> {
     Empty,
     One(T),
index b23deb2e3bc9b5fe75b368a32dade4c538a0dd72..bee8d13c762f976de14e357366fc8c8f8adec42c 100644 (file)
@@ -14,7 +14,7 @@
     UninitBytesAccess,
 };
 
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct Allocation<Tag = (), Extra = ()> {
     /// The actual bytes of the allocation.
@@ -172,8 +172,6 @@ pub fn relocations(&self) -> &Relocations<Tag> {
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {}
-
 /// Byte accessors.
 impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
     /// Just a small local helper function to avoid a bit of code repetition.
@@ -666,7 +664,7 @@ pub fn mark_compressed_init_range(
 }
 
 /// Relocations.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 pub struct Relocations<Tag = (), Id = AllocId>(SortedMap<Size, (Tag, Id)>);
 
 impl<Tag, Id> Relocations<Tag, Id> {
@@ -747,7 +745,7 @@ pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>)
 
 /// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte
 /// is initialized. If it is `false` the byte is uninitialized.
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct InitMask {
     blocks: Vec<Block>,
index 5be09c0e9bc2bcaef3eda598d7438b76ee119b5e..059925088ce1d52d66266574111bfe509ba3dccb 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_target::abi::{Align, Size};
 use std::{any::Any, backtrace::Backtrace, fmt, mem};
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub enum ErrorHandled {
     /// Already reported an error for this evaluation, and the compilation is
     /// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
@@ -137,7 +137,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 }
 
 /// Details of why a pointer had to be in-bounds.
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum CheckInAllocMsg {
     MemoryAccessTest,
     NullPointerTest,
index 2507f2184fff1026c54437d9e9a6d5dce1cf31b9..e607da29ce453c76e8ad46ca70b514bcb2cfcdc3 100644 (file)
@@ -108,11 +108,11 @@ macro_rules! throw_machine_stop {
 use rustc_data_structures::tiny_list::TinyList;
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
-use rustc_serialize::{Decodable, Encodable, Encoder};
+use rustc_serialize::{Decodable, Encodable};
 use rustc_target::abi::{Endian, Size};
 
 use crate::mir;
-use crate::ty::codec::TyDecoder;
+use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::subst::GenericArgKind;
 use crate::ty::{self, Instance, Ty, TyCtxt};
 
@@ -132,7 +132,7 @@ macro_rules! throw_machine_stop {
 /// - A constant
 /// - A static
 /// - A const fn where all arguments (if any) are zero-sized types
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, Lift)]
 pub struct GlobalId<'tcx> {
     /// For a constant or static, the `Instance` of the item itself.
@@ -182,17 +182,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for AllocId {}
-impl rustc_serialize::UseSpecializedDecodable for AllocId {}
-
-#[derive(RustcDecodable, RustcEncodable)]
+#[derive(TyDecodable, TyEncodable)]
 enum AllocDiscriminant {
     Alloc,
     Fn,
     Static,
 }
 
-pub fn specialized_encode_alloc_id<'tcx, E: Encoder>(
+pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
     encoder: &mut E,
     tcx: TyCtxt<'tcx>,
     alloc_id: AllocId,
@@ -333,7 +330,7 @@ pub fn decode_alloc_id<D>(&self, decoder: &mut D) -> Result<AllocId, D::Error>
         let alloc_id = decoder.with_position(pos, |decoder| {
             match alloc_kind {
                 AllocDiscriminant::Alloc => {
-                    let alloc = <&'tcx Allocation as Decodable>::decode(decoder)?;
+                    let alloc = <&'tcx Allocation as Decodable<_>>::decode(decoder)?;
                     // We already have a reserved `AllocId`.
                     let alloc_id = alloc_id.unwrap();
                     trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
@@ -351,7 +348,7 @@ pub fn decode_alloc_id<D>(&self, decoder: &mut D) -> Result<AllocId, D::Error>
                 AllocDiscriminant::Static => {
                     assert!(alloc_id.is_none());
                     trace!("creating extern static alloc ID");
-                    let did = DefId::decode(decoder)?;
+                    let did = <DefId as Decodable<D>>::decode(decoder)?;
                     trace!("decoded static def-ID: {:?}", did);
                     let alloc_id = decoder.tcx().create_static_alloc(did);
                     Ok(alloc_id)
@@ -369,7 +366,7 @@ pub fn decode_alloc_id<D>(&self, decoder: &mut D) -> Result<AllocId, D::Error>
 
 /// An allocation in the global (tcx-managed) memory can be either a function pointer,
 /// a static, or a "real" allocation with some data in it.
-#[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash, TyDecodable, TyEncodable, HashStable)]
 pub enum GlobalAlloc<'tcx> {
     /// The alloc ID is used as a function pointer.
     Function(Instance<'tcx>),
index ccad4f0a135a16d3557c7d5603b6222d39149709..e3d5a085613aaddfacf6fb61e2aca34521349648 100644 (file)
@@ -87,7 +87,7 @@ impl<T: HasDataLayout> PointerArithmetic for T {}
 ///
 /// `Pointer` is generic over the `Tag` associated with each pointer,
 /// which is used to do provenance tracking during execution.
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
 pub struct Pointer<Tag = ()> {
     pub alloc_id: AllocId,
index 50c76e29663f66af14c4355652bd973b3da74030..4c47f25105d0f4eb5d049b5b5e32ab6692e5806e 100644 (file)
@@ -23,7 +23,7 @@ pub struct RawConst<'tcx> {
 
 /// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
 /// array length computations, enum discriminants and the pattern matching logic.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
 pub enum ConstValue<'tcx> {
     /// Used only for types with `layout::abi::Scalar` ABI and ZSTs.
@@ -108,7 +108,7 @@ pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
 /// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
 /// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
 /// of a simple value or a pointer into another `Allocation`
-#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
 pub enum Scalar<Tag = ()> {
     /// The raw bytes of a simple value.
@@ -562,7 +562,7 @@ fn from(ptr: Pointer<Tag>) -> Self {
     }
 }
 
-#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)]
 pub enum ScalarMaybeUninit<Tag = ()> {
     Scalar(Scalar<Tag>),
     Uninit,
index 3b0c480f6d400458cb0f40b906fc9ceea216ab82..6a2b1d115848b4352e2dbacc2c6aded680532553 100644 (file)
@@ -5,6 +5,7 @@
 use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
+use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::subst::{Subst, SubstsRef};
@@ -73,7 +74,7 @@ fn local_decls(&self) -> &LocalDecls<'tcx> {
 /// The various "big phases" that MIR goes through.
 ///
 /// Warning: ordering of variants is significant.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
 #[derive(HashStable)]
 pub enum MirPhase {
     Build = 0,
@@ -91,7 +92,7 @@ pub fn phase_index(&self) -> usize {
 }
 
 /// The lowered representation of a single function.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
 pub struct Body<'tcx> {
     /// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock`
     /// that indexes into this vector.
@@ -413,7 +414,7 @@ pub fn dominators(&self) -> Dominators<BasicBlock> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum Safety {
     Safe,
     /// Unsafe because of a PushUnsafeBlock
@@ -465,9 +466,13 @@ pub fn assert_crate_local(self) -> T {
 const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
 const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
 
-impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {
+impl<'tcx, E: TyEncoder<'tcx>, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
     #[inline]
-    fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        if E::CLEAR_CROSS_CRATE {
+            return Ok(());
+        }
+
         match *self {
             ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
             ClearCrossCrate::Set(ref val) => {
@@ -477,12 +482,13 @@ fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E
         }
     }
 }
-impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {
+impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
     #[inline]
-    fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
-    where
-        D: rustc_serialize::Decoder,
-    {
+    fn decode(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error> {
+        if D::CLEAR_CROSS_CRATE {
+            return Ok(ClearCrossCrate::Clear);
+        }
+
         let discr = u8::decode(d)?;
 
         match discr {
@@ -491,7 +497,7 @@ fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
                 let val = T::decode(d)?;
                 Ok(ClearCrossCrate::Set(val))
             }
-            _ => unreachable!(),
+            tag => Err(d.error(&format!("Invalid tag for ClearCrossCrate: {:?}", tag))),
         }
     }
 }
@@ -501,7 +507,7 @@ fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
 /// Most passes can work with it as a whole, within a single function.
 // The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
 // `Hash`. Please ping @bjorn3 if removing them.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
 pub struct SourceInfo {
     /// The source span for the AST pertaining to this MIR entity.
     pub span: Span,
@@ -521,7 +527,7 @@ pub fn outermost(span: Span) -> Self {
 ///////////////////////////////////////////////////////////////////////////
 // Borrow kinds
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
@@ -632,7 +638,7 @@ pub enum LocalKind {
     ReturnPointer,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct VarBindingForm<'tcx> {
     /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
     pub binding_mode: ty::BindingMode,
@@ -654,7 +660,7 @@ pub struct VarBindingForm<'tcx> {
     pub pat_span: Span,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable)]
 pub enum BindingForm<'tcx> {
     /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
     Var(VarBindingForm<'tcx>),
@@ -665,7 +671,7 @@ pub enum BindingForm<'tcx> {
 }
 
 /// Represents what type of implicit self a function has, if any.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum ImplicitSelfKind {
     /// Represents a `fn x(self);`.
     Imm,
@@ -708,7 +714,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 /// involved in borrow_check errors, e.g., explanations of where the
 /// temporaries come from, when their destructors are run, and/or how
 /// one might revise the code to satisfy the borrow checker's rules.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct BlockTailInfo {
     /// If `true`, then the value resulting from evaluating this tail
     /// expression is ignored by the block's expression context.
@@ -725,7 +731,7 @@ pub struct BlockTailInfo {
 ///
 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
 /// argument, or the return place.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct LocalDecl<'tcx> {
     /// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
     ///
@@ -857,10 +863,13 @@ pub struct LocalDecl<'tcx> {
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(LocalDecl<'_>, 56);
 
-/// Extra information about a some locals that's used for diagnostics. (Not
-/// used for non-StaticRef temporaries, the return place, or anonymous function
-/// parameters.)
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+/// Extra information about a some locals that's used for diagnostics and for
+/// classifying variables into local variables, statics, etc, which is needed e.g.
+/// for unsafety checking.
+///
+/// Not used for non-StaticRef temporaries, the return place, or anonymous
+/// function parameters.
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub enum LocalInfo<'tcx> {
     /// A user-defined local variable or function parameter
     ///
@@ -1003,7 +1012,7 @@ pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
 }
 
 /// Debug information pertaining to a user variable.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct VarDebugInfo<'tcx> {
     pub name: Symbol,
 
@@ -1038,7 +1047,7 @@ pub fn start_location(self) -> Location {
 ///////////////////////////////////////////////////////////////////////////
 // BasicBlockData and Terminator
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct BasicBlockData<'tcx> {
     /// List of statements in this block.
     pub statements: Vec<Statement<'tcx>>,
@@ -1061,7 +1070,7 @@ pub struct BasicBlockData<'tcx> {
 }
 
 /// Information about an assertion failure.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
 pub enum AssertKind<O> {
     BoundsCheck { len: O, index: O },
     Overflow(BinOp, O, O),
@@ -1072,7 +1081,7 @@ pub enum AssertKind<O> {
     ResumedAfterPanic(GeneratorKind),
 }
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub enum InlineAsmOperand<'tcx> {
     In {
         reg: InlineAsmRegOrRegClass,
@@ -1317,7 +1326,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct Statement<'tcx> {
     pub source_info: SourceInfo,
     pub kind: StatementKind<'tcx>,
@@ -1343,7 +1352,7 @@ pub fn replace_nop(&mut self) -> Self {
     }
 }
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub enum StatementKind<'tcx> {
     /// Write the RHS Rvalue to the LHS Place.
     Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
@@ -1396,7 +1405,7 @@ pub enum StatementKind<'tcx> {
 }
 
 /// Describes what kind of retag is to be performed.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, HashStable)]
 pub enum RetagKind {
     /// The initial retag when entering a function.
     FnEntry,
@@ -1409,7 +1418,7 @@ pub enum RetagKind {
 }
 
 /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, HashStable, PartialEq)]
 pub enum FakeReadCause {
     /// Inject a fake read of the borrowed input at the end of each guards
     /// code.
@@ -1451,7 +1460,7 @@ pub enum FakeReadCause {
     ForIndex,
 }
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct LlvmInlineAsm<'tcx> {
     pub asm: hir::LlvmInlineAsmInner,
     pub outputs: Box<[Place<'tcx>]>,
@@ -1496,7 +1505,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
 pub struct Place<'tcx> {
     pub local: Local,
 
@@ -1504,10 +1513,8 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
-
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ProjectionElem<V, T> {
     Deref,
     Field(Field, T),
@@ -1732,7 +1739,7 @@ pub struct SourceScope {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct SourceScopeData {
     pub span: Span,
     pub parent_scope: Option<SourceScope>,
@@ -1742,7 +1749,7 @@ pub struct SourceScopeData {
     pub local_data: ClearCrossCrate<SourceScopeLocalData>,
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct SourceScopeLocalData {
     /// An `HirId` with lint levels equivalent to this scope's lint levels.
     pub lint_root: hir::HirId,
@@ -1755,7 +1762,7 @@ pub struct SourceScopeLocalData {
 
 /// These are values that can appear inside an rvalue. They are intentionally
 /// limited to prevent rvalues from being nested in one another.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub enum Operand<'tcx> {
     /// Copy: The value must be available for use afterwards.
     ///
@@ -1889,7 +1896,7 @@ pub fn place(&self) -> Option<Place<'tcx>> {
 ///////////////////////////////////////////////////////////////////////////
 /// Rvalues
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
 pub enum Rvalue<'tcx> {
     /// x (either a move or copy, depending on type of x)
     Use(Operand<'tcx>),
@@ -1935,13 +1942,13 @@ pub enum Rvalue<'tcx> {
     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum CastKind {
     Misc,
     Pointer(PointerCast),
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum AggregateKind<'tcx> {
     /// The type is of the element
     Array(Ty<'tcx>),
@@ -1958,7 +1965,7 @@ pub enum AggregateKind<'tcx> {
     Generator(DefId, SubstsRef<'tcx>, hir::Movability),
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum BinOp {
     /// The `+` operator (addition)
     Add,
@@ -2006,7 +2013,7 @@ pub fn is_checkable(self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum NullOp {
     /// Returns the size of a value of that type
     SizeOf,
@@ -2014,7 +2021,7 @@ pub enum NullOp {
     Box,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum UnOp {
     /// The `!` operator for logical inversion
     Not,
@@ -2127,7 +2134,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
                     AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
                         if let Some(def_id) = def_id.as_local() {
-                            let hir_id = tcx.hir().as_local_hir_id(def_id);
+                            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                             let name = if tcx.sess.opts.debugging_opts.span_free_formats {
                                 let substs = tcx.lift(&substs).unwrap();
                                 format!(
@@ -2155,7 +2162,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 
                     AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
                         if let Some(def_id) = def_id.as_local() {
-                            let hir_id = tcx.hir().as_local_hir_id(def_id);
+                            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                             let name = format!("[generator@{:?}]", tcx.hir().span(hir_id));
                             let mut struct_fmt = fmt.debug_struct(&name);
 
@@ -2184,7 +2191,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
 /// this does not necessarily mean that they are "==" in Rust -- in
 /// particular one must be wary of `NaN`!
 
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub struct Constant<'tcx> {
     pub span: Span,
 
@@ -2245,7 +2252,7 @@ pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
 /// The first will lead to the constraint `w: &'1 str` (for some
 /// inferred region `'1`). The second will lead to the constraint `w:
 /// &'static str`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct UserTypeProjections {
     pub contents: Vec<(UserTypeProjection, Span)>,
 }
@@ -2322,7 +2329,7 @@ pub fn variant(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx, field: Fi
 /// * `let (x, _): T = ...` -- here, the `projs` vector would contain
 ///   `field[0]` (aka `.0`), indicating that the type of `s` is
 ///   determined by finding the type of the `.0` field from `T`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, PartialEq)]
 pub struct UserTypeProjection {
     pub base: UserTypeAnnotationIndex,
     pub projs: Vec<ProjectionKind>,
index bb204223b60607ee9079ac6ec8da1e3e02b9d5a1..0d5f6619df5e0bf4c111e8bb8467f0b4bcbeccdc 100644 (file)
@@ -198,10 +198,10 @@ fn to_string_internal<'tcx>(
     pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
         match *self {
             MonoItem::Fn(Instance { def, .. }) => {
-                def.def_id().as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+                def.def_id().as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }
             MonoItem::Static(def_id) => {
-                def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+                def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
             }
             MonoItem::GlobalAsm(hir_id) => Some(hir_id),
         }
@@ -242,7 +242,7 @@ pub struct CodegenUnit<'tcx> {
 /// Specifies the linkage type for a `MonoItem`.
 ///
 /// See https://llvm.org/docs/LangRef.html#linkage-types for more details about these variants.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum Linkage {
     External,
     AvailableExternally,
@@ -346,9 +346,10 @@ fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'
                             // instances into account. The others don't matter for
                             // the codegen tests and can even make item order
                             // unstable.
-                            InstanceDef::Item(def) => {
-                                def.did.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
-                            }
+                            InstanceDef::Item(def) => def
+                                .did
+                                .as_local()
+                                .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)),
                             InstanceDef::VtableShim(..)
                             | InstanceDef::ReifyShim(..)
                             | InstanceDef::Intrinsic(..)
@@ -360,7 +361,7 @@ fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'
                         }
                     }
                     MonoItem::Static(def_id) => {
-                        def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+                        def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
                     }
                     MonoItem::GlobalAsm(hir_id) => Some(hir_id),
                 },
index 7508c0239397f6fe2d96d82bb2c1842511ea0f6a..b16a1d53fff1cdb2ea5e4f29bcad58e1d9becc1f 100644 (file)
@@ -54,16 +54,16 @@ pub(super) fn compute(
     }
 }
 
-impl serialize::Encodable for PredecessorCache {
+impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache {
     #[inline]
-    fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         serialize::Encodable::encode(&(), s)
     }
 }
 
-impl serialize::Decodable for PredecessorCache {
+impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache {
     #[inline]
-    fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
         serialize::Decodable::decode(d).map(|_v: ()| Self::new())
     }
 }
index 6ce5d61fbed1b82dcd710540511f874d32e38dc0..0878e9313d8c5d6153a836330fc00fb85eb29de2 100644 (file)
@@ -16,7 +16,7 @@
 
 use super::{Field, SourceInfo};
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub enum UnsafetyViolationKind {
     /// Only permitted in regular `fn`s, prohibited in `const fn`s.
     General,
@@ -35,7 +35,7 @@ pub enum UnsafetyViolationKind {
     UnsafeFnBorrowPacked,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub enum UnsafetyViolationDetails {
     CallToUnsafeFunction,
     UseOfInlineAssembly,
@@ -120,7 +120,7 @@ pub fn description_and_note(&self) -> (&'static str, &'static str) {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub struct UnsafetyViolation {
     pub source_info: SourceInfo,
     pub lint_root: hir::HirId,
@@ -128,7 +128,7 @@ pub struct UnsafetyViolation {
     pub details: UnsafetyViolationDetails,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
 pub struct UnsafetyCheckResult {
     /// Violations that are propagated *upwards* from this function.
     pub violations: Lrc<[UnsafetyViolation]>,
@@ -145,7 +145,7 @@ pub struct GeneratorSavedLocal {
 }
 
 /// The layout of generator state.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct GeneratorLayout<'tcx> {
     /// The type of every local stored inside the generator.
     pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
@@ -220,7 +220,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-#[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct BorrowCheckResult<'tcx> {
     /// All the opaque types that are restricted to concrete types
     /// by this function. Unlike the value in `TypeckResults`, this has
@@ -235,7 +235,7 @@ pub struct BorrowCheckResult<'tcx> {
 /// Each field corresponds to an implementer of the `Qualif` trait in
 /// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
 /// `Qualif`.
-#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
 pub struct ConstQualifs {
     pub has_mut_interior: bool,
     pub needs_drop: bool,
@@ -291,7 +291,7 @@ pub struct ConstQualifs {
 /// `ReEarlyBound`, `ReFree`). We use these because in a query response we
 /// cannot use `ReVar` (which is what we use internally within the rest of the
 /// NLL code).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct ClosureRegionRequirements<'tcx> {
     /// The number of external regions defined on the closure. In our
     /// example above, it would be 3 -- one for `'static`, then `'1`
@@ -307,7 +307,7 @@ pub struct ClosureRegionRequirements<'tcx> {
 
 /// Indicates an outlives-constraint between a type or between two
 /// free regions declared on the closure.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct ClosureOutlivesRequirement<'tcx> {
     // This region or type ...
     pub subject: ClosureOutlivesSubject<'tcx>,
@@ -328,7 +328,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
 ///
 /// See also `rustc_mir::borrow_check::constraints`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ConstraintCategory {
     Return(ReturnConstraint),
     Yield,
@@ -365,7 +365,7 @@ pub enum ConstraintCategory {
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ReturnConstraint {
     Normal,
     ClosureUpvar(hir::HirId),
@@ -373,7 +373,7 @@ pub enum ReturnConstraint {
 
 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
 /// that must outlive some region.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum ClosureOutlivesSubject<'tcx> {
     /// Subject is a type, typically a type parameter, but could also
     /// be a projection. Indicates a requirement like `T: 'a` being
@@ -398,7 +398,7 @@ pub struct DestructuredConst<'tcx> {
 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
 /// compiler option `-Zinstrument-coverage`). This information is generated by the
 /// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
 pub struct CoverageInfo {
     /// The total number of coverage region counters added to the MIR `Body`.
     pub num_counters: u32,
index 1f5041141d55b93420b81cf1d3246928b6192bde..0ab783812241e343afe204964f0f614cb131efb2 100644 (file)
@@ -16,7 +16,7 @@
 
 pub use super::query::*;
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
 pub enum TerminatorKind<'tcx> {
     /// Block should have one successor in the graph; we jump there.
     Goto { target: BasicBlock },
@@ -194,7 +194,7 @@ pub enum TerminatorKind<'tcx> {
         destination: Option<BasicBlock>,
     },
 }
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct Terminator<'tcx> {
     pub source_info: SourceInfo,
     pub kind: TerminatorKind<'tcx>,
index a8f6723a35605c281d5bb964dffe0798708d05f3..d874edf627472362fd7740a067c0c278405a3a60 100644 (file)
@@ -352,7 +352,7 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         /// per-type-parameter predicates for resolving `T::AssocTy`.
         query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
             desc { |tcx| "computing the bounds for type parameter `{}`", {
-                let id = tcx.hir().as_local_hir_id(key.1);
+                let id = tcx.hir().local_def_id_to_hir_id(key.1);
                 tcx.hir().ty_param_name(id)
             }}
         }
@@ -740,7 +740,8 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
     }
 
     Other {
-        query reachable_set(_: CrateNum) -> &'tcx HirIdSet {
+        query reachable_set(_: CrateNum) -> FxHashSet<LocalDefId> {
+            storage(ArenaCacheSelector<'tcx>)
             desc { "reachability" }
         }
 
index 585f29386a8e0e15c06f2595c2213dd72829c9a3..ea9c8b7a415840b15e2adfedca48baea42093e5b 100644 (file)
@@ -426,7 +426,7 @@ pub enum SelectionError<'tcx> {
 /// ### The type parameter `N`
 ///
 /// See explanation on `ImplSourceUserDefinedData`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub enum ImplSource<'tcx, N> {
     /// ImplSource identifying a particular impl.
     ImplSourceUserDefined(ImplSourceUserDefinedData<'tcx, N>),
@@ -557,14 +557,14 @@ pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
 /// is `Obligation`, as one might expect. During codegen, however, this
 /// is `()`, because codegen only requires a shallow resolution of an
 /// impl, and nested obligations are satisfied later.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceUserDefinedData<'tcx, N> {
     pub impl_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceGeneratorData<'tcx, N> {
     pub generator_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -573,7 +573,7 @@ pub struct ImplSourceGeneratorData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceClosureData<'tcx, N> {
     pub closure_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
@@ -582,18 +582,18 @@ pub struct ImplSourceClosureData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceAutoImplData<N> {
     pub trait_def_id: DefId,
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceBuiltinData<N> {
     pub nested: Vec<N>,
 }
 
-#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceObjectData<'tcx, N> {
     /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
     pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -606,17 +606,17 @@ pub struct ImplSourceObjectData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceFnPointerData<'tcx, N> {
     pub fn_ty: Ty<'tcx>,
     pub nested: Vec<N>,
 }
 
 // FIXME(@lcnr): This should be  refactored and merged with other builtin vtables.
-#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub struct ImplSourceDiscriminantKindData;
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub alias_def_id: DefId,
     pub substs: SubstsRef<'tcx>,
index c9aae8980076f1a81c3446a03b2d88b0c04fbb91..969404c68cab7084513835d141ce4e4c9a5231ab 100644 (file)
@@ -23,7 +23,7 @@
 ///   parents of a given specializing impl, which is needed for extracting
 ///   default items amongst other things. In the simple "chain" rule, every impl
 ///   has at most one parent.
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
 pub struct Graph {
     /// All impls have a parent; the "root" impls have as their parent the `def_id`
     /// of the trait.
@@ -50,7 +50,7 @@ pub fn parent(&self, child: DefId) -> DefId {
 
 /// Children of a given impl, grouped into blanket/non-blanket varieties as is
 /// done in `TraitDef`.
-#[derive(Default, RustcEncodable, RustcDecodable)]
+#[derive(Default, TyEncodable, TyDecodable)]
 pub struct Children {
     // Impls of a trait (or specializations of a given impl). To allow for
     // quicker lookup, the impls are indexed by a simplified version of their
index 52ebcd63e7cda40a5e807cfee3529551ed11d9de..0ab07aea426c3c95d217133c567d291e0c0f8cc0 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem};
 use rustc_macros::HashStable;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum PointerCast {
     /// Go from a fn-item type to a fn-pointer type.
     ReifyFnPointer,
@@ -76,7 +76,7 @@ pub enum PointerCast {
 ///    At some point, of course, `Box` should move out of the compiler, in which
 ///    case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
 ///    Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct Adjustment<'tcx> {
     pub kind: Adjust<'tcx>,
     pub target: Ty<'tcx>,
@@ -91,7 +91,7 @@ pub fn is_region_borrow(&self) -> bool {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub enum Adjust<'tcx> {
     /// Go from ! to any type.
     NeverToAny,
@@ -109,7 +109,7 @@ pub enum Adjust<'tcx> {
 /// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
 /// The target type is `U` in both cases, with the region and mutability
 /// being those shared by both the receiver and the returned reference.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub struct OverloadedDeref<'tcx> {
     pub region: ty::Region<'tcx>,
     pub mutbl: hir::Mutability,
@@ -143,13 +143,13 @@ pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, Substs
 /// new code via two-phase borrows, so we try to limit where we create two-phase
 /// capable mutable borrows.
 /// See #49434 for tracking.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum AllowTwoPhase {
     Yes,
     No,
 }
 
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum AutoBorrowMutability {
     Mut { allow_two_phase_borrow: AllowTwoPhase },
     Not,
@@ -164,7 +164,7 @@ fn from(m: AutoBorrowMutability) -> Self {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
 pub enum AutoBorrow<'tcx> {
     /// Converts from T to &T.
     Ref(ty::Region<'tcx>, AutoBorrowMutability),
@@ -179,7 +179,7 @@ pub enum AutoBorrow<'tcx> {
 /// This struct can be obtained via the `coerce_impl_info` query.
 /// Demanding this struct also has the side-effect of reporting errors
 /// for inappropriate impls.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
 pub struct CoerceUnsizedInfo {
     /// If this is a "custom coerce" impl, then what kind of custom
     /// coercion is it? This applies to impls of `CoerceUnsized` for
@@ -188,7 +188,7 @@ pub struct CoerceUnsizedInfo {
     pub custom_kind: Option<CustomCoerceUnsized>,
 }
 
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
 pub enum CustomCoerceUnsized {
     /// Records the index of the field being coerced.
     Struct(usize),
index 5ee8811509098e40a885025d38319784620ed7c5..3237147c8ba2f589f8d4478875b88c03d2d975af 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_hir::BindingAnnotation::*;
 use rustc_hir::Mutability;
 
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)]
 pub enum BindingMode {
     BindByReference(Mutability),
     BindByValue(Mutability),
index 31c106cb230b43624466384068b65aebbd1c8480..3a3caa55f60776f6a8a5b0bb52ac19cbc4960b0c 100644 (file)
@@ -31,7 +31,7 @@ pub enum CastTy<'tcx> {
 }
 
 /// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum CastKind {
     CoercionCast,
     PtrPtrCast,
index a7c7b16048039386290eef78c30dffe041f5074c..291648869fb69ed9d064aba56c9ffc84ccd62dc2 100644 (file)
@@ -8,12 +8,15 @@
 
 use crate::arena::ArenaAllocatable;
 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
-use crate::mir::{self, interpret::Allocation};
+use crate::mir::{
+    self,
+    interpret::{AllocId, Allocation},
+};
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::Span;
 use std::convert::{TryFrom, TryInto};
 use std::hash::Hash;
 /// This offset is also chosen so that the first byte is never < 0x80.
 pub const SHORTHAND_OFFSET: usize = 0x80;
 
-pub trait EncodableWithShorthand: Clone + Eq + Hash {
-    type Variant: Encodable;
+pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
+    type Variant: Encodable<E>;
     fn variant(&self) -> &Self::Variant;
 }
 
 #[allow(rustc::usage_of_ty_tykind)]
-impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
     type Variant = ty::TyKind<'tcx>;
     fn variant(&self) -> &Self::Variant {
         &self.kind
     }
 }
 
-impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate<'tcx> {
     type Variant = ty::PredicateKind<'tcx>;
     fn variant(&self) -> &Self::Variant {
         self.kind()
     }
 }
 
-pub trait TyEncoder: Encoder {
-    fn position(&self) -> usize;
+pub trait OpaqueEncoder: Encoder {
+    fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder;
+    fn encoder_position(&self) -> usize;
 }
 
-impl TyEncoder for opaque::Encoder {
+impl OpaqueEncoder for rustc_serialize::opaque::Encoder {
+    #[inline]
+    fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder {
+        self
+    }
     #[inline]
-    fn position(&self) -> usize {
+    fn encoder_position(&self) -> usize {
         self.position()
     }
 }
 
+pub trait TyEncoder<'tcx>: Encoder {
+    const CLEAR_CROSS_CRATE: bool;
+
+    fn tcx(&self) -> TyCtxt<'tcx>;
+    fn position(&self) -> usize;
+    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize>;
+    fn encode_alloc_id(&mut self, alloc_id: &AllocId) -> Result<(), Self::Error>;
+}
+
+/// Trait for decoding to a reference.
+///
+/// This is a separate trait from `Decodable` so that we can implement it for
+/// upstream types, such as `FxHashSet`.
+///
+/// The `TyDecodable` derive macro will use this trait for fields that are
+/// references (and don't use a type alias to hide that).
+///
+/// `Decodable` can still be implemented in cases where `Decodable` is required
+/// by a trait bound.
+pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> {
+    fn decode(d: &mut D) -> Result<&'tcx Self, D::Error>;
+}
+
 /// Encode the given value or a previously cached shorthand.
 pub fn encode_with_shorthand<E, T, M>(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error>
 where
-    E: TyEncoder,
+    E: TyEncoder<'tcx>,
     M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
-    T: EncodableWithShorthand,
+    T: EncodableWithShorthand<'tcx, E>,
     <T::Variant as DiscriminantKind>::Discriminant: Ord + TryFrom<usize>,
 {
-    let existing_shorthand = cache(encoder).get(value).cloned();
+    let existing_shorthand = cache(encoder).get(value).copied();
     if let Some(shorthand) = existing_shorthand {
         return encoder.emit_usize(shorthand);
     }
@@ -89,13 +121,51 @@ pub fn encode_with_shorthand<E, T, M>(encoder: &mut E, value: &T, cache: M) -> R
     // Check that the shorthand is a not longer than the
     // full encoding itself, i.e., it's an obvious win.
     if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
-        cache(encoder).insert(value.clone(), shorthand);
+        cache(encoder).insert(*value, shorthand);
     }
 
     Ok(())
 }
 
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        encode_with_shorthand(e, self, TyEncoder::type_shorthands)
+    }
+}
+
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        encode_with_shorthand(e, self, TyEncoder::predicate_shorthands)
+    }
+}
+
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+        e.encode_alloc_id(self)
+    }
+}
+
+macro_rules! encodable_via_deref {
+    ($($t:ty),+) => {
+        $(impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for $t {
+            fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+                (**self).encode(e)
+            }
+        })*
+    }
+}
+
+encodable_via_deref! {
+    &'tcx ty::TypeckResults<'tcx>,
+    ty::Region<'tcx>,
+    &'tcx mir::Body<'tcx>,
+    &'tcx mir::UnsafetyCheckResult,
+    &'tcx mir::BorrowCheckResult<'tcx>
+}
+
 pub trait TyDecoder<'tcx>: Decoder {
+    const CLEAR_CROSS_CRATE: bool;
+
     fn tcx(&self) -> TyCtxt<'tcx>;
 
     fn peek_byte(&self) -> u8;
@@ -127,10 +197,12 @@ fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
     fn positioned_at_shorthand(&self) -> bool {
         (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
     }
+
+    fn decode_alloc_id(&mut self) -> Result<AllocId, Self::Error>;
 }
 
 #[inline]
-pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
+pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>(
     decoder: &mut D,
 ) -> Result<&'tcx T, D::Error>
 where
@@ -140,172 +212,157 @@ pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
 }
 
 #[inline]
-pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
+pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>(
     decoder: &mut D,
 ) -> Result<&'tcx [T], D::Error>
 where
     D: TyDecoder<'tcx>,
 {
-    Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
+    Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)?))
 }
 
-#[inline]
-pub fn decode_cnum<D>(decoder: &mut D) -> Result<CrateNum, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let cnum = CrateNum::from_u32(u32::decode(decoder)?);
-    Ok(decoder.map_encoded_cnum_to_current(cnum))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
+    #[allow(rustc::usage_of_ty_tykind)]
+    fn decode(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> {
+        // Handle shorthands first, if we have an usize > 0x80.
+        if decoder.positioned_at_shorthand() {
+            let pos = decoder.read_usize()?;
+            assert!(pos >= SHORTHAND_OFFSET);
+            let shorthand = pos - SHORTHAND_OFFSET;
+
+            decoder.cached_ty_for_shorthand(shorthand, |decoder| {
+                decoder.with_position(shorthand, Ty::decode)
+            })
+        } else {
+            let tcx = decoder.tcx();
+            Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
+        }
+    }
 }
 
-#[allow(rustc::usage_of_ty_tykind)]
-#[inline]
-pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    // Handle shorthands first, if we have an usize > 0x80.
-    if decoder.positioned_at_shorthand() {
-        let pos = decoder.read_usize()?;
-        assert!(pos >= SHORTHAND_OFFSET);
-        let shorthand = pos - SHORTHAND_OFFSET;
-
-        decoder.cached_ty_for_shorthand(shorthand, |decoder| {
-            decoder.with_position(shorthand, Ty::decode)
-        })
-    } else {
-        let tcx = decoder.tcx();
-        Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
+    fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+        // Handle shorthands first, if we have an usize > 0x80.
+        let predicate_kind = if decoder.positioned_at_shorthand() {
+            let pos = decoder.read_usize()?;
+            assert!(pos >= SHORTHAND_OFFSET);
+            let shorthand = pos - SHORTHAND_OFFSET;
+
+            decoder.with_position(shorthand, ty::PredicateKind::decode)
+        } else {
+            ty::PredicateKind::decode(decoder)
+        }?;
+        let predicate = decoder.tcx().mk_predicate(predicate_kind);
+        Ok(predicate)
     }
 }
 
-#[inline]
-pub fn decode_predicate<D>(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    // Handle shorthands first, if we have an usize > 0x80.
-    if decoder.positioned_at_shorthand() {
-        let pos = decoder.read_usize()?;
-        assert!(pos >= SHORTHAND_OFFSET);
-        let shorthand = pos - SHORTHAND_OFFSET;
-
-        decoder.cached_predicate_for_shorthand(shorthand, |decoder| {
-            decoder.with_position(shorthand, ty::Predicate::decode)
-        })
-    } else {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for SubstsRef<'tcx> {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        let len = decoder.read_usize()?;
         let tcx = decoder.tcx();
-        Ok(tcx.mk_predicate(ty::PredicateKind::decode(decoder)?))
+        Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
     }
 }
 
-#[inline]
-pub fn decode_spanned_predicates<D>(
-    decoder: &mut D,
-) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let tcx = decoder.tcx();
-    Ok(tcx.arena.alloc_from_iter(
-        (0..decoder.read_usize()?)
-            .map(|_| Decodable::decode(decoder))
-            .collect::<Result<Vec<_>, _>>()?,
-    ))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        let local: mir::Local = Decodable::decode(decoder)?;
+        let len = decoder.read_usize()?;
+        let projection: &'tcx List<mir::PlaceElem<'tcx>> =
+            decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
+        Ok(mir::Place { local, projection })
+    }
 }
 
-#[inline]
-pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let len = decoder.read_usize()?;
-    let tcx = decoder.tcx();
-    Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
+    }
 }
 
-#[inline]
-pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let local: mir::Local = Decodable::decode(decoder)?;
-    let len = decoder.read_usize()?;
-    let projection: &'tcx List<mir::PlaceElem<'tcx>> =
-        decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
-    Ok(mir::Place { local, projection })
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        let len = decoder.read_usize()?;
+        let interned: Result<Vec<CanonicalVarInfo>, _> =
+            (0..len).map(|_| Decodable::decode(decoder)).collect();
+        Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
+    }
 }
 
-#[inline]
-pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        decoder.decode_alloc_id()
+    }
 }
 
-#[inline]
-pub fn decode_ty_slice<D>(decoder: &mut D) -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let len = decoder.read_usize()?;
-    Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
+    fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+        Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?))
+    }
 }
 
-#[inline]
-pub fn decode_adt_def<D>(decoder: &mut D) -> Result<&'tcx ty::AdtDef, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let def_id = DefId::decode(decoder)?;
-    Ok(decoder.tcx().adt_def(def_id))
+macro_rules! impl_decodable_via_ref {
+    ($($t:ty),+) => {
+        $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t {
+            fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+                RefDecodable::decode(decoder)
+            }
+        })*
+    }
 }
 
-#[inline]
-pub fn decode_symbol_name<D>(decoder: &mut D) -> Result<ty::SymbolName<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        let def_id = <DefId as Decodable<D>>::decode(decoder)?;
+        Ok(decoder.tcx().adt_def(def_id))
+    }
 }
 
-#[inline]
-pub fn decode_existential_predicate_slice<D>(
-    decoder: &mut D,
-) -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let len = decoder.read_usize()?;
-    Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        let len = decoder.read_usize()?;
+        Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
+    }
 }
 
-#[inline]
-pub fn decode_canonical_var_infos<D>(decoder: &mut D) -> Result<CanonicalVarInfos<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    let len = decoder.read_usize()?;
-    let interned: Result<Vec<CanonicalVarInfo>, _> =
-        (0..len).map(|_| Decodable::decode(decoder)).collect();
-    Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::ExistentialPredicate<'tcx>> {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        let len = decoder.read_usize()?;
+        Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
+    }
 }
 
-#[inline]
-pub fn decode_const<D>(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::Const<'tcx> {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
+    }
 }
 
-#[inline]
-pub fn decode_allocation<D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error>
-where
-    D: TyDecoder<'tcx>,
-{
-    Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for Allocation {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
+    }
+}
+
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] {
+    fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+        Ok(decoder.tcx().arena.alloc_from_iter(
+            (0..decoder.read_usize()?)
+                .map(|_| Decodable::decode(decoder))
+                .collect::<Result<Vec<_>, _>>()?,
+        ))
+    }
+}
+
+impl_decodable_via_ref! {
+    &'tcx ty::TypeckResults<'tcx>,
+    &'tcx ty::List<Ty<'tcx>>,
+    &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    &'tcx Allocation,
+    &'tcx mir::Body<'tcx>,
+    &'tcx mir::UnsafetyCheckResult,
+    &'tcx mir::BorrowCheckResult<'tcx>
 }
 
 #[macro_export]
@@ -320,42 +377,21 @@ fn $name(&mut self) -> Result<$ty, Self::Error> {
     }
 }
 
-#[macro_export]
 macro_rules! impl_arena_allocatable_decoder {
     ([]$args:tt) => {};
     ([decode $(, $attrs:ident)*]
-     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => {
-         // FIXME(#36588): These impls are horribly unsound as they allow
-         // the caller to pick any lifetime for `'tcx`, including `'static`.
-        #[allow(unused_lifetimes)]
-        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty>
-        for $DecoderName<$($typaram),*>
-        where &'_a $gen_ty: UseSpecializedDecodable
-        {
+     [[$name:ident: $ty:ty], $tcx:lifetime]) => {
+        impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for $ty {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> {
-                unsafe {
-                    std::mem::transmute::<
-                        Result<&$tcx $ty, Self::Error>,
-                        Result<&'_a $gen_ty, Self::Error>,
-                    >(decode_arena_allocable(self))
-                }
+            fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
+                decode_arena_allocable(decoder)
             }
         }
 
-        #[allow(unused_lifetimes)]
-        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]>
-        for $DecoderName<$($typaram),*>
-        where &'_a [$gen_ty]: UseSpecializedDecodable
-        {
+        impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for [$ty] {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
-                unsafe {
-                    std::mem::transmute::<
-                        Result<&$tcx [$ty], Self::Error>,
-                        Result<&'_a [$gen_ty], Self::Error>,
-                    >(decode_arena_allocable_slice(self))
-                }
+            fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
+                decode_arena_allocable_slice(decoder)
             }
         }
     };
@@ -364,38 +400,30 @@ fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
     };
 }
 
-#[macro_export]
 macro_rules! impl_arena_allocatable_decoders {
-    ($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
+    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
         $(
-            impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]);
+            impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]);
         )*
     }
 }
 
+rustc_hir::arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
+arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
+
 #[macro_export]
 macro_rules! implement_ty_decoder {
     ($DecoderName:ident <$($typaram:tt),*>) => {
         mod __ty_decoder_impl {
             use std::borrow::Cow;
-            use std::mem::transmute;
-
-            use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable};
-
-            use $crate::infer::canonical::CanonicalVarInfos;
-            use $crate::ty;
-            use $crate::ty::codec::*;
-            use $crate::ty::subst::InternalSubsts;
-            use rustc_hir::def_id::CrateNum;
-
-            use rustc_span::Span;
+            use rustc_serialize::Decoder;
 
             use super::$DecoderName;
 
             impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
                 type Error = String;
 
-                __impl_decoder_methods! {
+                $crate::__impl_decoder_methods! {
                     read_nil -> ();
 
                     read_u128 -> u128;
@@ -423,135 +451,6 @@ fn error(&mut self, err: &str) -> Self::Error {
                     self.opaque.error(err)
                 }
             }
-
-            // FIXME(#36588): These impls are horribly unsound as they allow
-            // the caller to pick any lifetime for `'tcx`, including `'static`.
-
-            arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
-
-            impl<$($typaram),*> SpecializedDecoder<CrateNum>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
-                    decode_cnum(self)
-                }
-            }
-
-            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>>
-            for $DecoderName<$($typaram),*>
-            where &'_x ty::TyS<'_y>: UseSpecializedDecodable
-            {
-                fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
-                    unsafe {
-                        transmute::<
-                            Result<ty::Ty<'tcx>, Self::Error>,
-                            Result<&'_x ty::TyS<'_y>, Self::Error>,
-                        >(decode_ty(self))
-                    }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<ty::Predicate<'_x>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Predicate<'_x>, Self::Error> {
-                    unsafe {
-                        transmute::<
-                            Result<ty::Predicate<'tcx>, Self::Error>,
-                            Result<ty::Predicate<'_x>, Self::Error>,
-                        >(decode_predicate(self))
-                    }
-                }
-            }
-
-            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]>
-            for $DecoderName<$($typaram),*>
-            where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable {
-                fn specialized_decode(&mut self)
-                                      -> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error>
-                {
-                    unsafe { transmute(decode_spanned_predicates(self)) }
-                }
-            }
-
-            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>>
-            for $DecoderName<$($typaram),*>
-            where &'_x InternalSubsts<'_y>: UseSpecializedDecodable {
-                fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> {
-                    unsafe { transmute(decode_substs(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(
-                    &mut self
-                ) -> Result<$crate::mir::Place<'_x>, Self::Error> {
-                    unsafe { transmute(decode_place(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<ty::Region<'_x>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Region<'_x>, Self::Error> {
-                    unsafe { transmute(decode_region(self)) }
-                }
-            }
-
-            impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>>
-            for $DecoderName<$($typaram),*>
-            where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable {
-                fn specialized_decode(&mut self)
-                                      -> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> {
-                    unsafe { transmute(decode_ty_slice(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> {
-                    unsafe { transmute(decode_adt_def(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<ty::SymbolName<'_x>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::SymbolName<'_x>, Self::Error> {
-                    unsafe { transmute(decode_symbol_name(self)) }
-                }
-            }
-
-            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List<ty::ExistentialPredicate<'_y>>>
-            for $DecoderName<$($typaram),*>
-            where &'_x ty::List<ty::ExistentialPredicate<'_y>>: UseSpecializedDecodable {
-                fn specialized_decode(&mut self)
-                    -> Result<&'_x ty::List<ty::ExistentialPredicate<'_y>>, Self::Error> {
-                        unsafe { transmute(decode_existential_predicate_slice(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<CanonicalVarInfos<'_x>>
-                for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self)
-                    -> Result<CanonicalVarInfos<'_x>, Self::Error> {
-                        unsafe { transmute(decode_canonical_var_infos(self)) }
-                }
-            }
-
-            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>>
-            for $DecoderName<$($typaram),*>
-            where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable {
-                fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> {
-                    unsafe { transmute(decode_const(self)) }
-                }
-            }
-
-            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(
-                    &mut self
-                ) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> {
-                    unsafe { transmute(decode_allocation(self)) }
-                }
-            }
         }
-    };
+    }
 }
index c0b5693dc594e0586498b13fa5e1a1eb4d2700cd..64faacc1c0bc2dc8d746420b33b3f6320aed4563 100644 (file)
@@ -15,7 +15,7 @@
 pub use kind::*;
 
 /// Typed constant value.
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
 #[derive(HashStable)]
 pub struct Const<'tcx> {
     pub ty: Ty<'tcx>,
@@ -88,7 +88,7 @@ pub fn from_opt_const_arg_anon_const(
             ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
                 // Find the name and index of the const parameter by indexing the generics of
                 // the parent item and construct a `ParamConst`.
-                let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                 let item_id = tcx.hir().get_parent_node(hir_id);
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id.to_def_id());
index e8a1e714a8f43885a9a5c65d39525fe3722930e5..ede28522000afcde48b0b1d645b2db3737845030 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_target::abi::Size;
 
 /// Represents a constant in Rust.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
 pub enum ConstKind<'tcx> {
     /// A const generic parameter.
@@ -34,7 +34,7 @@ pub enum ConstKind<'tcx> {
 
     /// A placeholder for a const which could not be computed; this is
     /// propagated to avoid useless error messages.
-    Error(ty::sty::DelaySpanBugEmitted),
+    Error(ty::DelaySpanBugEmitted),
 }
 
 #[cfg(target_arch = "x86_64")]
@@ -68,7 +68,7 @@ pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
 }
 
 /// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
 #[derive(HashStable)]
 pub enum InferConst<'tcx> {
     /// Infer the value of the const.
index d6bcfbf49cff12b2c67c7800d16231d9f637bc52..d7eeaafbf46bfb467ce4aad3f8992b897ab15265 100644 (file)
 use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
 use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
 use crate::traits;
+use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::steal::Steal;
 use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
 use crate::ty::TyKind::*;
 use crate::ty::{
-    self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
-    DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
-    IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
+    self, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree,
+    ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntVar,
+    IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
     ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
     TyVid, TypeAndMut,
 };
 use std::ops::{Bound, Deref};
 use std::sync::Arc;
 
+/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
+/// except through `tcx.err*()`, which are in this module.
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
+pub struct DelaySpanBugEmitted(());
+
 type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
@@ -263,7 +270,7 @@ pub fn remove(&mut self, id: hir::HirId) -> Option<V> {
 }
 
 /// All information necessary to validate and reveal an `impl Trait`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
 pub struct ResolvedOpaqueTy<'tcx> {
     /// The revealed type as seen by this function.
     pub concrete_type: Ty<'tcx>,
@@ -291,7 +298,7 @@ pub struct ResolvedOpaqueTy<'tcx> {
 ///
 /// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
 /// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
 pub struct GeneratorInteriorTypeCause<'tcx> {
     /// Type of the captured binding.
     pub ty: Ty<'tcx>,
@@ -305,7 +312,7 @@ pub struct GeneratorInteriorTypeCause<'tcx> {
     pub expr: Option<hir::HirId>,
 }
 
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(TyEncodable, TyDecodable, Debug)]
 pub struct TypeckResults<'tcx> {
     /// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
     pub hir_owner: LocalDefId,
@@ -728,7 +735,7 @@ pub struct UserTypeAnnotationIndex {
 pub type CanonicalUserTypeAnnotations<'tcx> =
     IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct CanonicalUserTypeAnnotation<'tcx> {
     pub user_ty: CanonicalUserType<'tcx>,
     pub span: Span,
@@ -787,7 +794,7 @@ pub fn is_identity(&self) -> bool {
 /// A user-given type annotation attached to a constant. These arise
 /// from constants that are named via paths, like `Foo::<A>::new` and
 /// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub enum UserType<'tcx> {
     Ty(Ty<'tcx>),
@@ -1170,7 +1177,7 @@ pub fn ty_error(self) -> Ty<'tcx> {
     #[track_caller]
     pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
         self.sess.delay_span_bug(span, msg);
-        self.mk_ty(Error(super::sty::DelaySpanBugEmitted(())))
+        self.mk_ty(Error(DelaySpanBugEmitted(())))
     }
 
     /// Like `err` but for constants.
@@ -1178,10 +1185,7 @@ pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty
     pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
         self.sess
             .delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
-        self.mk_const(ty::Const {
-            val: ty::ConstKind::Error(super::sty::DelaySpanBugEmitted(())),
-            ty,
-        })
+        self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
     }
 
     pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
@@ -1333,7 +1337,7 @@ pub fn allocate_metadata_dep_nodes(self) {
 
     pub fn serialize_query_result_cache<E>(self, encoder: &mut E) -> Result<(), E::Error>
     where
-        E: ty::codec::TyEncoder,
+        E: ty::codec::OpaqueEncoder,
     {
         self.queries.on_disk_cache.serialize(self, encoder)
     }
@@ -1420,7 +1424,7 @@ pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo>
             _ => return None, // not a free region
         };
 
-        let hir_id = self.hir().as_local_hir_id(suitable_region_binding_scope);
+        let hir_id = self.hir().local_def_id_to_hir_id(suitable_region_binding_scope);
         let is_impl_item = match self.hir().find(hir_id) {
             Some(Node::Item(..) | Node::TraitItem(..)) => false,
             Some(Node::ImplItem(..)) => {
@@ -1441,7 +1445,7 @@ pub fn return_type_impl_or_dyn_traits(
         &self,
         scope_def_id: LocalDefId,
     ) -> Vec<&'tcx hir::Ty<'tcx>> {
-        let hir_id = self.hir().as_local_hir_id(scope_def_id);
+        let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
         let hir_output = match self.hir().get(hir_id) {
             Node::Item(hir::Item {
                 kind:
@@ -1486,7 +1490,7 @@ pub fn return_type_impl_or_dyn_traits(
 
     pub fn return_type_impl_trait(&self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
         // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
-        let hir_id = self.hir().as_local_hir_id(scope_def_id);
+        let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
         match self.hir().get(hir_id) {
             Node::Item(item) => {
                 match item.kind {
@@ -2615,6 +2619,21 @@ pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetime
     }
 }
 
+impl TyCtxtAt<'tcx> {
+    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
+    #[track_caller]
+    pub fn ty_error(self) -> Ty<'tcx> {
+        self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
+    }
+
+    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+    /// ensure it gets used.
+    #[track_caller]
+    pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+        self.tcx.ty_error_with_message(self.span, msg)
+    }
+}
+
 pub trait InternAs<T: ?Sized, R> {
     type Output;
     fn intern_with<F>(self, f: F) -> Self::Output
index 30ff5a2d9ebdfcd660dbd4c48eee1971204471d5..438da832226d72c68c58074905c505ba12272a4d 100644 (file)
@@ -403,7 +403,7 @@ pub fn note_and_explain_type_err(
                             .type_param(p, self)
                             .def_id
                             .as_local()
-                            .map(|id| hir.as_local_hir_id(id))
+                            .map(|id| hir.local_def_id_to_hir_id(id))
                             .and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
                             .as_ref()
                             .and_then(|node| node.generics())
@@ -791,10 +791,11 @@ fn point_at_associated_type(
         body_owner_def_id: DefId,
         found: Ty<'tcx>,
     ) -> bool {
-        let hir_id = match body_owner_def_id.as_local().map(|id| self.hir().as_local_hir_id(id)) {
-            Some(hir_id) => hir_id,
-            None => return false,
-        };
+        let hir_id =
+            match body_owner_def_id.as_local().map(|id| self.hir().local_def_id_to_hir_id(id)) {
+                Some(hir_id) => hir_id,
+                None => return false,
+            };
         // When `body_owner` is an `impl` or `trait` item, look in its associated types for
         // `expected` and point at it.
         let parent_id = self.hir().get_parent_item(hir_id);
index b0fb179b18bdfbaecc242c11802e45c46843b99f..7456020ee9b679ff414c7c93c830672e4efcea83 100644 (file)
@@ -17,7 +17,7 @@
 /// because we sometimes need to use SimplifiedTypeGen values as stable sorting
 /// keys (in which case we use a DefPathHash as id-type) but in the general case
 /// the non-stable but fast to construct DefId-version is the better choice.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
 pub enum SimplifiedTypeGen<D>
 where
     D: Copy + Debug + Ord + Eq,
index 2def000da648086d7acdaf216c7d9fcffd050c00..e6dafd4965bc9fb321568a1af6d9be3e738a7927 100644 (file)
 /// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
 /// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval
 /// will do all required substitution as they run.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, Lift)]
 pub struct Instance<'tcx> {
     pub def: InstanceDef<'tcx>,
     pub substs: SubstsRef<'tcx>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum InstanceDef<'tcx> {
     /// A user-defined callable item.
     ///
index 5aa94ba3d09fd0b46229b4396b08395f45047994..16e65d2cca4cbcfed06447c84d90c7dcc04053d0 100644 (file)
@@ -165,7 +165,7 @@ fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 /// - For a slice, this is the length.
 pub const FAT_PTR_EXTRA: usize = 1;
 
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
     SizeOverflow(Ty<'tcx>),
index 92d6dbb5f90f557fb59ab4d2959a193a0112572c..fe390adf89f9fe70c32c94338f69807f3f7821e3 100644 (file)
@@ -76,9 +76,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<T: Encodable> Encodable for List<T> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
     #[inline]
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for &List<T> {
+    #[inline]
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
index 6798addb8aaa3a0c35d653f9347356132be259b6..3c79fe12255799fc581a5ebdfb78ca9eb3482aab 100644 (file)
@@ -60,6 +60,7 @@
 pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
 pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig};
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts};
+pub use self::sty::{ClosureSubstsParts, GeneratorSubstsParts};
 pub use self::sty::{ConstVid, FloatVid, IntVid, RegionVid, TyVid};
 pub use self::sty::{ExistentialPredicate, InferTy, ParamConst, ParamTy, ProjectionTy};
 pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
@@ -72,8 +73,8 @@
 
 pub use self::context::{tls, FreeRegionInfo, TyCtxt};
 pub use self::context::{
-    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
-    UserType, UserTypeAnnotationIndex,
+    CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+    DelaySpanBugEmitted, ResolvedOpaqueTy, UserType, UserTypeAnnotationIndex,
 };
 pub use self::context::{
     CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckResults,
 
 pub use self::consts::{Const, ConstInt, ConstKind, InferConst};
 
+pub mod _match;
 pub mod adjustment;
 pub mod binding;
 pub mod cast;
-#[macro_use]
 pub mod codec;
-pub mod _match;
 mod erase_regions;
 pub mod error;
 pub mod fast_reject;
@@ -171,7 +171,7 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
 pub enum ImplPolarity {
     /// `impl Trait for Type`
     Positive,
@@ -316,7 +316,7 @@ pub fn find_by_name_and_namespace(
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
@@ -403,7 +403,7 @@ pub fn is_visible_locally(self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyDecodable, TyEncodable, HashStable)]
 pub enum Variance {
     Covariant,     // T<A> <: T<B> iff A <: B -- e.g., function return type
     Invariant,     // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@@ -652,13 +652,9 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 #[rustc_diagnostic_item = "Ty"]
 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
 
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Ty<'tcx> {}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<Ty<'tcx>> {}
-
 pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>;
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub struct UpvarPath {
     pub hir_id: hir::HirId,
 }
@@ -666,13 +662,13 @@ pub struct UpvarPath {
 /// Upvars do not get their own `NodeId`. Instead, we use the pair of
 /// the original var ID (that is, the root variable that is referenced
 /// by the upvar) and the ID of the closure expression.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
 pub struct UpvarId {
     pub var_path: UpvarPath,
     pub closure_expr_id: LocalDefId,
 }
 
-#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)]
+#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
     ImmBorrow,
@@ -720,7 +716,7 @@ pub enum BorrowKind {
 
 /// Information describing the capture of an upvar. This is computed
 /// during `typeck`, specifically by `regionck`.
-#[derive(PartialEq, Clone, Debug, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
 pub enum UpvarCapture<'tcx> {
     /// Upvar is captured by value. This is always true when the
     /// closure is labeled `move`, but can also be true in other cases
@@ -731,7 +727,7 @@ pub enum UpvarCapture<'tcx> {
     ByRef(UpvarBorrow<'tcx>),
 }
 
-#[derive(PartialEq, Clone, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)]
 pub struct UpvarBorrow<'tcx> {
     /// The kind of borrow: by-ref upvars have access to shared
     /// immutable borrows, which are not part of the normal language
@@ -766,7 +762,7 @@ pub fn has_name(&self) -> bool {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub enum GenericParamDefKind {
     Lifetime,
     Type {
@@ -787,7 +783,7 @@ pub fn descr(&self) -> &'static str {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct GenericParamDef {
     pub name: Symbol,
     pub def_id: DefId,
@@ -831,7 +827,7 @@ pub struct GenericParamCount {
 ///
 /// The ordering of parameters is the same as in `Subst` (excluding child generics):
 /// `Self` (optionally), `Lifetime` params..., `Type` params...
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct Generics {
     pub parent: Option<DefId>,
     pub parent_count: usize,
@@ -933,7 +929,7 @@ pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &Generi
 }
 
 /// Bounds on generics.
-#[derive(Copy, Clone, Default, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
 pub struct GenericPredicates<'tcx> {
     pub parent: Option<DefId>,
     pub predicates: &'tcx [(Predicate<'tcx>, Span)],
@@ -1025,9 +1021,6 @@ pub struct Predicate<'tcx> {
     inner: &'tcx PredicateInner<'tcx>,
 }
 
-impl rustc_serialize::UseSpecializedEncodable for Predicate<'_> {}
-impl rustc_serialize::UseSpecializedDecodable for Predicate<'_> {}
-
 impl<'tcx> PartialEq for Predicate<'tcx> {
     fn eq(&self, other: &Self) -> bool {
         // `self.kind` is always interned.
@@ -1103,7 +1096,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum PredicateKind<'tcx> {
     /// `for<'a>: ...`
@@ -1111,7 +1104,7 @@ pub enum PredicateKind<'tcx> {
     Atom(PredicateAtom<'tcx>),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum PredicateAtom<'tcx> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
@@ -1261,7 +1254,7 @@ pub fn subst_supertrait(
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>,
@@ -1286,7 +1279,7 @@ pub fn def_id(self) -> DefId {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
 pub type PolyOutlivesPredicate<A, B> = ty::Binder<OutlivesPredicate<A, B>>;
@@ -1295,7 +1288,7 @@ pub fn def_id(self) -> DefId {
 pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>;
 pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>;
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct SubtypePredicate<'tcx> {
     pub a_is_expected: bool,
@@ -1316,7 +1309,7 @@ pub struct SubtypePredicate<'tcx> {
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct ProjectionPredicate<'tcx> {
     pub projection_ty: ProjectionTy<'tcx>,
@@ -1585,7 +1578,7 @@ pub fn cannot_name(self, other: UniverseIndex) -> bool {
 /// basically a name -- distinct bound regions within the same
 /// universe are just two regions with an unknown relationship to one
 /// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub struct Placeholder<T> {
     pub universe: UniverseIndex,
     pub name: T,
@@ -1635,7 +1628,7 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 ///     a.foo::<7>();
 /// }
 /// ```
-#[derive(Copy, Clone, Debug, TypeFoldable, Lift, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)]
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 #[derive(Hash, HashStable)]
 pub struct WithOptConstParam<T> {
@@ -2106,7 +2099,7 @@ pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef>
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub enum VariantDiscr {
     /// Explicit value for this variant, i.e., `X = 123`.
     /// The `DefId` corresponds to the embedded constant.
@@ -2178,14 +2171,12 @@ fn hash<H: Hasher>(&self, s: &mut H) {
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for &'tcx AdtDef {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for AdtDef {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         self.did.encode(s)
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx AdtDef {}
-
 impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         thread_local! {
@@ -2229,7 +2220,7 @@ fn into(self) -> DataTypeKind {
 }
 
 bitflags! {
-    #[derive(RustcEncodable, RustcDecodable, Default, HashStable)]
+    #[derive(TyEncodable, TyDecodable, Default, HashStable)]
     pub struct ReprFlags: u8 {
         const IS_C               = 1 << 0;
         const IS_SIMD            = 1 << 1;
@@ -2246,7 +2237,7 @@ pub struct ReprFlags: u8 {
 }
 
 /// Represents the repr options provided by the user,
-#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default, HashStable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)]
 pub struct ReprOptions {
     pub int: Option<attr::IntType>,
     pub align: Option<Align>,
@@ -2690,7 +2681,7 @@ pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
 ///
 /// You can get the environment type of a closure using
 /// `tcx.closure_env_ty()`.
-#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum ClosureKind {
     // Warning: Ordering is significant here! The ordering is chosen
@@ -2845,12 +2836,12 @@ pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'
     pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
         def_id
             .as_local()
-            .and_then(|def_id| self.hir().get(self.hir().as_local_hir_id(def_id)).ident())
+            .and_then(|def_id| self.hir().get(self.hir().local_def_id_to_hir_id(def_id)).ident())
     }
 
     pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
         let is_associated_item = if let Some(def_id) = def_id.as_local() {
-            match self.hir().get(self.hir().as_local_hir_id(def_id)) {
+            match self.hir().get(self.hir().local_def_id_to_hir_id(def_id)) {
                 Node::TraitItem(_) | Node::ImplItem(_) => true,
                 _ => false,
             }
@@ -3009,7 +3000,7 @@ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
     /// Gets the attributes of a definition.
     pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> {
         if let Some(did) = did.as_local() {
-            self.hir().attrs(self.hir().as_local_hir_id(did))
+            self.hir().attrs(self.hir().local_def_id_to_hir_id(did))
         } else {
             self.item_attrs(did)
         }
@@ -3048,7 +3039,7 @@ pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
     /// with the name of the crate containing the impl.
     pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
         if let Some(impl_did) = impl_did.as_local() {
-            let hir_id = self.hir().as_local_hir_id(impl_did);
+            let hir_id = self.hir().local_def_id_to_hir_id(impl_did);
             Ok(self.hir().span(hir_id))
         } else {
             Err(self.crate_name(impl_did.krate))
@@ -3109,7 +3100,7 @@ pub fn is_object_safe(self, key: DefId) -> bool {
 /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
 pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     if let Some(def_id) = def_id.as_local() {
-        if let Node::Item(item) = tcx.hir().get(tcx.hir().as_local_hir_id(def_id)) {
+        if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
             if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
                 return opaque_ty.impl_trait_fn;
             }
@@ -3141,7 +3132,7 @@ pub struct CrateInherentImpls {
     pub inherent_impls: DefIdMap<Vec<DefId>>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
 pub struct SymbolName<'tcx> {
     /// `&str` gives a consistent ordering, which ensures reproducible builds.
     pub name: &'tcx str,
@@ -3166,12 +3157,3 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(&self.name, fmt)
     }
 }
-
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for SymbolName<'tcx> {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(self.name)
-    }
-}
-
-// The decoding takes place in `decode_symbol_name()`.
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for SymbolName<'tcx> {}
index 87944db60de66d8e7b7ede44364d6756363e34bf..fc444d4cc5b52635dd52973832189c53973317c5 100644 (file)
@@ -610,7 +610,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
 
                 // FIXME(eddyb) should use `def_span`.
                 if let Some(did) = did.as_local() {
-                    let hir_id = self.tcx().hir().as_local_hir_id(did);
+                    let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
                     let span = self.tcx().hir().span(hir_id);
                     p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
 
@@ -656,7 +656,7 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
 
                 // FIXME(eddyb) should use `def_span`.
                 if let Some(did) = did.as_local() {
-                    let hir_id = self.tcx().hir().as_local_hir_id(did);
+                    let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
                     if self.tcx().sess.opts.debugging_opts.span_free_formats {
                         p!(write("@"), print_def_path(did.to_def_id(), substs));
                     } else {
index b39c0b5190a6d951c59cae210ccbd49dcee06544..4d820f75c56c457da3cb5a12e1c30cf5df6f1202 100644 (file)
@@ -43,7 +43,7 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
 use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
 use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
index 08b0bfecf49099ec0642a466c1e3d4c80fdc8dec..007b46b11769413aeb924d68f9404ca52c2b7c9e 100644 (file)
@@ -1,28 +1,24 @@
 use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
-use crate::mir::interpret;
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
+use crate::mir::{self, interpret};
+use crate::ty::codec::{OpaqueEncoder, RefDecodable, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_serialize::{
-    opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
-    UseSpecializedDecodable, UseSpecializedEncodable,
-};
+use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{
     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
     SyntaxContext, SyntaxContextData,
 };
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
-use rustc_span::symbol::Ident;
 use rustc_span::CachingSourceMapView;
 use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
 use std::mem;
@@ -87,7 +83,7 @@ pub struct OnDiskCache<'sess> {
 }
 
 // This type is used only for serialization and deserialization.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
     prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
@@ -105,10 +101,10 @@ struct Footer {
 type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
 type EncodedDiagnostics = Vec<Diagnostic>;
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
 struct SourceFileIndex(u32);
 
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
 struct AbsoluteBytePos(u32);
 
 impl AbsoluteBytePos {
@@ -182,7 +178,7 @@ pub fn new_empty(source_map: &'sess SourceMap) -> Self {
 
     pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error>
     where
-        E: TyEncoder,
+        E: OpaqueEncoder,
     {
         // Serializing the `DepGraph` should not modify it.
         tcx.dep_graph.with_ignore(|| {
@@ -333,7 +329,7 @@ macro_rules! encode_queries {
 
             // Encode the position of the footer as the last 8 bytes of the
             // file so we know where to look for it.
-            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
+            IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder.opaque())?;
 
             // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
             // of the footer must be the last thing in the data stream.
@@ -380,13 +376,13 @@ pub fn store_diagnostics(
 
     /// Returns the cached query result if there is something in the cache for
     /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
-    pub fn try_load_query_result<T>(
+    crate fn try_load_query_result<'tcx, T>(
         &self,
-        tcx: TyCtxt<'_>,
+        tcx: TyCtxt<'tcx>,
         dep_node_index: SerializedDepNodeIndex,
     ) -> Option<T>
     where
-        T: Decodable,
+        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
     {
         self.load_indexed(tcx, dep_node_index, &self.query_result_index, "query result")
     }
@@ -417,7 +413,7 @@ fn load_indexed<'tcx, T>(
         debug_tag: &'static str,
     ) -> Option<T>
     where
-        T: Decodable,
+        T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
     {
         let pos = index.get(&dep_node_index).cloned()?;
 
@@ -427,14 +423,14 @@ fn load_indexed<'tcx, T>(
         })
     }
 
-    fn with_decoder<'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+    fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
         &'sess self,
         tcx: TyCtxt<'tcx>,
         pos: AbsoluteBytePos,
         f: F,
     ) -> T
     where
-        T: Decodable,
+        T: Decodable<CacheDecoder<'a, 'tcx>>,
     {
         let cnum_map =
             self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
@@ -492,7 +488,7 @@ fn compute_cnum_map(
 /// A decoder that can read from the incr. comp. cache. It is similar to the one
 /// we use for crate metadata decoding in that it can rebase spans and eventually
 /// will also handle things that contain `Ty` instances.
-struct CacheDecoder<'a, 'tcx> {
+crate struct CacheDecoder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     opaque: opaque::Decoder<'a>,
     source_map: &'a SourceMap,
@@ -547,8 +543,8 @@ fn position(&self) -> usize {
 // tag matches and the correct amount of bytes was read.
 fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
 where
-    T: Decodable + Eq + ::std::fmt::Debug,
-    V: Decodable,
+    T: Decodable<D> + Eq + ::std::fmt::Debug,
+    V: Decodable<D>,
     D: DecoderWithPosition,
 {
     let start_pos = decoder.position();
@@ -565,6 +561,8 @@ fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Erro
 }
 
 impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
+    const CLEAR_CROSS_CRATE: bool = false;
+
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
@@ -642,14 +640,19 @@ fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
         self.cnum_map[cnum].unwrap_or_else(|| bug!("could not find new `CrateNum` for {:?}", cnum))
     }
+
+    fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
+        let alloc_decoding_session = self.alloc_decoding_session;
+        alloc_decoding_session.decode_alloc_id(self)
+    }
 }
 
-implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
+crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
 
-impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
-        let syntax_contexts = self.syntax_contexts;
-        rustc_span::hygiene::decode_syntax_context(self, self.hygiene_context, |this, id| {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let syntax_contexts = decoder.syntax_contexts;
+        rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
             // This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
             // We look up the position of the associated `SyntaxData` and decode it.
             let pos = syntax_contexts.get(&id).unwrap();
@@ -661,12 +664,12 @@ fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<ExpnId> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
-        let expn_data = self.expn_data;
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let expn_data = decoder.expn_data;
         rustc_span::hygiene::decode_expn_id(
-            self,
-            ExpnDataDecodeMode::incr_comp(self.hygiene_context),
+            decoder,
+            ExpnDataDecodeMode::incr_comp(decoder.hygiene_context),
             |this, index| {
                 // This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
                 // We look up the position of the associated `ExpnData` and decode it.
@@ -683,16 +686,9 @@ fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
-        let alloc_decoding_session = self.alloc_decoding_session;
-        alloc_decoding_session.decode_alloc_id(self)
-    }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
-        let tag: u8 = Decodable::decode(self)?;
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
+    fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let tag: u8 = Decodable::decode(decoder)?;
 
         if tag == TAG_INVALID_SPAN {
             return Ok(DUMMY_SP);
@@ -700,13 +696,13 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
             debug_assert_eq!(tag, TAG_VALID_SPAN);
         }
 
-        let file_lo_index = SourceFileIndex::decode(self)?;
-        let line_lo = usize::decode(self)?;
-        let col_lo = BytePos::decode(self)?;
-        let len = BytePos::decode(self)?;
-        let ctxt = SyntaxContext::decode(self)?;
+        let file_lo_index = SourceFileIndex::decode(decoder)?;
+        let line_lo = usize::decode(decoder)?;
+        let col_lo = BytePos::decode(decoder)?;
+        let len = BytePos::decode(decoder)?;
+        let ctxt = SyntaxContext::decode(decoder)?;
 
-        let file_lo = self.file_index_to_file(file_lo_index);
+        let file_lo = decoder.file_index_to_file(file_lo_index);
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
@@ -714,10 +710,10 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<Ident> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
-        // FIXME: Handle hygiene in incremental
-        bug!("Trying to decode Ident for incremental");
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let cnum = CrateNum::from_u32(u32::decode(d)?);
+        Ok(d.map_encoded_cnum_to_current(cnum))
     }
 }
 
@@ -725,43 +721,69 @@ fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
 // `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
 // because we would not know how to transform the `DefIndex` to the current
 // context.
-impl<'a, 'tcx> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
-        bug!("trying to decode `DefIndex` outside the context of a `DefId`")
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<DefIndex, String> {
+        Err(d.error("trying to decode `DefIndex` outside the context of a `DefId`"))
     }
 }
 
 // Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
 // compilation sessions. We use the `DefPathHash`, which is stable across
 // sessions, to map the old `DefId` to the new one.
-impl<'a, 'tcx> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx> {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         // Load the `DefPathHash` which is was we encoded the `DefId` as.
-        let def_path_hash = DefPathHash::decode(self)?;
+        let def_path_hash = DefPathHash::decode(d)?;
 
         // Using the `DefPathHash`, we can lookup the new `DefId`.
-        Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
+        Ok(d.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx> {
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
-        Ok(DefId::decode(self)?.expect_local())
+impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> {
+    fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error> {
+        Fingerprint::decode_opaque(&mut self.opaque)
     }
 }
 
-impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx> {
-    fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
-        Fingerprint::decode_opaque(&mut self.opaque)
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+    for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
+{
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+    for &'tcx [rustc_ast::ast::InlineAsmTemplatePiece]
+{
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
+    }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Span] {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        RefDecodable::decode(d)
     }
 }
 
 //- ENCODING -------------------------------------------------------------------
 
 /// An encoder that can write the incr. comp. cache.
-struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> {
+struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
     tcx: TyCtxt<'tcx>,
     encoder: &'a mut E,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@@ -774,7 +796,7 @@ struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> {
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
     fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
         self.file_to_file_index[&(&*source_file as *const SourceFile)]
@@ -785,7 +807,7 @@ fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex
     /// encode the specified tag, then the given value, then the number of
     /// bytes taken up by tag and value. On decoding, we can then verify that
     /// we get the expected tag and read the expected number of bytes.
-    fn encode_tagged<T: Encodable, V: Encodable>(
+    fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
         &mut self,
         tag: T,
         value: &V,
@@ -800,170 +822,111 @@ fn encode_tagged<T: Encodable, V: Encodable>(
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
-        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
-        index.encode(self)
+impl<'a, 'tcx> FingerprintEncoder for CacheEncoder<'a, 'tcx, rustc_serialize::opaque::Encoder> {
+    fn encode_fingerprint(&mut self, f: &Fingerprint) -> opaque::EncodeResult {
+        f.encode_opaque(self.encoder)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<SyntaxContext> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    fn specialized_encode(&mut self, ctxt: &SyntaxContext) -> Result<(), Self::Error> {
-        rustc_span::hygiene::raw_encode_syntax_context(*ctxt, self.hygiene_context, self)
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<ExpnId> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         rustc_span::hygiene::raw_encode_expn_id(
-            *expn,
-            self.hygiene_context,
+            *self,
+            s.hygiene_context,
             ExpnDataEncodeMode::IncrComp,
-            self,
+            s,
         )
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
-        if *span == DUMMY_SP {
-            return TAG_INVALID_SPAN.encode(self);
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        if *self == DUMMY_SP {
+            return TAG_INVALID_SPAN.encode(s);
         }
 
-        let span_data = span.data();
-        let (file_lo, line_lo, col_lo) =
-            match self.source_map.byte_pos_to_line_and_col(span_data.lo) {
-                Some(pos) => pos,
-                None => return TAG_INVALID_SPAN.encode(self),
-            };
+        let span_data = self.data();
+        let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
+            Some(pos) => pos,
+            None => return TAG_INVALID_SPAN.encode(s),
+        };
 
         if !file_lo.contains(span_data.hi) {
-            return TAG_INVALID_SPAN.encode(self);
+            return TAG_INVALID_SPAN.encode(s);
         }
 
         let len = span_data.hi - span_data.lo;
 
-        let source_file_index = self.source_file_index(file_lo);
+        let source_file_index = s.source_file_index(file_lo);
 
-        TAG_VALID_SPAN.encode(self)?;
-        source_file_index.encode(self)?;
-        line_lo.encode(self)?;
-        col_lo.encode(self)?;
-        len.encode(self)?;
-        span_data.ctxt.encode(self)?;
-        Ok(())
+        TAG_VALID_SPAN.encode(s)?;
+        source_file_index.encode(s)?;
+        line_lo.encode(s)?;
+        col_lo.encode(s)?;
+        len.encode(s)?;
+        span_data.ctxt.encode(s)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<Ident> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + ty_codec::TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    fn specialized_encode(&mut self, _: &Ident) -> Result<(), Self::Error> {
-        // We don't currently encode enough information to ensure hygiene works
-        // with incremental, so panic rather than risk incremental bugs.
+    const CLEAR_CROSS_CRATE: bool = false;
 
-        // FIXME: handle hygiene in incremental.
-        bug!("trying to encode `Ident` for incremental");
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
     }
-}
-
-impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
     fn position(&self) -> usize {
-        self.encoder.position()
+        self.encoder.encoder_position()
     }
-}
-
-impl<'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
-    fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
-        self.emit_u32(cnum.as_u32())
+    fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
+        &mut self.type_shorthands
     }
-}
-
-impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-    &'b ty::TyS<'c>: UseSpecializedEncodable,
-{
-    #[inline]
-    fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> {
-        debug_assert!(self.tcx.lift(ty).is_some());
-        let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) };
-        ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands)
-    }
-}
-
-impl<'a, 'b, 'tcx, E> SpecializedEncoder<ty::Predicate<'b>> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
-    fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> {
-        debug_assert!(self.tcx.lift(predicate).is_some());
-        let predicate =
-            unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) };
-        ty_codec::encode_with_shorthand(self, predicate, |encoder| {
-            &mut encoder.predicate_shorthands
-        })
+    fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize> {
+        &mut self.predicate_shorthands
     }
-}
+    fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
+        let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
 
-impl<'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-{
-    #[inline]
-    fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
-        let def_path_hash = self.tcx.def_path_hash(*id);
-        def_path_hash.encode(self)
+        index.encode(self)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    #[inline]
-    fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
-        id.to_def_id().encode(self)
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+        let def_path_hash = s.tcx.def_path_hash(*self);
+        def_path_hash.encode(s)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
-    fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
+    fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         bug!("encoding `DefIndex` without context");
     }
 }
 
-impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for CacheEncoder<'a, 'tcx, opaque::Encoder> {
-    fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
-        f.encode_opaque(&mut self.encoder)
-    }
-}
-
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
         #[inline]
@@ -975,7 +938,7 @@ macro_rules! encoder_methods {
 
 impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
 where
-    E: 'a + TyEncoder,
+    E: 'a + OpaqueEncoder,
 {
     type Error = E::Error;
 
@@ -1014,32 +977,29 @@ impl IntEncodedWithFixedSize {
     pub const ENCODED_SIZE: usize = 8;
 }
 
-impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
-impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
-
-impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
-    fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
-        let start_pos = self.position();
+impl Encodable<opaque::Encoder> for IntEncodedWithFixedSize {
+    fn encode(&self, e: &mut opaque::Encoder) -> Result<(), !> {
+        let start_pos = e.position();
         for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
-            ((x.0 >> (i * 8)) as u8).encode(self)?;
+            ((self.0 >> (i * 8)) as u8).encode(e)?;
         }
-        let end_pos = self.position();
+        let end_pos = e.position();
         assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
         Ok(())
     }
 }
 
-impl<'a> SpecializedDecoder<IntEncodedWithFixedSize> for opaque::Decoder<'a> {
-    fn specialized_decode(&mut self) -> Result<IntEncodedWithFixedSize, Self::Error> {
+impl<'a> Decodable<opaque::Decoder<'a>> for IntEncodedWithFixedSize {
+    fn decode(decoder: &mut opaque::Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> {
         let mut value: u64 = 0;
-        let start_pos = self.position();
+        let start_pos = decoder.position();
 
         for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
-            let byte: u8 = Decodable::decode(self)?;
+            let byte: u8 = Decodable::decode(decoder)?;
             value |= (byte as u64) << (i * 8);
         }
 
-        let end_pos = self.position();
+        let end_pos = decoder.position();
         assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
 
         Ok(IntEncodedWithFixedSize(value))
@@ -1053,8 +1013,8 @@ fn encode_query_results<'a, 'tcx, Q, E>(
 ) -> Result<(), E::Error>
 where
     Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
-    Q::Value: Encodable,
-    E: 'a + TyEncoder,
+    Q::Value: Encodable<CacheEncoder<'a, 'tcx, E>>,
+    E: 'a + OpaqueEncoder,
 {
     let _timer = tcx
         .sess
@@ -1066,15 +1026,16 @@ fn encode_query_results<'a, 'tcx, Q, E>(
 
     state.iter_results(|results| {
         for (key, value, dep_node) in results {
-            if Q::cache_on_disk(tcx, &key, Some(&value)) {
+            if Q::cache_on_disk(tcx, &key, Some(value)) {
                 let dep_node = SerializedDepNodeIndex::new(dep_node.index());
 
                 // Record position of the cache entry.
-                query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
+                query_result_index
+                    .push((dep_node, AbsoluteBytePos::new(encoder.encoder.opaque().position())));
 
                 // Encode the type check tables with the `SerializedDepNodeIndex`
                 // as tag.
-                encoder.encode_tagged(dep_node, &value)?;
+                encoder.encode_tagged(dep_node, value)?;
             }
         }
         Ok(())
index 0683dc0201129bddca91b54fc36d3a10b1df3c7f..9b1837356e3053df7778812c8de0e2b1864b1d49 100644 (file)
@@ -1,8 +1,9 @@
 use crate::ty::context::TyCtxt;
+use crate::ty::WithOptConstParam;
 use measureme::{StringComponent, StringId};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::profiling::SelfProfiler;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
 use rustc_query_system::query::QueryCache;
 use rustc_query_system::query::QueryState;
@@ -154,6 +155,49 @@ fn spec_to_self_profile_string(
     }
 }
 
+impl SpecIntoSelfProfilingString for LocalDefId {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
+    }
+}
+
+impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
+        // We print `WithOptConstParam` values as tuples to make them shorter
+        // and more readable, without losing information:
+        //
+        // "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
+        // becomes "(foo::bar, foo::baz)" and
+        // "WithOptConstParam { did: foo::bar, const_param_did: None }"
+        // becomes "(foo::bar, _)".
+
+        let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
+
+        let const_param_did = if let Some(const_param_did) = self.const_param_did {
+            let const_param_did = builder.def_id_to_string_id(const_param_did);
+            StringComponent::Ref(const_param_did)
+        } else {
+            StringComponent::Value("_")
+        };
+
+        let components = [
+            StringComponent::Value("("),
+            did,
+            StringComponent::Value(", "),
+            const_param_did,
+            StringComponent::Value(")"),
+        ];
+
+        builder.profiler.alloc_string(&components[..])
+    }
+}
+
 impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
 where
     T0: SpecIntoSelfProfilingString,
index 310ab4f7235ebf8e57fc4d5b8603619b62e6c81a..82160681ee8cf374f40d2abcb6e211a645cc4fa4 100644 (file)
@@ -10,7 +10,7 @@
 use crate::ty::{
     self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
 };
-use crate::ty::{List, ParamEnv, TyS};
+use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
 use polonius_engine::Atom;
 use rustc_ast::ast;
 use rustc_data_structures::captures::Captures;
 use std::ops::Range;
 use ty::util::IntTypeExt;
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub struct TypeAndMut<'tcx> {
     pub ty: Ty<'tcx>,
     pub mutbl: hir::Mutability,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
 /// A "free" region `fr` can be interpreted as "some region
 /// at least as big as the scope `fr.scope`".
@@ -43,7 +43,7 @@ pub struct FreeRegion {
     pub bound_region: BoundRegion,
 }
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
 #[derive(HashStable)]
 pub enum BoundRegion {
     /// An anonymous region parameter for a given fn (&T)
@@ -82,7 +82,7 @@ pub fn assert_bound_var(&self) -> BoundVar {
 
 /// N.B., if you change this, you'll probably want to change the corresponding
 /// AST structure in `librustc_ast/ast.rs` as well.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)]
 #[derive(HashStable)]
 #[rustc_diagnostic_item = "TyKind"]
 pub enum TyKind<'tcx> {
@@ -212,12 +212,6 @@ pub fn is_primitive(&self) -> bool {
     }
 }
 
-/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
-/// except through `tcx.err*()`.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
-pub struct DelaySpanBugEmitted(pub(super) ());
-
 // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(TyKind<'_>, 24);
@@ -325,24 +319,39 @@ pub struct ClosureSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-/// Struct returned by `split()`. Note that these are subslices of the
-/// parent slice and not canonical substs themselves.
-struct SplitClosureSubsts<'tcx> {
-    parent: &'tcx [GenericArg<'tcx>],
-    closure_kind_ty: GenericArg<'tcx>,
-    closure_sig_as_fn_ptr_ty: GenericArg<'tcx>,
-    tupled_upvars_ty: GenericArg<'tcx>,
+/// Struct returned by `split()`.
+pub struct ClosureSubstsParts<'tcx, T> {
+    pub parent_substs: &'tcx [GenericArg<'tcx>],
+    pub closure_kind_ty: T,
+    pub closure_sig_as_fn_ptr_ty: T,
+    pub tupled_upvars_ty: T,
 }
 
 impl<'tcx> ClosureSubsts<'tcx> {
-    /// Divides the closure substs into their respective
-    /// components. Single source of truth with respect to the
-    /// ordering.
-    fn split(self) -> SplitClosureSubsts<'tcx> {
+    /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs`
+    /// for the closure parent, alongside additional closure-specific components.
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
+    ) -> ClosureSubsts<'tcx> {
+        ClosureSubsts {
+            substs: tcx.mk_substs(
+                parts.parent_substs.iter().copied().chain(
+                    [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
+                        .iter()
+                        .map(|&ty| ty.into()),
+                ),
+            ),
+        }
+    }
+
+    /// Divides the closure substs into their respective components.
+    /// The ordering assumed here must match that used by `ClosureSubsts::new` above.
+    fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
         match self.substs[..] {
-            [ref parent @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
-                SplitClosureSubsts {
-                    parent,
+            [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+                ClosureSubstsParts {
+                    parent_substs,
                     closure_kind_ty,
                     closure_sig_as_fn_ptr_ty,
                     tupled_upvars_ty,
@@ -363,7 +372,7 @@ pub fn is_valid(self) -> bool {
 
     /// Returns the substitutions of the closure's parent.
     pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent
+        self.split().parent_substs
     }
 
     #[inline]
@@ -418,21 +427,46 @@ pub struct GeneratorSubsts<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-struct SplitGeneratorSubsts<'tcx> {
-    parent: &'tcx [GenericArg<'tcx>],
-    resume_ty: GenericArg<'tcx>,
-    yield_ty: GenericArg<'tcx>,
-    return_ty: GenericArg<'tcx>,
-    witness: GenericArg<'tcx>,
-    tupled_upvars_ty: GenericArg<'tcx>,
+pub struct GeneratorSubstsParts<'tcx, T> {
+    pub parent_substs: &'tcx [GenericArg<'tcx>],
+    pub resume_ty: T,
+    pub yield_ty: T,
+    pub return_ty: T,
+    pub witness: T,
+    pub tupled_upvars_ty: T,
 }
 
 impl<'tcx> GeneratorSubsts<'tcx> {
-    fn split(self) -> SplitGeneratorSubsts<'tcx> {
+    /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs`
+    /// for the generator parent, alongside additional generator-specific components.
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
+    ) -> GeneratorSubsts<'tcx> {
+        GeneratorSubsts {
+            substs: tcx.mk_substs(
+                parts.parent_substs.iter().copied().chain(
+                    [
+                        parts.resume_ty,
+                        parts.yield_ty,
+                        parts.return_ty,
+                        parts.witness,
+                        parts.tupled_upvars_ty,
+                    ]
+                    .iter()
+                    .map(|&ty| ty.into()),
+                ),
+            ),
+        }
+    }
+
+    /// Divides the generator substs into their respective components.
+    /// The ordering assumed here must match that used by `GeneratorSubsts::new` above.
+    fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> {
         match self.substs[..] {
-            [ref parent @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
-                SplitGeneratorSubsts {
-                    parent,
+            [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
+                GeneratorSubstsParts {
+                    parent_substs,
                     resume_ty,
                     yield_ty,
                     return_ty,
@@ -455,7 +489,7 @@ pub fn is_valid(self) -> bool {
 
     /// Returns the substitutions of the generator's parent.
     pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
-        self.split().parent
+        self.split().parent_substs
     }
 
     /// This describes the types that can be contained in a generator.
@@ -622,7 +656,7 @@ pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub enum ExistentialPredicate<'tcx> {
     /// E.g., `Iterator`.
@@ -673,8 +707,6 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicat
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
-
 impl<'tcx> List<ExistentialPredicate<'tcx>> {
     /// Returns the "principal `DefId`" of this set of existential predicates.
     ///
@@ -770,7 +802,7 @@ pub fn iter<'a>(
 ///
 /// Trait references also appear in object types like `Foo<U>`, but in
 /// that case the `Self` parameter is absent from the substitutions.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
@@ -828,7 +860,7 @@ pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
 ///
 /// The substitutions don't include the erased `Self`, only trait
 /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct ExistentialTraitRef<'tcx> {
     pub def_id: DefId,
@@ -884,7 +916,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTrai
 /// erase, or otherwise "discharge" these bound vars, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g., `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 pub struct Binder<T>(T);
 
 impl<T> Binder<T> {
@@ -1016,7 +1048,7 @@ pub fn transpose(self) -> Option<Binder<T>> {
 
 /// Represents the projection of an associated type. In explicit UFCS
 /// form this would be written `<T as Trait<..>>::N`.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct ProjectionTy<'tcx> {
     /// The parameters of the associated item.
@@ -1086,7 +1118,7 @@ pub fn return_ty(&self) -> ty::Binder<Ty<'tcx>> {
 /// - `inputs`: is the list of arguments and their modes.
 /// - `output`: is the return type.
 /// - `c_variadic`: indicates whether this is a C-variadic function.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct FnSig<'tcx> {
     pub inputs_and_output: &'tcx List<Ty<'tcx>>,
@@ -1147,7 +1179,7 @@ pub fn abi(&self) -> abi::Abi {
 
 pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct ParamTy {
     pub index: u32,
@@ -1172,7 +1204,7 @@ pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
 #[derive(HashStable)]
 pub struct ParamConst {
     pub index: u32,
@@ -1345,7 +1377,7 @@ pub struct DebruijnIndex {
 /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     /// Region bound in a type or fn declaration which will be
     /// substituted 'early' -- that is, at the same time when type
@@ -1383,32 +1415,30 @@ pub enum RegionKind {
     ReErased,
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
 pub struct EarlyBoundRegion {
     pub def_id: DefId,
     pub index: u32,
     pub name: Symbol,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 pub struct TyVid {
     pub index: u32,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 pub struct ConstVid<'tcx> {
     pub index: u32,
     pub phantom: PhantomData<&'tcx ()>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 pub struct IntVid {
     pub index: u32,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 pub struct FloatVid {
     pub index: u32,
 }
@@ -1425,7 +1455,7 @@ fn index(self) -> usize {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum InferTy {
     TyVar(TyVid),
@@ -1444,14 +1474,14 @@ pub enum InferTy {
     pub struct BoundVar { .. }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub struct BoundTy {
     pub var: BoundVar,
     pub kind: BoundTyKind,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundTyKind {
     Anon,
@@ -1465,7 +1495,7 @@ fn from(var: BoundVar) -> Self {
 }
 
 /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable)]
 pub struct ExistentialProjection<'tcx> {
     pub item_def_id: DefId,
index 866b529f35ec381d4e751e0d835942b167ba859a..acd58ab7f967a6e60af7917aa41c272db3b4c55c 100644 (file)
@@ -1,13 +1,14 @@
 // Type substitutions.
 
 use crate::infer::canonical::Canonical;
+use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
-use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{self, Decodable, Encodable};
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::SmallVec;
 
@@ -34,7 +35,7 @@ pub struct GenericArg<'tcx> {
 const REGION_TAG: usize = 0b01;
 const CONST_TAG: usize = 0b10;
 
-#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
 pub enum GenericArgKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
@@ -168,14 +169,14 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx> Encodable for GenericArg<'tcx> {
-    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for GenericArg<'tcx> {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         self.unpack().encode(e)
     }
 }
 
-impl<'tcx> Decodable for GenericArg<'tcx> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<GenericArg<'tcx>, D::Error> {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArg<'tcx> {
+    fn decode(d: &mut D) -> Result<GenericArg<'tcx>, D::Error> {
         Ok(GenericArgKind::decode(d)?.pack())
     }
 }
@@ -396,8 +397,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for SubstsRef<'tcx> {}
-
 ///////////////////////////////////////////////////////////////////////////
 // Public trait `Subst`
 //
@@ -653,7 +652,7 @@ fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'
 
 /// Stores the user-given substs to reach some fully qualified path
 /// (e.g., `<T>::Item` or `<T as Trait>::Item`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub struct UserSubsts<'tcx> {
     /// The substitutions for the item as given by the user.
@@ -680,7 +679,7 @@ pub struct UserSubsts<'tcx> {
 /// the impl (with the substs from `UserSubsts`) and apply those to
 /// the self type, giving `Foo<?A>`. Finally, we unify that with
 /// the self type here, which contains `?A` to be `&'static u32`
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
 pub struct UserSelfTy<'tcx> {
     pub impl_def_id: DefId,
index f93cce3f4da7f1b1f786f3d883a3a94fb2f12526..86fe3ac3751aff2247a57155a3eb50bf8003d181 100644 (file)
@@ -47,7 +47,7 @@ pub struct TraitDef {
 
 /// Whether this trait is treated specially by the standard library
 /// specialization lint.
-#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(HashStable, PartialEq, Clone, Copy, TyEncodable, TyDecodable)]
 pub enum TraitSpecializationKind {
     /// The default. Specializing on this trait is not allowed.
     None,
index 07221082048fbc3603a8995e98d7f670e3e374e1..5c5fe9dbd7abfaf7bbe9ad4c70502d04bb8e855f 100644 (file)
@@ -879,7 +879,7 @@ fn are_inner_types_recursive<'tcx>(
                         let span = match field
                             .did
                             .as_local()
-                            .map(|id| tcx.hir().as_local_hir_id(id))
+                            .map(|id| tcx.hir().local_def_id_to_hir_id(id))
                             .and_then(|id| tcx.hir().find(id))
                         {
                             Some(hir::Node::Field(field)) => field.ty.span,
@@ -1143,7 +1143,7 @@ pub fn needs_drop_components(
     }
 }
 
-#[derive(Copy, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
 pub struct AlwaysRequiresDrop;
 
 /// Normalizes all opaque types in the given value, replacing them
index f05c47e0ed62655656c4f330ca095cbc49e9d793..2693d29e41c4ce7071f4b1259f7f6fa2b1246942 100644 (file)
@@ -13,7 +13,7 @@ doctest = false
 either = "1.5.0"
 rustc_graphviz = { path = "../librustc_graphviz" }
 itertools = "0.8"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 log_settings = "0.1.1"
 polonius-engine = "0.12.0"
 rustc_middle = { path = "../librustc_middle" }
index 8e7c97c4a1baca8c8cac927fd02b158b0348590e..7a50bdfeef625e0a25a906aa3b917241004d0471 100644 (file)
@@ -263,7 +263,7 @@ pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
             let needs_note = match ty.kind {
                 ty::Closure(id, _) => {
                     let tables = self.infcx.tcx.typeck(id.expect_local());
-                    let hir_id = self.infcx.tcx.hir().as_local_hir_id(id.expect_local());
+                    let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
 
                     tables.closure_kind_origins().get(hir_id).is_none()
                 }
@@ -954,7 +954,7 @@ fn report_local_value_does_not_live_long_enough(
                 format!("`{}` would have to be valid for `{}`...", name, region_name),
             );
 
-            let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+            let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
             err.span_label(
                 drop_span,
                 format!(
@@ -1863,7 +1863,7 @@ fn annotate_fn_sig(
     ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
         let is_closure = self.infcx.tcx.is_closure(did);
-        let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did.as_local()?);
+        let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did.as_local()?);
         let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
 
         // We need to work out which arguments to highlight. We do this by looking
index ba74ffaa8d620f8536dda39b468ab48584061992..daffdec2a83bed72239b89fcfc78aa523b553688 100644 (file)
@@ -104,7 +104,7 @@ pub(super) fn add_moved_or_invoked_closure_note(
                 debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
                 if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind {
                     let did = did.expect_local();
-                    let hir_id = self.infcx.tcx.hir().as_local_hir_id(did);
+                    let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
 
                     if let Some((span, name)) =
                         self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
@@ -127,7 +127,7 @@ pub(super) fn add_moved_or_invoked_closure_note(
         if let Some(target) = target {
             if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind {
                 let did = did.expect_local();
-                let hir_id = self.infcx.tcx.hir().as_local_hir_id(did);
+                let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
 
                 if let Some((span, name)) =
                     self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
@@ -937,7 +937,7 @@ fn closure_span(
             "closure_span: def_id={:?} target_place={:?} places={:?}",
             def_id, target_place, places
         );
-        let hir_id = self.infcx.tcx.hir().as_local_hir_id(def_id.as_local()?);
+        let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id.as_local()?);
         let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
index ef0fe71abecb25da3c077da05de1a86b8b10661e..d26436ff1de54d2c44697351590129653fecc72b 100644 (file)
@@ -492,7 +492,7 @@ fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Spa
         err.span_label(sp, format!("cannot {}", act));
 
         let hir = self.infcx.tcx.hir();
-        let closure_id = hir.as_local_hir_id(self.mir_def_id);
+        let closure_id = hir.local_def_id_to_hir_id(self.mir_def_id);
         let fn_call_id = hir.get_parent_node(closure_id);
         let node = hir.get(fn_call_id);
         let item_id = hir.enclosing_body_owner(fn_call_id);
@@ -691,7 +691,7 @@ fn annotate_struct_field(
         if let ty::Adt(def, _) = ty.kind {
             let field = def.all_fields().nth(field.index())?;
             // Use the HIR types to construct the diagnostic message.
-            let hir_id = tcx.hir().as_local_hir_id(field.did.as_local()?);
+            let hir_id = tcx.hir().local_def_id_to_hir_id(field.did.as_local()?);
             let node = tcx.hir().find(hir_id)?;
             // Now we're dealing with the actual struct that we're going to suggest a change to,
             // we can expect a field that is an immutable reference to a type.
index 8521f900988e49a212043b3119e46928b45ad068..9197a83cdd07a4615d37ff1628410f35d832a538 100644 (file)
@@ -3,10 +3,10 @@
 
 use std::collections::BTreeMap;
 
-use log::debug;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagnosticBuilder;
 use rustc_middle::ty::RegionVid;
+use tracing::debug;
 
 use smallvec::SmallVec;
 
index 32195adc60ef87980442f3a9054d650604be7da6..2603b1e048d81ebe793a394dddad81d4e9db7f37 100644 (file)
@@ -266,7 +266,7 @@ fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
                 }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+                    let mir_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     if let DefiningTy::Closure(_, substs) = def_ty {
@@ -361,7 +361,7 @@ fn get_argument_hir_ty_for_highlighting(
         &self,
         argument_index: usize,
     ) -> Option<&hir::Ty<'tcx>> {
-        let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+        let mir_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
         let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
         let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
         match argument_hir_ty.kind {
@@ -648,7 +648,7 @@ fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Opti
         highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
         let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
+        let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
 
         let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
@@ -700,7 +700,7 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
         highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
         let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
+        let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
 
         let yield_span = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
index 6e211b42a052ee36575f983a59931655fa14e334..f7031b2a598484963d763b63722119aaddcf141d 100644 (file)
@@ -129,7 +129,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     let tcx = infcx.tcx;
     let param_env = tcx.param_env(def.did);
-    let id = tcx.hir().as_local_hir_id(def.did);
+    let id = tcx.hir().local_def_id_to_hir_id(def.did);
 
     let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
     for var_debug_info in &input_body.var_debug_info {
index c5aa5c5ebc7f2368fce8dd59ed78391dc0c0e593..cd6b75cf55602cb7a3150720486190c5e269dd47 100644 (file)
@@ -231,7 +231,7 @@ pub fn new(
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
         let tcx = infcx.tcx;
-        let mir_hir_id = tcx.hir().as_local_hir_id(mir_def.did);
+        let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
         UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
     }
 
index 7fbe5c409d3ce283f0a694a86a9f4d4551c21130..291b42c12d71866026dfbf7a859cbf9021027ec9 100644 (file)
@@ -57,6 +57,12 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     ecx.run()?;
 
     // Intern the result
+    // FIXME: since the DefId of a promoted is the DefId of its owner, this
+    // means that promoteds in statics are actually interned like statics!
+    // However, this is also currently crucial because we promote mutable
+    // non-empty slices in statics to extend their lifetime, and this
+    // ensures that they are put into a mutable allocation.
+    // For other kinds of promoteds in statics (like array initializers), this is rather silly.
     let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
         Some(m) => InternKind::Static(m),
         None if cid.promoted.is_some() => InternKind::Promoted,
@@ -347,7 +353,7 @@ pub fn const_eval_raw_provider<'tcx>(
                     // validation thus preventing such a hard error from being a backwards
                     // compatibility hazard
                     DefKind::Const | DefKind::AssocConst => {
-                        let hir_id = tcx.hir().as_local_hir_id(def.did);
+                        let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
                         err.report_as_lint(
                             tcx.at(tcx.def_span(def.did)),
                             "any use of this value will cause an error",
@@ -370,7 +376,7 @@ pub fn const_eval_raw_provider<'tcx>(
                                 err.report_as_lint(
                                     tcx.at(span),
                                     "reaching this expression at runtime will panic or abort",
-                                    tcx.hir().as_local_hir_id(def.did),
+                                    tcx.hir().local_def_id_to_hir_id(def.did),
                                     Some(err.span),
                                 )
                             }
index 70ddd79ee40b082916e3f0f85bf47f5780dae605..9ef63b3322dd54900aea201995ee63a6bbc1d51e 100644 (file)
@@ -90,7 +90,7 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
 /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
 /// said intrinsic has a `rustc_const_{un,}stable` attribute.
 fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
 
     let node = tcx.hir().get(hir_id);
 
index dffbc969c21b8c645158e7ba7850e59d29df5bb6..6c8ee72bc66c2e01e65435a34df0ceeb13fb7eb8 100644 (file)
@@ -312,7 +312,8 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
     let tcx = ecx.tcx;
     let base_intern_mode = match intern_kind {
         InternKind::Static(mutbl) => InternMode::Static(mutbl),
-        // FIXME: what about array lengths, array initializers?
+        // `Constant` includes array lengths.
+        // `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments.
         InternKind::Constant | InternKind::Promoted => InternMode::ConstBase,
     };
 
index 4e7142a93aedc7c20afbe97eca387192d3764f88..3118e7ac3ab17f57ec3e2f7076bd1b03adba385d 100644 (file)
@@ -30,7 +30,7 @@
 #![recursion_limit = "256"]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
index fc9f7f1af622f8e7508a81e9cd35b7c9401995c3..d946c1947c2df0178f7891976d8ab3455f23ee15 100644 (file)
@@ -69,8 +69,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
 
     // Visit MIR and accumululate used generic parameters.
     let body = tcx.optimized_mir(def_id);
-    let mut vis =
-        UsedGenericParametersVisitor { tcx, def_id, unused_parameters: &mut unused_parameters };
+    let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
     vis.visit_body(body);
     debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
 
@@ -120,45 +119,101 @@ fn mark_used_by_predicates<'tcx>(
     def_id: DefId,
     unused_parameters: &mut FiniteBitSet<u32>,
 ) {
-    let def_id = tcx.closure_base_def_id(def_id);
-
-    let is_self_ty_used = |unused_parameters: &mut FiniteBitSet<u32>, self_ty: Ty<'tcx>| {
-        debug!("unused_generic_params: self_ty={:?}", self_ty);
-        if let ty::Param(param) = self_ty.kind {
-            !unused_parameters.contains(param.index).unwrap_or(false)
-        } else {
-            false
-        }
+    let is_ty_used = |unused_parameters: &FiniteBitSet<u32>, ty: Ty<'tcx>| -> bool {
+        let mut vis = IsUsedGenericParams { unused_parameters };
+        ty.visit_with(&mut vis)
     };
 
     let mark_ty = |unused_parameters: &mut FiniteBitSet<u32>, ty: Ty<'tcx>| {
-        let mut vis = UsedGenericParametersVisitor { tcx, def_id, unused_parameters };
+        let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters };
         ty.visit_with(&mut vis);
     };
 
+    let def_id = tcx.closure_base_def_id(def_id);
     let predicates = tcx.explicit_predicates_of(def_id);
-    debug!("mark_parameters_used_in_predicates: predicates_of={:?}", predicates);
-    for (predicate, _) in predicates.predicates {
-        match predicate.skip_binders() {
-            ty::PredicateAtom::Trait(predicate, ..) => {
-                let trait_ref = predicate.trait_ref;
-                if is_self_ty_used(unused_parameters, trait_ref.self_ty()) {
+    debug!("mark_used_by_predicates: predicates_of={:?}", predicates);
+
+    let mut current_unused_parameters = FiniteBitSet::new_empty();
+    // Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
+    // bit set so that this is skipped if all parameters are already used.
+    while current_unused_parameters != *unused_parameters {
+        debug!(
+            "mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
+            current_unused_parameters, unused_parameters
+        );
+        current_unused_parameters = *unused_parameters;
+
+        for (predicate, _) in predicates.predicates {
+            match predicate.skip_binders() {
+                ty::PredicateAtom::Trait(predicate, ..) => {
+                    let trait_ref = predicate.trait_ref;
+                    debug!("mark_used_by_predicates: (trait) trait_ref={:?}", trait_ref);
+
+                    // Consider `T` used if `I` is used in predicates of the form
+                    // `I: Iterator<Item = T>`
+                    debug!("mark_used_by_predicates: checking self");
+                    if is_ty_used(unused_parameters, trait_ref.self_ty()) {
+                        debug!("mark_used_by_predicates: used!");
+                        for ty in trait_ref.substs.types() {
+                            mark_ty(unused_parameters, ty);
+                        }
+
+                        // No need to check for a type being used in the substs if `self_ty` was
+                        // used.
+                        continue;
+                    }
+
+                    // Consider `I` used if `T` is used in predicates of the form
+                    // `I: Iterator<Item = &'a (T, E)>` (see rust-lang/rust#75326)
+                    debug!("mark_used_by_predicates: checking substs");
                     for ty in trait_ref.substs.types() {
-                        debug!("unused_generic_params: (trait) ty={:?}", ty);
-                        mark_ty(unused_parameters, ty);
+                        if is_ty_used(unused_parameters, ty) {
+                            debug!("mark_used_by_predicates: used!");
+                            mark_ty(unused_parameters, trait_ref.self_ty());
+                        }
                     }
                 }
-            }
-            ty::PredicateAtom::Projection(proj, ..) => {
-                let self_ty = proj.projection_ty.self_ty();
-                if is_self_ty_used(unused_parameters, self_ty) {
-                    debug!("unused_generic_params: (projection ty={:?}", proj.ty);
-                    mark_ty(unused_parameters, proj.ty);
+                ty::PredicateAtom::Projection(proj, ..) => {
+                    let self_ty = proj.projection_ty.self_ty();
+                    debug!(
+                        "mark_used_by_predicates: (projection) self_ty={:?} proj.ty={:?}",
+                        self_ty, proj.ty
+                    );
+
+                    // Consider `T` used if `I` is used in predicates of the form
+                    // `<I as Iterator>::Item = T`
+                    debug!("mark_used_by_predicates: checking self");
+                    if is_ty_used(unused_parameters, self_ty) {
+                        debug!("mark_used_by_predicates: used!");
+                        mark_ty(unused_parameters, proj.ty);
+
+                        // No need to check for projection type being used if `self_ty` was used.
+                        continue;
+                    }
+
+                    // Consider `I` used if `T` is used in predicates of the form
+                    // `<I as Iterator>::Item = &'a (T, E)` (see rust-lang/rust#75326)
+                    debug!("mark_used_by_predicates: checking projection ty");
+                    if is_ty_used(unused_parameters, proj.ty) {
+                        debug!("mark_used_by_predicates: used!");
+                        mark_ty(unused_parameters, self_ty);
+                    }
                 }
+                ty::PredicateAtom::RegionOutlives(..)
+                | ty::PredicateAtom::TypeOutlives(..)
+                | ty::PredicateAtom::WellFormed(..)
+                | ty::PredicateAtom::ObjectSafe(..)
+                | ty::PredicateAtom::ClosureKind(..)
+                | ty::PredicateAtom::Subtype(..)
+                | ty::PredicateAtom::ConstEvaluatable(..)
+                | ty::PredicateAtom::ConstEquate(..) => (),
             }
-            _ => (),
         }
     }
+
+    if let Some(parent) = predicates.parent {
+        mark_used_by_predicates(tcx, parent, unused_parameters);
+    }
 }
 
 /// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
@@ -204,13 +259,13 @@ fn emit_unused_generic_params_error<'tcx>(
 }
 
 /// Visitor used to aggregate generic parameter uses.
-struct UsedGenericParametersVisitor<'a, 'tcx> {
+struct MarkUsedGenericParams<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     unused_parameters: &'a mut FiniteBitSet<u32>,
 }
 
-impl<'a, 'tcx> UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
     /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
     /// a closure, generator or constant).
     fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
@@ -229,7 +284,7 @@ fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
         debug!("visit_local_decl: local_decl={:?}", local_decl);
         if local == Local::from_usize(1) {
@@ -256,7 +311,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
     }
 }
 
-impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
         debug!("visit_const: c={:?}", c);
         if !c.has_param_types_or_consts() {
@@ -318,3 +373,36 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
         }
     }
 }
+
+/// Visitor used to check if a generic parameter is used.
+struct IsUsedGenericParams<'a> {
+    unused_parameters: &'a FiniteBitSet<u32>,
+}
+
+impl<'a, 'tcx> TypeVisitor<'tcx> for IsUsedGenericParams<'a> {
+    fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
+        debug!("visit_const: c={:?}", c);
+        if !c.has_param_types_or_consts() {
+            return false;
+        }
+
+        match c.val {
+            ty::ConstKind::Param(param) => {
+                !self.unused_parameters.contains(param.index).unwrap_or(false)
+            }
+            _ => c.super_visit_with(self),
+        }
+    }
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+        debug!("visit_ty: ty={:?}", ty);
+        if !ty.has_param_types_or_consts() {
+            return false;
+        }
+
+        match ty.kind {
+            ty::Param(param) => !self.unused_parameters.contains(param.index).unwrap_or(false),
+            _ => ty.super_visit_with(self),
+        }
+    }
+}
index baa3e5e1581c5c2f2f90652690de56cf5c16a6da..324289166b9fb0c913929dadcc63863979d8d44c 100644 (file)
@@ -86,12 +86,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
                 .skip(1)
                 .take(arg_count)
                 .map(|(local, _)| Place::from(local))
-                .filter(needs_retag)
-                .collect::<Vec<_>>();
+                .filter(needs_retag);
             // Emit their retags.
             basic_blocks[START_BLOCK].statements.splice(
                 0..0,
-                places.into_iter().map(|place| Statement {
+                places.map(|place| Statement {
                     source_info,
                     kind: StatementKind::Retag(RetagKind::FnEntry, box (place)),
                 }),
@@ -101,29 +100,24 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx
         // PART 2
         // Retag return values of functions.  Also escape-to-raw the argument of `drop`.
         // We collect the return destinations because we cannot mutate while iterating.
-        let mut returns: Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new();
-        for block_data in basic_blocks.iter_mut() {
-            match block_data.terminator().kind {
-                TerminatorKind::Call { ref destination, .. } => {
-                    // Remember the return destination for later
-                    if let Some(ref destination) = destination {
-                        if needs_retag(&destination.0) {
-                            returns.push((
-                                block_data.terminator().source_info,
-                                destination.0,
-                                destination.1,
-                            ));
-                        }
+        let returns = basic_blocks
+            .iter_mut()
+            .filter_map(|block_data| {
+                match block_data.terminator().kind {
+                    TerminatorKind::Call { destination: Some(ref destination), .. }
+                        if needs_retag(&destination.0) =>
+                    {
+                        // Remember the return destination for later
+                        Some((block_data.terminator().source_info, destination.0, destination.1))
                     }
-                }
-                TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+
                     // `Drop` is also a call, but it doesn't return anything so we are good.
-                }
-                _ => {
+                    TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None,
                     // Not a block ending in a Call -> ignore.
+                    _ => None,
                 }
-            }
-        }
+            })
+            .collect::<Vec<_>>();
         // Now we go over the returns we collected to retag the return values.
         for (source_info, dest_place, dest_block) in returns {
             basic_blocks[dest_block].statements.insert(
index f64c72e7b362dfce3c0621308d4d1f3951fef38a..526c896df093cad5ad57a074afa68f7911cc5032 100644 (file)
@@ -215,7 +215,7 @@ pub fn check_body(&mut self) {
             && !tcx.is_thread_local_static(def_id.to_def_id());
 
         if should_check_for_sync {
-            let hir_id = tcx.hir().as_local_hir_id(def_id);
+            let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
             check_return_ty_is_sync(tcx, &body, hir_id);
         }
     }
index 9c06e173bcd5713b2b946af7faa85dd4a341614b..d2a5616b8ed3481edb267de9136810aa614e078c 100644 (file)
@@ -483,7 +483,7 @@ fn check_unused_unsafe(
     used_unsafe: &FxHashSet<hir::HirId>,
     unsafe_blocks: &mut Vec<(hir::HirId, bool)>,
 ) {
-    let body_id = tcx.hir().maybe_body_owned_by(tcx.hir().as_local_hir_id(def_id));
+    let body_id = tcx.hir().maybe_body_owned_by(tcx.hir().local_def_id_to_hir_id(def_id));
 
     let body_id = match body_id {
         Some(body) => body,
@@ -511,7 +511,7 @@ fn unsafety_check_result<'tcx>(
 
     let param_env = tcx.param_env(def.did);
 
-    let id = tcx.hir().as_local_hir_id(def.did);
+    let id = tcx.hir().local_def_id_to_hir_id(def.did);
     let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
         hir::BodyOwnerKind::Closure => (false, false),
         hir::BodyOwnerKind::Fn => {
@@ -532,7 +532,7 @@ fn unsafety_check_result<'tcx>(
 }
 
 fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let lint_hir_id = tcx.hir().as_local_hir_id(def_id);
+    let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| {
         // FIXME: when we make this a hard error, this should have its
index 3b39d5f66b78fa81d4135acbe070e785bcc1384a..7e8a94f181f63a5b79f11dcc64abc6606c00d7dd 100644 (file)
@@ -67,7 +67,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
         }
 
         use rustc_middle::hir::map::blocks::FnLikeNode;
-        let hir_id = tcx.hir().as_local_hir_id(source.def_id().expect_local());
+        let hir_id = tcx.hir().local_def_id_to_hir_id(source.def_id().expect_local());
 
         let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some();
         let is_assoc_const = tcx.def_kind(source.def_id()) == DefKind::AssocConst;
index 2de701284e3f5815dfd7e7a9df876c1a84c78e71..66989a902447d6076071f0936672459dc276f4e9 100644 (file)
@@ -12,26 +12,24 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<
         for bb in basic_blocks {
             bb.expand_statements(|stmt| {
                 // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
-                if let StatementKind::Assign(box (_, ref rhs)) = stmt.kind {
-                    if let Rvalue::Aggregate(ref kind, _) = *rhs {
-                        // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
-                        if let AggregateKind::Array(_) = **kind {
-                            return None;
-                        }
-                    } else {
+                match stmt.kind {
+                    // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
+                    StatementKind::Assign(box (
+                        _,
+                        Rvalue::Aggregate(box AggregateKind::Array(_), _),
+                    )) => {
                         return None;
                     }
-                } else {
-                    return None;
+                    StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
+                    _ => return None,
                 }
 
                 let stmt = stmt.replace_nop();
                 let source_info = stmt.source_info;
                 let (lhs, kind, operands) = match stmt.kind {
-                    StatementKind::Assign(box (lhs, rvalue)) => match rvalue {
-                        Rvalue::Aggregate(kind, operands) => (lhs, kind, operands),
-                        _ => bug!(),
-                    },
+                    StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) => {
+                        (lhs, kind, operands)
+                    }
                     _ => bug!(),
                 };
 
index 92ea162e419dbb6941ffe68dc8439bac96acd8ce..315d4fa9d477de5e6b97079410ebfcb0baaf2713 100644 (file)
@@ -75,7 +75,7 @@ fn run_pass(&self, caller_body: &mut Body<'tcx>) {
         let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id());
 
         // Only do inlining into fn bodies.
-        let id = self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
+        let id = self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
         if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
             for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
                 if let Some(callsite) =
@@ -101,9 +101,9 @@ fn run_pass(&self, caller_body: &mut Body<'tcx>) {
                 }
 
                 let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
-                    let callee_hir_id = self.tcx.hir().as_local_hir_id(callee_def_id);
+                    let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
                     let self_hir_id =
-                        self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
+                        self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
                     // Avoid a cycle here by only using `optimized_mir` only if we have
                     // a lower `HirId` than the callee. This ensures that the callee will
                     // not inline us. This trick only works without incremental compilation.
index 5b2954dd5b0a3e08ebf228722ed6d056f35d9631..500d66ece0676312e08461c17b9e24e11f515446 100644 (file)
@@ -295,6 +295,21 @@ fn inject_call(
 
         let (file_name, start_line, start_col, end_line, end_col) = self.code_region(&span);
 
+        // FIXME(richkadel): Note that `const_str()` results in the creation of an `Allocation` to
+        // hold one copy of each unique filename. It looks like that `Allocation` may translate into
+        // the creation of an `@alloc` in LLVM IR that is never actually used by runtime code.
+        //
+        // Example LLVM IR:
+        //
+        // @alloc4 = private unnamed_addr constant <{ [43 x i8] }> \
+        //   <{ [43 x i8] c"C:\\msys64\\home\\richkadel\\rust\\rust_basic.rs" }>, align 1
+        //
+        // Can I flag the alloc as something not to be added to codegen? Or somehow remove it before
+        // it gets added to the LLVM IR? Do we need some kind of reference counting to know it's
+        // not used by any runtime code?
+        //
+        // This question is moot if I convert the Call Terminators to Statements, I believe:
+        // https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Implement.20LLVM-compatible.20source-based.20cod.20compiler-team.23278/near/206731748
         args.push(self.const_str(&file_name, inject_at));
         args.push(self.const_u32(start_line, inject_at));
         args.push(self.const_u32(start_col, inject_at));
diff --git a/src/librustc_mir/transform/match_branches.rs b/src/librustc_mir/transform/match_branches.rs
new file mode 100644 (file)
index 0000000..c1d574d
--- /dev/null
@@ -0,0 +1,135 @@
+use crate::transform::{MirPass, MirSource};
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct MatchBranchSimplification;
+
+/// If a source block is found that switches between two blocks that are exactly
+/// the same modulo const bool assignments (e.g., one assigns true another false
+/// to the same place), merge a target block statements into the source block,
+/// using Eq / Ne comparison with switch value where const bools value differ.
+///
+/// For example:
+///
+/// ```rust
+/// bb0: {
+///     switchInt(move _3) -> [42_isize: bb1, otherwise: bb2];
+/// }
+///
+/// bb1: {
+///     _2 = const true;
+///     goto -> bb3;
+/// }
+///
+/// bb2: {
+///     _2 = const false;
+///     goto -> bb3;
+/// }
+/// ```
+///
+/// into:
+///
+/// ```rust
+/// bb0: {
+///    _2 = Eq(move _3, const 42_isize);
+///    goto -> bb3;
+/// }
+/// ```
+
+impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        let param_env = tcx.param_env(src.def_id());
+        let bbs = body.basic_blocks_mut();
+        'outer: for bb_idx in bbs.indices() {
+            let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
+                TerminatorKind::SwitchInt {
+                    discr: Operand::Copy(ref place) | Operand::Move(ref place),
+                    switch_ty,
+                    ref targets,
+                    ref values,
+                    ..
+                } if targets.len() == 2 && values.len() == 1 && targets[0] != targets[1] => {
+                    (place, values[0], switch_ty, targets[0], targets[1])
+                }
+                // Only optimize switch int statements
+                _ => continue,
+            };
+
+            // Check that destinations are identical, and if not, then don't optimize this block
+            if &bbs[first].terminator().kind != &bbs[second].terminator().kind {
+                continue;
+            }
+
+            // Check that blocks are assignments of consts to the same place or same statement,
+            // and match up 1-1, if not don't optimize this block.
+            let first_stmts = &bbs[first].statements;
+            let scnd_stmts = &bbs[second].statements;
+            if first_stmts.len() != scnd_stmts.len() {
+                continue;
+            }
+            for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) {
+                match (&f.kind, &s.kind) {
+                    // If two statements are exactly the same, we can optimize.
+                    (f_s, s_s) if f_s == s_s => {}
+
+                    // If two statements are const bool assignments to the same place, we can optimize.
+                    (
+                        StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
+                        StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
+                    ) if lhs_f == lhs_s
+                        && f_c.literal.ty.is_bool()
+                        && s_c.literal.ty.is_bool()
+                        && f_c.literal.try_eval_bool(tcx, param_env).is_some()
+                        && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
+
+                    // Otherwise we cannot optimize. Try another block.
+                    _ => continue 'outer,
+                }
+            }
+            // Take ownership of items now that we know we can optimize.
+            let discr = discr.clone();
+
+            // We already checked that first and second are different blocks,
+            // and bb_idx has a different terminator from both of them.
+            let (from, first, second) = bbs.pick3_mut(bb_idx, first, second);
+
+            let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| {
+                match (&f.kind, &s.kind) {
+                    (f_s, s_s) if f_s == s_s => (*f).clone(),
+
+                    (
+                        StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))),
+                        StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
+                    ) => {
+                        // From earlier loop we know that we are dealing with bool constants only:
+                        let f_b = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
+                        let s_b = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
+                        if f_b == s_b {
+                            // Same value in both blocks. Use statement as is.
+                            (*f).clone()
+                        } else {
+                            // Different value between blocks. Make value conditional on switch condition.
+                            let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                            let const_cmp = Operand::const_from_scalar(
+                                tcx,
+                                switch_ty,
+                                crate::interpret::Scalar::from_uint(val, size),
+                                rustc_span::DUMMY_SP,
+                            );
+                            let op = if f_b { BinOp::Eq } else { BinOp::Ne };
+                            let rhs = Rvalue::BinaryOp(op, Operand::Copy(discr.clone()), const_cmp);
+                            Statement {
+                                source_info: f.source_info,
+                                kind: StatementKind::Assign(box (*lhs, rhs)),
+                            }
+                        }
+                    }
+
+                    _ => unreachable!(),
+                }
+            });
+            from.statements.extend(new_stmts);
+            from.terminator_mut().kind = first.terminator().kind.clone();
+        }
+    }
+}
index 3803ee78fd4d9e5543550ab9bea710c2fb8c6c59..4f26f3bb45973b178c36fc8821c9bc24025221b8 100644 (file)
@@ -29,6 +29,7 @@
 pub mod inline;
 pub mod instcombine;
 pub mod instrument_coverage;
+pub mod match_branches;
 pub mod no_landing_pads;
 pub mod nrvo;
 pub mod promote_consts;
@@ -440,6 +441,7 @@ fn run_optimization_passes<'tcx>(
         // with async primitives.
         &generator::StateTransform,
         &instcombine::InstCombine,
+        &match_branches::MatchBranchSimplification,
         &const_prop::ConstProp,
         &simplify_branches::SimplifyBranches::new("after-const-prop"),
         &simplify_try::SimplifyArmIdentity,
index c0564105701575f20c9c00150f3be4d61ce602f9..94637bae44a7806cce8d6c3b9157890ebd74f512 100644 (file)
@@ -101,7 +101,7 @@ pub fn is_promotable(&self) -> bool {
 /// of a larger candidate.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum Candidate {
-    /// Borrow of a constant temporary.
+    /// Borrow of a constant temporary, candidate for lifetime extension.
     Ref(Location),
 
     /// Promotion of the `x` in `[x; 32]`.
index dfd01e27d57c99bfbed9259f31104ae9ef2aa704..7abb09885ffd335dd685c07d732f1c325ff1f002 100644 (file)
@@ -14,7 +14,7 @@
 pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult {
     // Prevent const trait methods from being annotated as `stable`.
     if tcx.features().staged_api {
-        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
             return Err((body.span, "trait methods cannot be stable const fn".into()));
         }
index 02896d7de357ff40524e740a303f75264bec4232..84082edd1933f61ec858fe2abba005a3ede99ec9 100644 (file)
@@ -246,12 +246,14 @@ fn find_storage_live_dead_stmts_for_local<'tcx>(
         tmp_assigned_vars.insert(*r);
     }
 
-    let mut dbg_info_to_adjust = Vec::new();
-    for (i, var_info) in debug_info.iter().enumerate() {
-        if tmp_assigned_vars.contains(var_info.place.local) {
-            dbg_info_to_adjust.push(i);
-        }
-    }
+    let dbg_info_to_adjust: Vec<_> =
+        debug_info
+            .iter()
+            .enumerate()
+            .filter_map(|(i, var_info)| {
+                if tmp_assigned_vars.contains(var_info.place.local) { Some(i) } else { None }
+            })
+            .collect();
 
     Some(ArmIdentityInfo {
         local_temp_0: local_tmp_s0,
@@ -461,14 +463,14 @@ fn match_get_variant_field<'tcx>(
     stmt: &Statement<'tcx>,
 ) -> Option<(Local, Local, VarField<'tcx>, &'tcx List<PlaceElem<'tcx>>)> {
     match &stmt.kind {
-        StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
-            Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)) => {
-                let local_into = place_into.as_local()?;
-                let (local_from, vf) = match_variant_field_place(*pf)?;
-                Some((local_into, local_from, vf, pf.projection))
-            }
-            _ => None,
-        },
+        StatementKind::Assign(box (
+            place_into,
+            Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)),
+        )) => {
+            let local_into = place_into.as_local()?;
+            let (local_from, vf) = match_variant_field_place(*pf)?;
+            Some((local_into, local_from, vf, pf.projection))
+        }
         _ => None,
     }
 }
@@ -479,14 +481,11 @@ fn match_get_variant_field<'tcx>(
 /// ```
 fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
     match &stmt.kind {
-        StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
-            Rvalue::Use(Operand::Move(place_into)) => {
-                let local_into = place_into.as_local()?;
-                let (local_from, vf) = match_variant_field_place(*place_from)?;
-                Some((local_into, local_from, vf))
-            }
-            _ => None,
-        },
+        StatementKind::Assign(box (place_from, Rvalue::Use(Operand::Move(place_into)))) => {
+            let local_into = place_into.as_local()?;
+            let (local_from, vf) = match_variant_field_place(*place_from)?;
+            Some((local_into, local_from, vf))
+        }
         _ => None,
     }
 }
index e3b182b88492f10e81f5b2e7430dd3c3a6114452..4cca4d223c0cb6dd7c2f6cff5e71b762b549012b 100644 (file)
@@ -99,26 +99,18 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
             if let TerminatorKind::SwitchInt { values, targets, .. } =
                 &mut body.basic_blocks_mut()[bb].terminator_mut().kind
             {
-                let vals = &*values;
-                let zipped = vals.iter().zip(targets.iter());
-
-                let mut matched_values = Vec::with_capacity(allowed_variants.len());
-                let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1);
-
-                for (val, target) in zipped {
-                    if allowed_variants.contains(val) {
-                        matched_values.push(*val);
-                        matched_targets.push(*target);
-                    } else {
-                        trace!("eliminating {:?} -> {:?}", val, target);
-                    }
-                }
-
-                // handle the "otherwise" branch
-                matched_targets.push(targets.pop().unwrap());
-
-                *values = matched_values.into();
-                *targets = matched_targets;
+                // take otherwise out early
+                let otherwise = targets.pop().unwrap();
+                assert_eq!(targets.len(), values.len());
+                let mut i = 0;
+                targets.retain(|_| {
+                    let keep = allowed_variants.contains(&values[i]);
+                    i += 1;
+                    keep
+                });
+                targets.push(otherwise);
+
+                values.to_mut().retain(|var| allowed_variants.contains(var));
             } else {
                 unreachable!()
             }
index d9f2259030ff5b0b05ee715e8687b7405259bcb1..fa362c66fb2897a02661f19e2a50486830f1021e 100644 (file)
@@ -67,18 +67,13 @@ fn remove_successors<F>(
 where
     F: Fn(BasicBlock) -> bool,
 {
-    match *terminator_kind {
-        TerminatorKind::Goto { target } if predicate(target) => Some(TerminatorKind::Unreachable),
+    let terminator = match *terminator_kind {
+        TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable,
         TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
             let original_targets_len = targets.len();
             let (otherwise, targets) = targets.split_last().unwrap();
-            let retained = values
-                .iter()
-                .zip(targets.iter())
-                .filter(|(_, &t)| !predicate(t))
-                .collect::<Vec<_>>();
-            let mut values = retained.iter().map(|&(v, _)| *v).collect::<Vec<_>>();
-            let mut targets = retained.iter().map(|&(_, d)| *d).collect::<Vec<_>>();
+            let (mut values, mut targets): (Vec<_>, Vec<_>) =
+                values.iter().zip(targets.iter()).filter(|(_, &t)| !predicate(t)).unzip();
 
             if !predicate(*otherwise) {
                 targets.push(*otherwise);
@@ -89,20 +84,21 @@ fn remove_successors<F>(
             let retained_targets_len = targets.len();
 
             if targets.is_empty() {
-                Some(TerminatorKind::Unreachable)
+                TerminatorKind::Unreachable
             } else if targets.len() == 1 {
-                Some(TerminatorKind::Goto { target: targets[0] })
+                TerminatorKind::Goto { target: targets[0] }
             } else if original_targets_len != retained_targets_len {
-                Some(TerminatorKind::SwitchInt {
+                TerminatorKind::SwitchInt {
                     discr: discr.clone(),
                     switch_ty,
                     values: Cow::from(values),
                     targets,
-                })
+                }
             } else {
-                None
+                return None;
             }
         }
-        _ => None,
-    }
+        _ => return None,
+    };
+    Some(terminator)
 }
index 96059fa43e52124f3f2e1d3959e595ea1e16962a..97621f205fbb7c28f94557fc627b532b450aec5a 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_attr = { path = "../librustc_attr" }
index f3f3c3e33a46d1f64d7191a8419bb2fb5eedfe91..0c3f6fee665e85bc4afa1736e2ee7ffdef71fb30 100644 (file)
@@ -10,7 +10,6 @@
 use rustc_hir::{GeneratorKind, HirIdMap, Node};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::Subst;
@@ -35,7 +34,7 @@
 
 /// Construct the MIR for a given `DefId`.
 fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
-    let id = tcx.hir().as_local_hir_id(def.did);
+    let id = tcx.hir().local_def_id_to_hir_id(def.did);
 
     // Figure out what primary body this item has.
     let (body_id, return_ty_span) = match tcx.hir().get(id) {
@@ -798,22 +797,12 @@ fn args_and_body(
         argument_scope: region::Scope,
         ast_body: &'tcx hir::Expr<'tcx>,
     ) -> BlockAnd<()> {
-        let tcx = self.hir.tcx();
-        let attrs = tcx.codegen_fn_attrs(fn_def_id);
-        let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED);
-
         // Allocate locals for the function arguments
         for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
             let source_info =
                 SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
             let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
 
-            // Emit function argument debuginfo only for non-naked functions.
-            // See: https://github.com/rust-lang/rust/issues/42779
-            if naked {
-                continue;
-            }
-
             // If this is a simple binding pattern, give debuginfo a nice name.
             if let Some(arg) = arg_opt {
                 if let Some(ident) = arg.pat.simple_ident() {
@@ -826,6 +815,7 @@ fn args_and_body(
             }
         }
 
+        let tcx = self.hir.tcx();
         let tcx_hir = tcx.hir();
         let hir_typeck_results = self.hir.typeck_results();
 
index 30545558933f7d8ace5109ec80906bd2cc187dae..313bb979a5161bdaf28a27d16c2d6492f1245e9c 100644 (file)
@@ -12,7 +12,7 @@
 #![recursion_limit = "256"]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
index ac5d128a1baa26ded9d12d616534f7bd4416afbb..662b6c7735747c04f29ba53f0c753b50c27f286c 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_span::Span;
 
 crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
         if let FnKind::Closure(_) = fn_like_node.kind() {
@@ -37,7 +37,7 @@
 
         vis.reachable_recursive_calls.sort();
 
-        let hir_id = tcx.hir().as_local_hir_id(def_id);
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id));
         tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
             let mut db = lint.build("function cannot return without recursing");
index ea41a66b3e43d873d032821e6111a750fa55e4d7..c51c3bcf5628845808801358cf677a915c416336 100644 (file)
@@ -781,7 +781,7 @@ fn convert_path_expr<'a, 'tcx>(
         }
 
         Res::Def(DefKind::ConstParam, def_id) => {
-            let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
+            let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
             let item_id = cx.tcx.hir().get_parent_node(hir_id);
             let item_def_id = cx.tcx.hir().local_def_id(item_id);
             let generics = cx.tcx.generics_of(item_def_id);
index 744f319205f94a18bf18eaec1699344d9d346c72..1687286093d9c5062dade3278b6105fae1681468 100644 (file)
@@ -23,7 +23,7 @@
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
     let body_id = match def_id.as_local() {
         None => return,
-        Some(id) => tcx.hir().body_owned_by(tcx.hir().as_local_hir_id(id)),
+        Some(id) => tcx.hir().body_owned_by(tcx.hir().local_def_id_to_hir_id(id)),
     };
 
     let mut visitor = MatchVisitor {
index 25144bd610d3e11b3cce06a00cc1ec6b4565bc22..31d858849af484b66a3567643f63269d86b349b5 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 bitflags = "1.0"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
index c3a79660eb9b9fb15e2d6dc3c00dc532673a1771..675cfa41f10483b9a698321888ed73467328237d 100644 (file)
@@ -8,8 +8,8 @@
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{BytePos, Pos, Span};
 
-use log::debug;
 use std::char;
+use tracing::debug;
 
 mod tokentrees;
 mod unescape_error_reporting;
index d41775a143ad6c467e6e69d00d7e481cc137d2bc..6f249f491a647a62b10cb41e4f581628bf97f9d5 100644 (file)
@@ -18,7 +18,7 @@ pub(crate) fn emit_unescape_error(
     range: Range<usize>,
     error: EscapeError,
 ) {
-    log::debug!(
+    tracing::debug!(
         "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}",
         lit,
         span_with_quotes,
index 723e4333790ae002b108b35591d9fb78d3b81788..829e1a97b100d422440c7647df2edb16eca3e084 100644 (file)
@@ -20,7 +20,7 @@
 use std::path::Path;
 use std::str;
 
-use log::{debug, info};
+use tracing::{debug, info};
 
 pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");
 
index b6a8ee71beb0cc029e916498e814b295a78460dd..c942394fa7ccbd161a7dfa1812576a8ed3e6fb1f 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::{error_code, PResult};
 use rustc_span::Span;
 
-use log::debug;
+use tracing::debug;
 
 #[derive(Debug)]
 pub(super) enum InnerAttrPolicy<'a> {
index 2854356ab0fc6cd89582b6308bebf60d91d1bf98..27e1bb01d528418f3b8e680178b53e40b50863a5 100644 (file)
@@ -16,7 +16,7 @@
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
 
-use log::{debug, trace};
+use tracing::{debug, trace};
 
 const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments";
 
index 9b99eb2e0bd4b69cf82348ff43e8de9747a9c869..0ceb588b3afe7175ed36e3ede754325876886972 100644 (file)
@@ -4,7 +4,6 @@
 use super::{SemiColonMode, SeqSep, TokenExpectType};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
-use log::debug;
 use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Lit, UnOp, DUMMY_NODE_ID};
 use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
 use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
@@ -18,6 +17,7 @@
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use std::mem;
+use tracing::debug;
 
 /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
 /// dropped into the token stream, which happens while parsing the result of
@@ -318,11 +318,18 @@ fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
             // want to keep their span info to improve diagnostics in these cases in a later stage.
             (true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
             (true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
-            (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
             (true, Some(AssocOp::Add)) // `{ 42 } + 42
             // If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
             // `if x { a } else { b } && if y { c } else { d }`
-            if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
+            if !self.look_ahead(1, |t| t.is_used_keyword()) => {
+                // These cases are ambiguous and can't be identified in the parser alone.
+                let sp = self.sess.source_map().start_point(self.token.span);
+                self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
+                false
+            }
+            (true, Some(AssocOp::LAnd)) => {
+                // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
+                // above due to #74233.
                 // These cases are ambiguous and can't be identified in the parser alone.
                 let sp = self.sess.source_map().start_point(self.token.span);
                 self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
index 10d214e52abdbdda46f4b6df3de9508b5db0abcb..ce2dd15ab2601d10fa7c7f939dd6c463e19cc445 100644 (file)
@@ -20,9 +20,9 @@
 use rustc_span::source_map::{self, Span};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
-use log::debug;
 use std::convert::TryFrom;
 use std::mem;
+use tracing::debug;
 
 impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
@@ -1313,7 +1313,7 @@ fn parse_name_and_ty(
         vis: Visibility,
         attrs: Vec<Attribute>,
     ) -> PResult<'a, StructField> {
-        let name = self.parse_ident()?;
+        let name = self.parse_ident_common(false)?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
         Ok(StructField {
index b33ae4bed828b95ad518c274e778244e3f9cacef..a30131e4f7af49b75e8f8b81f78334576d26a326 100644 (file)
@@ -13,7 +13,6 @@
 use diagnostics::Error;
 pub use path::PathStyle;
 
-use log::debug;
 use rustc_ast::ast::DUMMY_NODE_ID;
 use rustc_ast::ast::{self, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
 use rustc_ast::ast::{
@@ -27,6 +26,7 @@
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::{respan, Span, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use tracing::debug;
 
 use std::{cmp, mem, slice};
 
index d4e44c54b127405fdcdc4c11fe474dda129938f5..0f2b46f7e16303b3cbc1f740ec8359977f6b93e5 100644 (file)
@@ -10,8 +10,8 @@
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::symbol::{kw, sym, Ident};
 
-use log::debug;
 use std::mem;
+use tracing::debug;
 
 /// Specifies how to parse a path.
 #[derive(Copy, Clone, PartialEq)]
index d9fa435e3ad680e002780a08b968c5cdb39e9adb..db481c0d0d4c2965eeb440f6c37a64a332b913f6 100644 (file)
@@ -9,7 +9,7 @@ name = "rustc_passes"
 path = "lib.rs"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index 0e5298acc2cafbcd333218205c00a40ac56d5116..29939c7cfafb05cd5b3a1bfbedee754a70741c6c 100644 (file)
@@ -62,7 +62,7 @@ fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
 
     fn check_def_id(&mut self, def_id: DefId) {
         if let Some(def_id) = def_id.as_local() {
-            let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
             if should_explore(self.tcx, hir_id) || self.struct_constructors.contains_key(&hir_id) {
                 self.worklist.push(hir_id);
             }
@@ -72,7 +72,7 @@ fn check_def_id(&mut self, def_id: DefId) {
 
     fn insert_def_id(&mut self, def_id: DefId) {
         if let Some(def_id) = def_id.as_local() {
-            let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+            let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
             debug_assert!(!should_explore(self.tcx, hir_id));
             self.live_symbols.insert(hir_id);
         }
@@ -461,7 +461,7 @@ fn create_and_seed_worklist<'tcx>(
         )
         .chain(
             // Seed entry point
-            tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_hir_id(def_id)),
+            tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)),
         )
         .collect::<Vec<_>>();
 
@@ -546,7 +546,7 @@ fn symbol_is_live(&mut self, id: hir::HirId) -> bool {
         for &impl_did in inherent_impls.iter() {
             for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
                 if let Some(did) = item_did.as_local() {
-                    let item_hir_id = self.tcx.hir().as_local_hir_id(did);
+                    let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(did);
                     if self.live_symbols.contains(&item_hir_id) {
                         return true;
                     }
index 95b236ba1c9e4ee5de5d59f82fc2d5136aaf43e7..be4c542ec3a1d89ea00cfde7d7c149d8b73c6d82 100644 (file)
@@ -13,7 +13,7 @@
 #[macro_use]
 extern crate rustc_middle;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 
 use rustc_middle::ty::query::Providers;
 
index c71dbdf515aa932dd677a9a78bf1fbff27787fd4..8d5c980609cd9a99c7d921e1ce4acf19bfadd8ce 100644 (file)
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirIdSet, Node};
+use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
 
@@ -53,7 +53,7 @@ fn method_might_be_inlined(
             return true;
         }
     }
-    match tcx.hir().find(tcx.hir().as_local_hir_id(impl_src)) {
+    match tcx.hir().find(tcx.hir().local_def_id_to_hir_id(impl_src)) {
         Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs),
         Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"),
     }
@@ -65,10 +65,11 @@ struct ReachableContext<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
     // The set of items which must be exported in the linkage sense.
-    reachable_symbols: HirIdSet,
+    reachable_symbols: FxHashSet<LocalDefId>,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
     // and will be scanned for further references.
-    worklist: Vec<hir::HirId>,
+    // FIXME(eddyb) benchmark if this would be faster as a `VecDeque`.
+    worklist: Vec<LocalDefId>,
     // Whether any output of this compilation is a library
     any_library: bool,
 }
@@ -100,35 +101,27 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
             _ => None,
         };
 
-        match res {
-            Some(Res::Local(hir_id)) => {
-                self.reachable_symbols.insert(hir_id);
-            }
-            Some(res) => {
-                if let Some((hir_id, def_id)) = res.opt_def_id().and_then(|def_id| {
-                    def_id.as_local().map(|def_id| (self.tcx.hir().as_local_hir_id(def_id), def_id))
-                }) {
-                    if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
-                        self.worklist.push(hir_id);
-                    } else {
-                        match res {
-                            // If this path leads to a constant, then we need to
-                            // recurse into the constant to continue finding
-                            // items that are reachable.
-                            Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
-                                self.worklist.push(hir_id);
-                            }
+        if let Some(res) = res {
+            if let Some(def_id) = res.opt_def_id().and_then(|def_id| def_id.as_local()) {
+                if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
+                    self.worklist.push(def_id);
+                } else {
+                    match res {
+                        // If this path leads to a constant, then we need to
+                        // recurse into the constant to continue finding
+                        // items that are reachable.
+                        Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
+                            self.worklist.push(def_id);
+                        }
 
-                            // If this wasn't a static, then the destination is
-                            // surely reachable.
-                            _ => {
-                                self.reachable_symbols.insert(hir_id);
-                            }
+                        // If this wasn't a static, then the destination is
+                        // surely reachable.
+                        _ => {
+                            self.reachable_symbols.insert(def_id);
                         }
                     }
                 }
             }
-            _ => {}
         }
 
         intravisit::walk_expr(self, expr)
@@ -149,7 +142,7 @@ fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
     // eligible for inlining and false otherwise.
     fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
         let hir_id = match def_id.as_local() {
-            Some(def_id) => self.tcx.hir().as_local_hir_id(def_id),
+            Some(def_id) => self.tcx.hir().local_def_id_to_hir_id(def_id),
             None => {
                 return false;
             }
@@ -181,7 +174,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                             // Check the impl. If the generics on the self
                             // type of the impl require inlining, this method
                             // does too.
-                            let impl_hir_id = self.tcx.hir().as_local_hir_id(impl_did);
+                            let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did);
                             match self.tcx.hir().expect_item(impl_hir_id).kind {
                                 hir::ItemKind::Impl { .. } => {
                                     let generics = self.tcx.generics_of(impl_did);
@@ -207,13 +200,15 @@ fn propagate(&mut self) {
                 continue;
             }
 
-            if let Some(ref item) = self.tcx.hir().find(search_item) {
+            if let Some(ref item) =
+                self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(search_item))
+            {
                 self.propagate_node(item, search_item);
             }
         }
     }
 
-    fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
+    fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
         if !self.any_library {
             // If we are building an executable, only explicitly extern
             // types need to be exported.
@@ -295,8 +290,9 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
                     self.visit_nested_body(body);
                 }
                 hir::ImplItemKind::Fn(_, body) => {
-                    let did = self.tcx.hir().get_parent_did(search_item);
-                    if method_might_be_inlined(self.tcx, impl_item, did) {
+                    let impl_def_id =
+                        self.tcx.parent(search_item.to_def_id()).unwrap().expect_local();
+                    if method_might_be_inlined(self.tcx, impl_item, impl_def_id) {
                         self.visit_nested_body(body)
                     }
                 }
@@ -315,7 +311,9 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
             _ => {
                 bug!(
                     "found unexpected node kind in worklist: {} ({:?})",
-                    self.tcx.hir().node_to_string(search_item),
+                    self.tcx
+                        .hir()
+                        .node_to_string(self.tcx.hir().local_def_id_to_hir_id(search_item)),
                     node,
                 );
             }
@@ -334,7 +332,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
 struct CollectPrivateImplItemsVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     access_levels: &'a privacy::AccessLevels,
-    worklist: &'a mut Vec<hir::HirId>,
+    worklist: &'a mut Vec<LocalDefId>,
 }
 
 impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> {
@@ -347,13 +345,16 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
         if codegen_attrs.contains_extern_indicator()
             || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
         {
-            self.worklist.push(item.hir_id);
+            self.worklist.push(def_id);
         }
 
         // We need only trait impls here, not inherent impls, and only non-exported ones
         if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
             if !self.access_levels.is_reachable(item.hir_id) {
-                self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id));
+                // FIXME(#53488) remove `let`
+                let tcx = self.tcx;
+                self.worklist
+                    .extend(items.iter().map(|ii_ref| tcx.hir().local_def_id(ii_ref.id.hir_id)));
 
                 let trait_def_id = match trait_ref.path.res {
                     Res::Def(DefKind::Trait, def_id) => def_id,
@@ -364,11 +365,9 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     return;
                 }
 
-                // FIXME(#53488) remove `let`
-                let tcx = self.tcx;
                 self.worklist.extend(
                     tcx.provided_trait_methods(trait_def_id)
-                        .map(|assoc| tcx.hir().as_local_hir_id(assoc.def_id.expect_local())),
+                        .map(|assoc| assoc.def_id.expect_local()),
                 );
             }
         }
@@ -381,7 +380,7 @@ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {
     }
 }
 
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet {
+fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> {
     debug_assert!(crate_num == LOCAL_CRATE);
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
@@ -403,11 +402,13 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
     //         If other crates link to us, they're going to expect to be able to
     //         use the lang items, so we need to be sure to mark them as
     //         exported.
-    reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id));
+    reachable_context
+        .worklist
+        .extend(access_levels.map.iter().map(|(id, _)| tcx.hir().local_def_id(*id)));
     for item in tcx.lang_items().items().iter() {
-        if let Some(did) = *item {
-            if let Some(hir_id) = did.as_local().map(|did| tcx.hir().as_local_hir_id(did)) {
-                reachable_context.worklist.push(hir_id);
+        if let Some(def_id) = *item {
+            if let Some(def_id) = def_id.as_local() {
+                reachable_context.worklist.push(def_id);
             }
         }
     }
@@ -426,7 +427,7 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet
     debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols);
 
     // Return the set of reachable symbols.
-    tcx.arena.alloc(reachable_context.reachable_symbols)
+    reachable_context.reachable_symbols
 }
 
 pub fn provide(providers: &mut Providers) {
index b2a89651881e5142252b86240e7a8caaaee86f9d..1af79abe4b9119451725e451bc9530a9934140f2 100644 (file)
@@ -807,7 +807,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
         return tcx.region_scope_tree(closure_base_def_id);
     }
 
-    let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(id) {
         let mut visitor = RegionResolutionVisitor {
             tcx,
index 3aed4942563ddcffb6267e9ede9554c862f2374f..91b8ae07637df001da64d72639d6ef7f9e2d9c16 100644 (file)
@@ -15,7 +15,7 @@ pub fn provide(providers: &mut Providers) {
             return None;
         }
 
-        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         let body = tcx.hir().body(tcx.hir().maybe_body_owned_by(hir_id)?);
 
         let mut local_collector = LocalCollector::default();
index 6f543e71b428137a0f1455bfcc9e6e55f31dff96..3641f0f8a31170002b04f4e4dc1dd20bef075404 100644 (file)
@@ -17,4 +17,4 @@ rustc_typeck = { path = "../librustc_typeck" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
index 3ba5acd00a09a0dd92ac5cb03d66e1150d2ae6f5..a3f2668691fd832107b443319420ed421dd4ec39 100644 (file)
@@ -226,7 +226,7 @@ fn def_id_visibility<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
 ) -> (ty::Visibility, Span, &'static str) {
-    match def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id)) {
+    match def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) {
         Some(hir_id) => {
             let vis = match tcx.hir().get(hir_id) {
                 Node::Item(item) => &item.vis,
@@ -431,7 +431,7 @@ impl VisibilityLike for Option<AccessLevel> {
     fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
         cmp::min(
             if let Some(def_id) = def_id.as_local() {
-                let hir_id = find.tcx.hir().as_local_hir_id(def_id);
+                let hir_id = find.tcx.hir().local_def_id_to_hir_id(def_id);
                 find.access_levels.map.get(&hir_id).cloned()
             } else {
                 Self::MAX
@@ -533,7 +533,7 @@ fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod
                     if let Res::Def(def_kind, def_id) = export.res {
                         let vis = def_id_visibility(self.tcx, def_id).0;
                         if let Some(def_id) = def_id.as_local() {
-                            let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+                            let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                             self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
                         }
                     }
@@ -650,7 +650,7 @@ fn update_visibility_of_intermediate_use_statements(
                 // there will be no corresponding item.
                 .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
                 .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| self.tcx.hir().as_local_hir_id(def_id))
+                    def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
                 })
                 .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
             {
@@ -913,7 +913,7 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) {
                     if export.vis == ty::Visibility::Public {
                         if let Some(def_id) = export.res.opt_def_id() {
                             if let Some(def_id) = def_id.as_local() {
-                                let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+                                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 self.update(hir_id, Some(AccessLevel::Exported));
                             }
                         }
@@ -1004,7 +1004,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
     fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
         if let Some(def_id) = def_id.as_local() {
-            let hir_id = self.ev.tcx.hir().as_local_hir_id(def_id);
+            let hir_id = self.ev.tcx.hir().local_def_id_to_hir_id(def_id);
             if let ((ty::Visibility::Public, ..), _)
             | (_, Some(AccessLevel::ReachableFromImplTrait)) =
                 (def_id_visibility(self.tcx(), def_id.to_def_id()), self.access_level)
@@ -1437,7 +1437,7 @@ fn path_is_private_type(&self, path: &hir::Path<'_>) -> bool {
         if let Some(did) = did.as_local() {
             // .. and it corresponds to a private type in the AST (this returns
             // `None` for type parameters).
-            match self.tcx.hir().find(self.tcx.hir().as_local_hir_id(did)) {
+            match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) {
                 Some(Node::Item(ref item)) => !item.vis.node.is_pub(),
                 Some(_) | None => false,
             }
@@ -1556,7 +1556,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                         let did = tr.path.res.def_id();
 
                         if let Some(did) = did.as_local() {
-                            self.trait_is_public(self.tcx.hir().as_local_hir_id(did))
+                            self.trait_is_public(self.tcx.hir().local_def_id_to_hir_id(did))
                         } else {
                             true // external traits must be public
                         }
@@ -1815,7 +1815,7 @@ fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
         }
 
         let hir_id = match def_id.as_local() {
-            Some(def_id) => self.tcx.hir().as_local_hir_id(def_id),
+            Some(def_id) => self.tcx.hir().local_def_id_to_hir_id(def_id),
             None => return false,
         };
 
@@ -1853,7 +1853,7 @@ fn leaks_private_dep(&self, item_id: DefId) -> bool {
         let ret = self.required_visibility == ty::Visibility::Public
             && self.tcx.is_private_dep(item_id.krate);
 
-        log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
+        tracing::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
         ret
     }
 }
index 64af9c5f1a15244a1c9b74704e552973a5f0235a..1e89d379cb77cb2182846bea4fe465fe3a0f1ce0 100644 (file)
@@ -11,10 +11,11 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc-rayon-core = "0.3.0"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
+rustc_macros = { path = "../librustc_macros" }
 rustc_index = { path = "../librustc_index" }
 rustc_serialize = { path = "../librustc_serialize" }
 rustc_span = { path = "../librustc_span" }
index 002b0f9c165dde4f3a967699dc1d72a659dc4773..e302784cc3e5fb5f78820d90b70ca436b0e700a1 100644 (file)
@@ -50,7 +50,7 @@
 use std::fmt;
 use std::hash::Hash;
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 pub struct DepNode<K> {
     pub kind: K,
     pub hash: Fingerprint,
@@ -152,7 +152,8 @@ fn to_fingerprint(&self, _: Ctxt) -> Fingerprint {
 /// some independent path or string that persists between runs without
 /// the need to be mapped or unmapped. (This ensures we can serialize
 /// them even in the absence of a tcx.)
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable)]
 pub struct WorkProductId {
     hash: Fingerprint,
 }
index 04a45090b722675d179f32c4edb4d5282449fc26..d70306b4869218d9ecce39f793ad8e3dbeecd5a4 100644 (file)
@@ -857,7 +857,7 @@ fn next_virtual_depnode_index(&self) -> DepNodeIndex {
 /// may be added -- for example, new monomorphizations -- even if
 /// nothing in P changed!). We will compare that hash against the
 /// previous hash. If it matches up, we can reuse the object file.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
 pub struct WorkProduct {
     pub cgu_name: String,
     /// Saved file associated with this CGU.
index 5cba64cac4b3449eb26eddc6c053c460444f6aea..29357ce9449ce26f48df11c3ac0c12c743efa0a2 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
 pub struct PreviousDepGraph<K: DepKind> {
     data: SerializedDepGraph<K>,
     index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>,
index 4a89da23ea6a59239ff9a99834d9bc029e51d2bf..932c6d2a2f184260434bf38989fa5d9626f88dff 100644 (file)
@@ -9,7 +9,7 @@ pub struct SerializedDepNodeIndex { .. }
 }
 
 /// Data for use when recompiling the **current crate**.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
 pub struct SerializedDepGraph<K: DepKind> {
     /// The set of all DepNodes in the graph
     pub nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
index 4bbba7befe93f00363e03a8b458cca79f19f6e0d..26b76a9c006cd1a3b93c48879672f02eb93d5c57 100644 (file)
@@ -7,9 +7,11 @@
 #![feature(stmt_expr_attributes)]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_data_structures;
+#[macro_use]
+extern crate rustc_macros;
 
 pub mod cache;
 pub mod dep_graph;
index f0beec0a177262a315f5c1de65413c52b3cc3e4d..1839e1af45eeff7d004dc1bacc5efbacec42a89e 100644 (file)
@@ -43,9 +43,8 @@ fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
         OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
         OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;
 
-    fn complete<CTX: QueryContext>(
+    fn complete(
         &self,
-        tcx: CTX,
         lock_sharded_storage: &mut Self::Sharded,
         key: Self::Key,
         value: Self::Value,
@@ -112,9 +111,8 @@ fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
     }
 
     #[inline]
-    fn complete<CTX: QueryContext>(
+    fn complete(
         &self,
-        _: CTX,
         lock_sharded_storage: &mut Self::Sharded,
         key: K,
         value: V,
@@ -195,9 +193,8 @@ fn lookup<CTX: QueryContext, R, OnHit, OnMiss>(
     }
 
     #[inline]
-    fn complete<CTX: QueryContext>(
+    fn complete(
         &self,
-        _: CTX,
         lock_sharded_storage: &mut Self::Sharded,
         key: K,
         value: V,
index cc7d0a157035578311fd942daa348c7768c40b7b..ae042cc808126bec5a2085fd74399789368d412a 100644 (file)
@@ -264,7 +264,7 @@ fn try_start<'a, 'b>(
     /// Completes the query by updating the query cache with the `result`,
     /// signals the waiter and forgets the JobOwner, so it won't poison the query
     #[inline(always)]
-    fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
+    fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
         // We can move out of `self` here because we `mem::forget` it below
         let key = unsafe { ptr::read(&self.key) };
         let state = self.state;
@@ -278,7 +278,7 @@ fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C
                 QueryResult::Started(job) => job,
                 QueryResult::Poisoned => panic!(),
             };
-            let result = state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index);
+            let result = state.cache.complete(&mut lock.cache, key, result, dep_node_index);
             (job, result)
         };
 
@@ -432,7 +432,7 @@ fn try_execute_query<CTX, C>(
             tcx.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
         }
 
-        return job.complete(tcx, result, dep_node_index);
+        return job.complete(result, dep_node_index);
     }
 
     let dep_node = query.to_dep_node(tcx, &key);
@@ -458,7 +458,7 @@ fn try_execute_query<CTX, C>(
             })
         });
         if let Some((result, dep_node_index)) = loaded {
-            return job.complete(tcx, result, dep_node_index);
+            return job.complete(result, dep_node_index);
         }
     }
 
@@ -609,7 +609,7 @@ fn force_query_with_job<C, CTX>(
         }
     }
 
-    let result = job.complete(tcx, result, dep_node_index);
+    let result = job.complete(result, dep_node_index);
 
     (result, dep_node_index)
 }
index 1cb49132ead9cf7f103ed057b25792d0abbdc789..e5260866f29e71695aa206f273e70f57ee02b8b3 100644 (file)
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_ast = { path = "../librustc_ast" }
 rustc_arena = { path = "../librustc_arena" }
 rustc_middle = { path = "../librustc_middle" }
index 11c7793b3ad9a3903471f69ee7595883e70a4e5a..ddc16d18952ade992a2ae0d80b7355750674e879 100644 (file)
@@ -37,9 +37,9 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 
-use log::debug;
 use std::cell::Cell;
 use std::ptr;
+use tracing::debug;
 
 type Res = def::Res<NodeId>;
 
index 32af920020ce6438ea15b5761d08627042d9d6bb..7dbf51aab28f19a8ddec7559d77ed15307f20496 100644 (file)
@@ -1,5 +1,4 @@
 use crate::Resolver;
-use log::debug;
 use rustc_ast::ast::*;
 use rustc_ast::token::{self, Token};
 use rustc_ast::visit::{self, FnKind};
@@ -11,6 +10,7 @@
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
+use tracing::debug;
 
 crate fn collect_definitions(
     resolver: &mut Resolver<'_>,
index de92204a7c2f07e33b875a264e12e33ce351f321..1e5e937db663d9df62c2c507481f38c073faea15 100644 (file)
@@ -1,7 +1,6 @@
 use std::cmp::Reverse;
 use std::ptr;
 
-use log::debug;
 use rustc_ast::ast::{self, Path};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_ast_pretty::pprust;
@@ -18,6 +17,7 @@
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span};
+use tracing::debug;
 
 use crate::imports::{Import, ImportKind, ImportResolver};
 use crate::path_names_to_string;
index d3f45f962a025e5d3cbf2a51dffdb45373871e78..ef51a1c73afdff9e4a1ba287aa0689933214135a 100644 (file)
@@ -28,7 +28,7 @@
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{MultiSpan, Span};
 
-use log::*;
+use tracing::*;
 
 use std::cell::Cell;
 use std::{mem, ptr};
index 7ecfe2554ec8ab04e0d6bf7da75c21429dc0a5e7..2f63257a98214bd83a4b0f0a39c0532af8eaf34a 100644 (file)
 use rustc_span::Span;
 use smallvec::{smallvec, SmallVec};
 
-use log::debug;
 use rustc_span::source_map::{respan, Spanned};
 use std::collections::BTreeSet;
 use std::mem::{replace, take};
+use tracing::debug;
 
 mod diagnostics;
 crate mod lifetimes;
@@ -1732,7 +1732,12 @@ fn smart_resolve_path_fragment(
         source: PathSource<'ast>,
         crate_lint: CrateLint,
     ) -> PartialRes {
-        log::debug!("smart_resolve_path_fragment(id={:?},qself={:?},path={:?}", id, qself, path);
+        tracing::debug!(
+            "smart_resolve_path_fragment(id={:?},qself={:?},path={:?}",
+            id,
+            qself,
+            path
+        );
         let ns = source.namespace();
         let is_expected = &|res| source.is_expected(res);
 
index a7d3697405751782b82f579613424af3a6ae6351..2e606beca26b43cd247bde82c16c778ac69157bd 100644 (file)
@@ -7,6 +7,7 @@
 
 use rustc_ast::ast::{self, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
 use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
@@ -19,7 +20,7 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
-use log::debug;
+use tracing::debug;
 
 type Res = def::Res<ast::NodeId>;
 
@@ -175,16 +176,40 @@ pub(crate) fn smart_resolve_report_errors(
         let code = source.error_code(res.is_some());
         let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
 
+        let is_assoc_fn = self.self_type_is_available(span);
         // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
-        if ["this", "my"].contains(&&*item_str.as_str())
-            && self.self_value_is_available(path[0].ident.span, span)
-        {
+        if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn {
             err.span_suggestion_short(
                 span,
                 "you might have meant to use `self` here instead",
                 "self".to_string(),
                 Applicability::MaybeIncorrect,
             );
+            if !self.self_value_is_available(path[0].ident.span, span) {
+                if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) =
+                    &self.diagnostic_metadata.current_function
+                {
+                    let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
+                        (param.span.shrink_to_lo(), "&self, ")
+                    } else {
+                        (
+                            self.r
+                                .session
+                                .source_map()
+                                .span_through_char(*fn_span, '(')
+                                .shrink_to_hi(),
+                            "&self",
+                        )
+                    };
+                    err.span_suggestion_verbose(
+                        span,
+                        "if you meant to use `self`, you are also missing a `self` receiver \
+                         argument",
+                        sugg.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
         }
 
         // Emit special messages for unresolved `Self` and `self`.
@@ -213,7 +238,38 @@ pub(crate) fn smart_resolve_report_errors(
                 if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
                     err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
                 } else {
-                    err.span_label(*span, "this function doesn't have a `self` parameter");
+                    let doesnt = if is_assoc_fn {
+                        let (span, sugg) = fn_kind
+                            .decl()
+                            .inputs
+                            .get(0)
+                            .map(|p| (p.span.shrink_to_lo(), "&self, "))
+                            .unwrap_or_else(|| {
+                                (
+                                    self.r
+                                        .session
+                                        .source_map()
+                                        .span_through_char(*span, '(')
+                                        .shrink_to_hi(),
+                                    "&self",
+                                )
+                            });
+                        err.span_suggestion_verbose(
+                            span,
+                            "add a `self` receiver parameter to make the associated `fn` a method",
+                            sugg.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        "doesn't"
+                    } else {
+                        "can't"
+                    };
+                    if let Some(ident) = fn_kind.ident() {
+                        err.span_label(
+                            ident.span,
+                            &format!("this function {} have a `self` parameter", doesnt),
+                        );
+                    }
                 }
             }
             return (err, Vec::new());
index 2046419d984d0fd0be20c2e0fb0fe87f793cb2a2..e2f0d388f7e5373eaa0e470017e0aa75e8c2c0d3 100644 (file)
@@ -26,7 +26,7 @@
 use std::cell::Cell;
 use std::mem::take;
 
-use log::debug;
+use tracing::debug;
 
 // This counts the no of times a lifetime is used
 #[derive(Clone, Copy, Debug)]
@@ -607,7 +607,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
                         let def = self.map.defs.get(&lifetime.hir_id).cloned();
                         if let Some(Region::LateBound(_, def_id, _)) = def {
                             if let Some(def_id) = def_id.as_local() {
-                                let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+                                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 // Ensure that the parent of the def is an item, not HRTB
                                 let parent_id = self.tcx.hir().get_parent_node(hir_id);
                                 let parent_impl_id = hir::ImplItemId { hir_id: parent_id };
@@ -1154,7 +1154,8 @@ fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, lab
                     if let Some(def) =
                         lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0()))
                     {
-                        let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap().expect_local());
+                        let hir_id =
+                            tcx.hir().local_def_id_to_hir_id(def.id().unwrap().expect_local());
 
                         signal_shadowing_problem(
                             tcx,
@@ -1525,7 +1526,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
 
             match lifetimeuseset {
                 Some(LifetimeUseSet::One(lifetime)) => {
-                    let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+                    let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                     debug!("hir id first={:?}", hir_id);
                     if let Some((id, span, name)) = match self.tcx.hir().get(hir_id) {
                         Node::Lifetime(hir_lifetime) => Some((
@@ -1545,7 +1546,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
 
                         if let Some(parent_def_id) = self.tcx.parent(def_id) {
                             if let Some(def_id) = parent_def_id.as_local() {
-                                let parent_hir_id = self.tcx.hir().as_local_hir_id(def_id);
+                                let parent_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                                 // lifetimes in `derive` expansions don't count (Issue #53738)
                                 if self.tcx.hir().attrs(parent_hir_id).iter().any(|attr| {
                                     self.tcx.sess.check_name(attr, sym::automatically_derived)
@@ -1583,7 +1584,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                     debug!("not one use lifetime");
                 }
                 None => {
-                    let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+                    let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                     if let Some((id, span, name)) = match self.tcx.hir().get(hir_id) {
                         Node::Lifetime(hir_lifetime) => Some((
                             hir_lifetime.hir_id,
@@ -1939,7 +1940,7 @@ fn visit_segment_args(
 
             let map = &self.map;
             let unsubst = if let Some(def_id) = def_id.as_local() {
-                let id = self.tcx.hir().as_local_hir_id(def_id);
+                let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
                 &map.object_lifetime_defaults[&id]
             } else {
                 let tcx = self.tcx;
@@ -2637,7 +2638,7 @@ fn check_lifetime_param_for_shadowing(
                 Scope::Binder { ref lifetimes, s, .. } => {
                     if let Some(&def) = lifetimes.get(&param.name.normalize_to_macros_2_0()) {
                         let hir_id =
-                            self.tcx.hir().as_local_hir_id(def.id().unwrap().expect_local());
+                            self.tcx.hir().local_def_id_to_hir_id(def.id().unwrap().expect_local());
 
                         signal_shadowing_problem(
                             self.tcx,
index 79f5a27bb28ed178f7635f0d926d2dae2d969c98..339a5ae6675e7178e4c8a5c1b7ea1d785397b281 100644 (file)
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
-use log::debug;
 use std::cell::{Cell, RefCell};
 use std::collections::BTreeSet;
 use std::{cmp, fmt, iter, ptr};
+use tracing::debug;
 
 use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
 use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
index 7a5ae0ace3ae67e4f4500054d22c1f3a6dc0ac81..3c2edc1fa5571fae34cf5a56636400b0238451f1 100644 (file)
@@ -9,7 +9,7 @@ name = "rustc_save_analysis"
 path = "lib.rs"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast = { path = "../librustc_ast" }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
index 5aa676e3fce8eafb8a7663d97f124ea344440df6..f33d2f46aa2699f32f673fc5a1861e0c9c8bee60 100644 (file)
@@ -45,7 +45,7 @@
     RefKind, Relation, RelationKind, SpanData,
 };
 
-use log::{debug, error};
+use tracing::{debug, error};
 
 macro_rules! down_cast_data {
     ($id:ident, $kind:ident, $sp:expr) => {
index 6469971fce830e4ff7e5692a80cac0f767ba25c9..ca98ada4e57290be539c8f6052ba8ff7a6f534f5 100644 (file)
@@ -45,7 +45,7 @@
     RefKind, Relation, RelationKind, SpanData,
 };
 
-use log::{debug, error, info};
+use tracing::{debug, error, info};
 
 pub struct SaveContext<'tcx> {
     tcx: TyCtxt<'tcx>,
index 84206df50ccee318cdd19c597785f04da1f3adcb..939e6a59ba0990e99bd9d0c6e90e5b2853228fe3 100644 (file)
@@ -11,3 +11,6 @@ path = "lib.rs"
 [dependencies]
 indexmap = "1"
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+
+[dev-dependencies]
+rustc_macros = { path = "../librustc_macros" }
index 49b8094abd0eb5d64f7c491d1c292c0498a23cb1..3d274cb01507b004bcde7191709a66c6c6bb4ed4 100644 (file)
@@ -9,8 +9,8 @@
 
 use smallvec::{Array, SmallVec};
 
-impl<A: Array<Item: Encodable>> Encodable for SmallVec<A> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -20,8 +20,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<A: Array<Item: Decodable>> Decodable for SmallVec<A> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
+impl<D: Decoder, A: Array<Item: Decodable<D>>> Decodable<D> for SmallVec<A> {
+    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>
@@ -33,8 +33,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for LinkedList<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for LinkedList<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -44,8 +44,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for LinkedList<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
+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 {
@@ -56,8 +56,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for VecDeque<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for VecDeque<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -67,8 +67,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for VecDeque<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
+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 {
@@ -79,12 +79,12 @@ fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
     }
 }
 
-impl<K, V> Encodable for BTreeMap<K, V>
+impl<S: Encoder, K, V> Encodable<S> for BTreeMap<K, V>
 where
-    K: Encodable + PartialEq + Ord,
-    V: Encodable,
+    K: Encodable<S> + PartialEq + Ord,
+    V: Encodable<S>,
 {
-    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+    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))?;
@@ -95,12 +95,12 @@ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<K, V> Decodable for BTreeMap<K, V>
+impl<D: Decoder, K, V> Decodable<D> for BTreeMap<K, V>
 where
-    K: Decodable + PartialEq + Ord,
-    V: Decodable,
+    K: Decodable<D> + PartialEq + Ord,
+    V: Decodable<D>,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
+    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 {
@@ -113,11 +113,11 @@ fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
     }
 }
 
-impl<T> Encodable for BTreeSet<T>
+impl<S: Encoder, T> Encodable<S> for BTreeSet<T>
 where
-    T: Encodable + PartialEq + Ord,
+    T: Encodable<S> + PartialEq + Ord,
 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -127,11 +127,11 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T> Decodable for BTreeSet<T>
+impl<D: Decoder, T> Decodable<D> for BTreeSet<T>
 where
-    T: Decodable + PartialEq + Ord,
+    T: Decodable<D> + PartialEq + Ord,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
+    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 {
@@ -142,13 +142,13 @@ fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
     }
 }
 
-impl<K, V, S> Encodable for HashMap<K, V, S>
+impl<E: Encoder, K, V, S> Encodable<E> for HashMap<K, V, S>
 where
-    K: Encodable + Eq,
-    V: Encodable,
+    K: Encodable<E> + Eq,
+    V: Encodable<E>,
     S: BuildHasher,
 {
-    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+    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))?;
@@ -159,13 +159,13 @@ fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<K, V, S> Decodable for HashMap<K, V, S>
+impl<D: Decoder, K, V, S> Decodable<D> for HashMap<K, V, S>
 where
-    K: Decodable + Hash + Eq,
-    V: Decodable,
+    K: Decodable<D> + Hash + Eq,
+    V: Decodable<D>,
     S: BuildHasher + Default,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
+    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);
@@ -179,12 +179,12 @@ fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
     }
 }
 
-impl<T, S> Encodable for HashSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for HashSet<T, S>
 where
-    T: Encodable + Eq,
+    T: Encodable<E> + Eq,
     S: BuildHasher,
 {
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -194,12 +194,22 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<T, S> Decodable for HashSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for &HashSet<T, S>
 where
-    T: Decodable + Hash + Eq,
+    T: Encodable<E> + Eq,
+    S: BuildHasher,
+{
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        (**self).encode(s)
+    }
+}
+
+impl<D: Decoder, T, S> Decodable<D> for HashSet<T, S>
+where
+    T: Decodable<D> + Hash + Eq,
     S: BuildHasher + Default,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
+    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);
@@ -211,13 +221,13 @@ fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
     }
 }
 
-impl<K, V, S> Encodable for indexmap::IndexMap<K, V, S>
+impl<E: Encoder, K, V, S> Encodable<E> for indexmap::IndexMap<K, V, S>
 where
-    K: Encodable + Hash + Eq,
-    V: Encodable,
+    K: Encodable<E> + Hash + Eq,
+    V: Encodable<E>,
     S: BuildHasher,
 {
-    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+    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))?;
@@ -228,13 +238,13 @@ fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<K, V, S> Decodable for indexmap::IndexMap<K, V, S>
+impl<D: Decoder, K, V, S> Decodable<D> for indexmap::IndexMap<K, V, S>
 where
-    K: Decodable + Hash + Eq,
-    V: Decodable,
+    K: Decodable<D> + Hash + Eq,
+    V: Decodable<D>,
     S: BuildHasher + Default,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
+    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);
@@ -248,12 +258,12 @@ fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error
     }
 }
 
-impl<T, S> Encodable for indexmap::IndexSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for indexmap::IndexSet<T, S>
 where
-    T: Encodable + Hash + Eq,
+    T: Encodable<E> + Hash + Eq,
     S: BuildHasher,
 {
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?;
@@ -263,12 +273,12 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<T, S> Decodable for indexmap::IndexSet<T, S>
+impl<D: Decoder, T, S> Decodable<D> for indexmap::IndexSet<T, S>
 where
-    T: Decodable + Hash + Eq,
+    T: Decodable<D> + Hash + Eq,
     S: BuildHasher + Default,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
+    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);
@@ -280,8 +290,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for Rc<[T]> {
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
             for (index, e) in self.iter().enumerate() {
                 s.emit_seq_elt(index, |s| e.encode(s))?;
@@ -291,8 +301,8 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for Rc<[T]> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Rc<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
+    fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
         d.read_seq(|d, len| {
             let mut vec = Vec::with_capacity(len);
             for index in 0..len {
@@ -303,8 +313,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Rc<[T]>, D::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for Arc<[T]> {
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
             for (index, e) in self.iter().enumerate() {
                 s.emit_seq_elt(index, |s| e.encode(s))?;
@@ -314,8 +324,8 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for Arc<[T]> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Arc<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
+    fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
         d.read_seq(|d, len| {
             let mut vec = Vec::with_capacity(len);
             for index in 0..len {
index ab7f6975325bc0ccb403e5fd99483d2829bae210..6c8965aa2e31f92bac37026d419bac493c67b6be 100644 (file)
 //!
 //! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via
 //! the serialization API.
-//! To be able to encode a piece of data, it must implement the `serialize::RustcEncodable` trait.
-//! To be able to decode a piece of data, it must implement the `serialize::RustcDecodable` trait.
+//! To be able to encode a piece of data, it must implement the `serialize::Encodable` trait.
+//! To be able to decode a piece of data, it must implement the `serialize::Decodable` trait.
 //! The Rust compiler provides an annotation to automatically generate the code for these traits:
-//! `#[derive(RustcDecodable, RustcEncodable)]`
+//! `#[derive(Decodable, Encodable)]`
 //!
 //! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects.
 //! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value.
 //! A `json::Json` value can be encoded as a string or buffer using the functions described above.
 //! You can also use the `json::Encoder` object, which implements the `Encoder` trait.
 //!
-//! When using `ToJson` the `RustcEncodable` trait implementation is not mandatory.
+//! When using `ToJson` the `Encodable` trait implementation is not mandatory.
 //!
 //! # Examples of use
 //!
 //!
 //! ```rust
 //! # #![feature(rustc_private)]
+//! use rustc_macros::{Decodable, Encodable};
 //! use rustc_serialize::json;
 //!
 //! // Automatically generate `Decodable` and `Encodable` trait implementations
-//! #[derive(RustcDecodable, RustcEncodable)]
+//! #[derive(Decodable, Encodable)]
 //! pub struct TestStruct  {
 //!     data_int: u8,
 //!     data_str: String,
 //!
 //! ```rust
 //! # #![feature(rustc_private)]
+//! use rustc_macros::Encodable;
 //! use rustc_serialize::json::{self, ToJson, Json};
 //!
 //! // A custom data structure
 //!     }
 //! }
 //!
-//! // Only generate `RustcEncodable` trait implementation
-//! #[derive(RustcEncodable)]
+//! // Only generate `Encodable` trait implementation
+//! #[derive(Encodable)]
 //! pub struct ComplexNumRecord {
 //!     uid: u8,
 //!     dsc: String,
 //!
 //! ```rust
 //! # #![feature(rustc_private)]
+//! use rustc_macros::Decodable;
 //! use std::collections::BTreeMap;
 //! use rustc_serialize::json::{self, Json, ToJson};
 //!
-//! // Only generate `RustcDecodable` trait implementation
-//! #[derive(RustcDecodable)]
+//! // Only generate `Decodable` trait implementation
+//! #[derive(Decodable)]
 //! pub struct TestStruct {
 //!     data_int: u8,
 //!     data_str: String,
@@ -292,7 +295,7 @@ pub fn error_str(error: ErrorCode) -> &'static str {
 }
 
 /// Shortcut function to decode a JSON `&str` into an object
-pub fn decode<T: crate::Decodable>(s: &str) -> DecodeResult<T> {
+pub fn decode<T: crate::Decodable<Decoder>>(s: &str) -> DecodeResult<T> {
     let json = match from_str(s) {
         Ok(x) => x,
         Err(e) => return Err(ParseError(e)),
@@ -303,7 +306,9 @@ pub fn decode<T: crate::Decodable>(s: &str) -> DecodeResult<T> {
 }
 
 /// Shortcut function to encode a `T` into a JSON `String`
-pub fn encode<T: crate::Encodable>(object: &T) -> Result<string::String, EncoderError> {
+pub fn encode<T: for<'r> crate::Encodable<Encoder<'r>>>(
+    object: &T,
+) -> Result<string::String, EncoderError> {
     let mut s = String::new();
     {
         let mut encoder = Encoder::new(&mut s);
@@ -1144,8 +1149,8 @@ fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
     }
 }
 
-impl Encodable for Json {
-    fn encode<E: crate::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+impl<E: crate::Encoder> Encodable<E> for Json {
+    fn encode(&self, e: &mut E) -> Result<(), E::Error> {
         match *self {
             Json::I64(v) => v.encode(e),
             Json::U64(v) => v.encode(e),
@@ -2727,7 +2732,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> {
+impl<'a, T: for<'r> Encodable<Encoder<'r>>> fmt::Display for AsJson<'a, T> {
     /// Encodes a json value into a string
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut shim = FormatShim { inner: f };
@@ -2747,7 +2752,7 @@ pub fn indent(mut self, indent: usize) -> AsPrettyJson<'a, T> {
     }
 }
 
-impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> {
+impl<'a, T: for<'x> Encodable<PrettyEncoder<'x>>> fmt::Display for AsPrettyJson<'a, T> {
     /// Encodes a json value into a string
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut shim = FormatShim { inner: f };
index 3dc3e783820963e4e0dc417c8c44380f92ab0b7a..265b3b95e956a9c0e9505cd3ab71be6cff89c26e 100644 (file)
@@ -10,7 +10,6 @@
     test(attr(allow(unused_variables), deny(warnings)))
 )]
 #![feature(box_syntax)]
-#![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
@@ -19,9 +18,6 @@
 
 pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};
 
-pub use self::serialize::{SpecializationError, SpecializedDecoder, SpecializedEncoder};
-pub use self::serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
-
 mod collection_impls;
 mod serialize;
 
index 29c5737ad895abc8b834394fcb6f328ddefb1ee4..c0e23b89a60df3bc1cf64954116e18c931cb9c46 100644 (file)
@@ -4,7 +4,6 @@
 Core encoding and decoding interfaces.
 */
 
-use std::any;
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::marker::PhantomData;
@@ -380,282 +379,155 @@ fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error
     fn error(&mut self, err: &str) -> Self::Error;
 }
 
-pub trait Encodable {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>;
-}
-
-pub trait Decodable: Sized {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
-}
-
-impl Encodable for usize {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_usize(*self)
-    }
-}
-
-impl Decodable for usize {
-    fn decode<D: Decoder>(d: &mut D) -> Result<usize, D::Error> {
-        d.read_usize()
-    }
-}
-
-impl Encodable for u8 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u8(*self)
-    }
-}
-
-impl Decodable for u8 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<u8, D::Error> {
-        d.read_u8()
-    }
-}
-
-impl Encodable for u16 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u16(*self)
-    }
-}
-
-impl Decodable for u16 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<u16, D::Error> {
-        d.read_u16()
-    }
-}
-
-impl Encodable for u32 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u32(*self)
-    }
+/// Trait for types that can be serialized
+///
+/// This can be implemented using the `Encodable`, `TyEncodable` and
+/// `MetadataEncodable` macros.
+///
+/// * `Encodable` should be used in crates that don't depend on
+///   `rustc_middle`.
+/// * `MetadataEncodable` is used in `rustc_metadata` for types that contain
+///   `rustc_metadata::rmeta::Lazy`.
+/// * `TyEncodable` should be used for types that are only serialized in crate
+///   metadata or the incremental cache. This is most types in `rustc_middle`.
+pub trait Encodable<S: Encoder> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error>;
 }
 
-impl Decodable for u32 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<u32, D::Error> {
-        d.read_u32()
-    }
-}
+/// Trait for types that can be deserialized
+///
+/// This can be implemented using the `Decodable`, `TyDecodable` and
+/// `MetadataDecodable` macros.
+///
+/// * `Decodable` should be used in crates that don't depend on
+///   `rustc_middle`.
+/// * `MetadataDecodable` is used in `rustc_metadata` for types that contain
+///   `rustc_metadata::rmeta::Lazy`.
+/// * `TyDecodable` should be used for types that are only serialized in crate
+///   metadata or the incremental cache. This is most types in `rustc_middle`.
+pub trait Decodable<D: Decoder>: Sized {
+    fn decode(d: &mut D) -> Result<Self, D::Error>;
+}
+
+macro_rules! direct_serialize_impls {
+    ($($ty:ident $emit_method:ident $read_method:ident),*) => {
+        $(
+            impl<S: Encoder> Encodable<S> for $ty {
+                fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+                    s.$emit_method(*self)
+                }
+            }
 
-impl Encodable for ::std::num::NonZeroU32 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+            impl<D: Decoder> Decodable<D> for $ty {
+                fn decode(d: &mut D) -> Result<$ty, D::Error> {
+                    d.$read_method()
+                }
+            }
+        )*
+    }
+}
+
+direct_serialize_impls! {
+    usize emit_usize read_usize,
+    u8 emit_u8 read_u8,
+    u16 emit_u16 read_u16,
+    u32 emit_u32 read_u32,
+    u64 emit_u64 read_u64,
+    u128 emit_u128 read_u128,
+    isize emit_isize read_isize,
+    i8 emit_i8 read_i8,
+    i16 emit_i16 read_i16,
+    i32 emit_i32 read_i32,
+    i64 emit_i64 read_i64,
+    i128 emit_i128 read_i128,
+    f32 emit_f32 read_f32,
+    f64 emit_f64 read_f64,
+    bool emit_bool read_bool,
+    char emit_char read_char
+}
+
+impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u32(self.get())
     }
 }
 
-impl Decodable for ::std::num::NonZeroU32 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+impl<D: Decoder> Decodable<D> for ::std::num::NonZeroU32 {
+    fn decode(d: &mut D) -> Result<Self, D::Error> {
         d.read_u32().map(|d| ::std::num::NonZeroU32::new(d).unwrap())
     }
 }
 
-impl Encodable for u64 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u64(*self)
-    }
-}
-
-impl Decodable for u64 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<u64, D::Error> {
-        d.read_u64()
-    }
-}
-
-impl Encodable for u128 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u128(*self)
-    }
-}
-
-impl Decodable for u128 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<u128, D::Error> {
-        d.read_u128()
-    }
-}
-
-impl Encodable for isize {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_isize(*self)
-    }
-}
-
-impl Decodable for isize {
-    fn decode<D: Decoder>(d: &mut D) -> Result<isize, D::Error> {
-        d.read_isize()
-    }
-}
-
-impl Encodable for i8 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_i8(*self)
-    }
-}
-
-impl Decodable for i8 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<i8, D::Error> {
-        d.read_i8()
-    }
-}
-
-impl Encodable for i16 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_i16(*self)
-    }
-}
-
-impl Decodable for i16 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<i16, D::Error> {
-        d.read_i16()
-    }
-}
-
-impl Encodable for i32 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_i32(*self)
-    }
-}
-
-impl Decodable for i32 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<i32, D::Error> {
-        d.read_i32()
-    }
-}
-
-impl Encodable for i64 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_i64(*self)
-    }
-}
-
-impl Decodable for i64 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<i64, D::Error> {
-        d.read_i64()
-    }
-}
-
-impl Encodable for i128 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_i128(*self)
-    }
-}
-
-impl Decodable for i128 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<i128, D::Error> {
-        d.read_i128()
+impl<S: Encoder> Encodable<S> for str {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(self)
     }
 }
 
-impl Encodable for str {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for &str {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_str(self)
     }
 }
 
-impl Encodable for String {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for String {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_str(&self[..])
     }
 }
 
-impl Decodable for String {
-    fn decode<D: Decoder>(d: &mut D) -> Result<String, D::Error> {
+impl<D: Decoder> Decodable<D> for String {
+    fn decode(d: &mut D) -> Result<String, D::Error> {
         Ok(d.read_str()?.into_owned())
     }
 }
 
-impl Encodable for f32 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_f32(*self)
-    }
-}
-
-impl Decodable for f32 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<f32, D::Error> {
-        d.read_f32()
-    }
-}
-
-impl Encodable for f64 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_f64(*self)
-    }
-}
-
-impl Decodable for f64 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<f64, D::Error> {
-        d.read_f64()
-    }
-}
-
-impl Encodable for bool {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_bool(*self)
-    }
-}
-
-impl Decodable for bool {
-    fn decode<D: Decoder>(d: &mut D) -> Result<bool, D::Error> {
-        d.read_bool()
-    }
-}
-
-impl Encodable for char {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_char(*self)
-    }
-}
-
-impl Decodable for char {
-    fn decode<D: Decoder>(d: &mut D) -> Result<char, D::Error> {
-        d.read_char()
-    }
-}
-
-impl Encodable for () {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for () {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_unit()
     }
 }
 
-impl Decodable for () {
-    fn decode<D: Decoder>(d: &mut D) -> Result<(), D::Error> {
+impl<D: Decoder> Decodable<D> for () {
+    fn decode(d: &mut D) -> Result<(), D::Error> {
         d.read_nil()
     }
 }
 
-impl<T> Encodable for PhantomData<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T> Encodable<S> for PhantomData<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_unit()
     }
 }
 
-impl<T> Decodable for PhantomData<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<PhantomData<T>, D::Error> {
+impl<D: Decoder, T> Decodable<D> for PhantomData<T> {
+    fn decode(d: &mut D) -> Result<PhantomData<T>, D::Error> {
         d.read_nil()?;
         Ok(PhantomData)
     }
 }
 
-impl<T: Decodable> Decodable for Box<[T]> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<[T]> {
+    fn decode(d: &mut D) -> Result<Box<[T]>, D::Error> {
         let v: Vec<T> = Decodable::decode(d)?;
         Ok(v.into_boxed_slice())
     }
 }
 
-impl<T: Encodable> Encodable for Rc<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<T: Decodable> Decodable for Rc<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Rc<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
+    fn decode(d: &mut D) -> Result<Rc<T>, D::Error> {
         Ok(Rc::new(Decodable::decode(d)?))
     }
 }
 
-impl<T: Encodable> Encodable for [T] {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -665,8 +537,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for Vec<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -676,8 +548,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for Vec<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Vec<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
+    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 {
@@ -688,8 +560,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Vec<T>, D::Error> {
     }
 }
 
-impl Encodable for [u8; 20] {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for [u8; 20] {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -699,8 +571,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl Decodable for [u8; 20] {
-    fn decode<D: Decoder>(d: &mut D) -> Result<[u8; 20], D::Error> {
+impl<D: Decoder> Decodable<D> for [u8; 20] {
+    fn decode(d: &mut D) -> Result<[u8; 20], D::Error> {
         d.read_seq(|d, len| {
             assert!(len == 20);
             let mut v = [0u8; 20];
@@ -712,11 +584,11 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<'a, T: Encodable> Encodable for Cow<'a, [T]>
+impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]>
 where
     [T]: ToOwned<Owned = Vec<T>>,
 {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -726,11 +598,11 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Decodable + ToOwned> Decodable for Cow<'static, [T]>
+impl<D: Decoder, T: Decodable<D> + ToOwned> Decodable<D> for Cow<'static, [T]>
 where
     [T]: ToOwned<Owned = Vec<T>>,
 {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
+    fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
             for i in 0..len {
@@ -741,8 +613,8 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
     }
 }
 
-impl<T: Encodable> Encodable for Option<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_option(|s| match *self {
             None => s.emit_option_none(),
             Some(ref v) => s.emit_option_some(|s| v.encode(s)),
@@ -750,14 +622,14 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T: Decodable> Decodable for Option<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Option<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
+    fn decode(d: &mut D) -> Result<Option<T>, D::Error> {
         d.read_option(|d, b| if b { Ok(Some(Decodable::decode(d)?)) } else { Ok(None) })
     }
 }
 
-impl<T1: Encodable, T2: Encodable> Encodable for Result<T1, T2> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::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 {
             Ok(ref v) => {
                 s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
@@ -769,8 +641,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl<T1: Decodable, T2: Decodable> Decodable for Result<T1, T2> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Result<T1, T2>, D::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_variant(&["Ok", "Err"], |d, disr| match disr {
                 0 => Ok(Ok(d.read_enum_variant_arg(0, |d| T1::decode(d))?)),
@@ -806,9 +678,9 @@ macro_rules! count {
 macro_rules! tuple {
     () => ();
     ( $($name:ident,)+ ) => (
-        impl<$($name:Decodable),+> Decodable for ($($name,)+) {
+        impl<D: Decoder, $($name: Decodable<D>),+> Decodable<D> for ($($name,)+) {
             #[allow(non_snake_case)]
-            fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)+), D::Error> {
+            fn decode(d: &mut D) -> Result<($($name,)+), D::Error> {
                 let len: usize = count!($($name)+);
                 d.read_tuple(len, |d| {
                     let mut i = 0;
@@ -819,9 +691,9 @@ fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)+), D::Error> {
                 })
             }
         }
-        impl<$($name:Encodable),+> Encodable for ($($name,)+) {
+        impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) {
             #[allow(non_snake_case)]
-            fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+            fn encode(&self, s: &mut S) -> Result<(), S::Error> {
                 let ($(ref $name,)+) = *self;
                 let mut n = 0;
                 $(let $name = $name; n += 1;)+
@@ -838,33 +710,33 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-impl Encodable for path::Path {
-    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for path::Path {
+    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
         self.to_str().unwrap().encode(e)
     }
 }
 
-impl Encodable for path::PathBuf {
-    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for path::PathBuf {
+    fn encode(&self, e: &mut S) -> Result<(), S::Error> {
         path::Path::encode(self, e)
     }
 }
 
-impl Decodable for path::PathBuf {
-    fn decode<D: Decoder>(d: &mut D) -> Result<path::PathBuf, D::Error> {
+impl<D: Decoder> Decodable<D> for path::PathBuf {
+    fn decode(d: &mut D) -> Result<path::PathBuf, D::Error> {
         let bytes: String = Decodable::decode(d)?;
         Ok(path::PathBuf::from(bytes))
     }
 }
 
-impl<T: Encodable + Copy> Encodable for Cell<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         self.get().encode(s)
     }
 }
 
-impl<T: Decodable + Copy> Decodable for Cell<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Cell<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
+    fn decode(d: &mut D) -> Result<Cell<T>, D::Error> {
         Ok(Cell::new(Decodable::decode(d)?))
     }
 }
@@ -874,136 +746,37 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Cell<T>, D::Error> {
 // `encoder.error("attempting to Encode borrowed RefCell")`
 // from `encode` when `try_borrow` returns `None`.
 
-impl<T: Encodable> Encodable for RefCell<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         self.borrow().encode(s)
     }
 }
 
-impl<T: Decodable> Decodable for RefCell<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<RefCell<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for RefCell<T> {
+    fn decode(d: &mut D) -> Result<RefCell<T>, D::Error> {
         Ok(RefCell::new(Decodable::decode(d)?))
     }
 }
 
-impl<T: Encodable> Encodable for Arc<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
 
-impl<T: Decodable> Decodable for Arc<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Arc<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<T> {
+    fn decode(d: &mut D) -> Result<Arc<T>, D::Error> {
         Ok(Arc::new(Decodable::decode(d)?))
     }
 }
 
-// ___________________________________________________________________________
-// Specialization-based interface for multi-dispatch Encodable/Decodable.
-
-/// Implement this trait on your `{Encodable,Decodable}::Error` types
-/// to override the default panic behavior for missing specializations.
-pub trait SpecializationError {
-    /// Creates an error for a missing method specialization.
-    /// Defaults to panicking with type, trait & method names.
-    /// `S` is the encoder/decoder state type,
-    /// `T` is the type being encoded/decoded, and
-    /// the arguments are the names of the trait
-    /// and method that should've been overridden.
-    fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> Self;
-}
-
-impl<E> SpecializationError for E {
-    default fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> E {
-        panic!(
-            "missing specialization: `<{} as {}<{}>>::{}` not overridden",
-            any::type_name::<S>(),
-            trait_name,
-            any::type_name::<T>(),
-            method_name
-        );
-    }
-}
-
-/// Implement this trait on encoders, with `T` being the type
-/// you want to encode (employing `UseSpecializedEncodable`),
-/// using a strategy specific to the encoder.
-pub trait SpecializedEncoder<T: ?Sized + UseSpecializedEncodable>: Encoder {
-    /// Encode the value in a manner specific to this encoder state.
-    fn specialized_encode(&mut self, value: &T) -> Result<(), Self::Error>;
-}
-
-impl<E: Encoder, T: ?Sized + UseSpecializedEncodable> SpecializedEncoder<T> for E {
-    default fn specialized_encode(&mut self, value: &T) -> Result<(), E::Error> {
-        value.default_encode(self)
-    }
-}
-
-/// Implement this trait on decoders, with `T` being the type
-/// you want to decode (employing `UseSpecializedDecodable`),
-/// using a strategy specific to the decoder.
-pub trait SpecializedDecoder<T: UseSpecializedDecodable>: Decoder {
-    /// Decode a value in a manner specific to this decoder state.
-    fn specialized_decode(&mut self) -> Result<T, Self::Error>;
-}
-
-impl<D: Decoder, T: UseSpecializedDecodable> SpecializedDecoder<T> for D {
-    default fn specialized_decode(&mut self) -> Result<T, D::Error> {
-        T::default_decode(self)
-    }
-}
-
-/// Implement this trait on your type to get an `Encodable`
-/// implementation which goes through `SpecializedEncoder`.
-pub trait UseSpecializedEncodable {
-    /// Defaults to returning an error (see `SpecializationError`).
-    fn default_encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
-        Err(E::Error::not_found::<E, Self>("SpecializedEncoder", "specialized_encode"))
-    }
-}
-
-impl<T: ?Sized + UseSpecializedEncodable> Encodable for T {
-    default fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
-        E::specialized_encode(e, self)
-    }
-}
-
-/// Implement this trait on your type to get an `Decodable`
-/// implementation which goes through `SpecializedDecoder`.
-pub trait UseSpecializedDecodable: Sized {
-    /// Defaults to returning an error (see `SpecializationError`).
-    fn default_decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
-        Err(D::Error::not_found::<D, Self>("SpecializedDecoder", "specialized_decode"))
-    }
-}
-
-impl<T: UseSpecializedDecodable> Decodable for T {
-    default fn decode<D: Decoder>(d: &mut D) -> Result<T, D::Error> {
-        D::specialized_decode(d)
-    }
-}
-
-// Can't avoid specialization for &T and Box<T> impls,
-// as proxy impls on them are blankets that conflict
-// with the Encodable and Decodable impls above,
-// which only have `default` on their methods
-// for this exact reason.
-// May be fixable in a simpler fashion via the
-// more complex lattice model for specialization.
-impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         (**self).encode(s)
     }
 }
-impl<T: Decodable> UseSpecializedDecodable for Box<T> {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> {
+    fn decode(d: &mut D) -> Result<Box<T>, D::Error> {
         Ok(box Decodable::decode(d)?)
     }
 }
-impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
-impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}
index 59c481edbca3a662bce3a8202347debe042d8b67..e3a823127d93ea60621623ec8cb51e593ed4b192 100644 (file)
@@ -9,6 +9,7 @@
     from_str, DecodeResult, Decoder, DecoderError, Encoder, EncoderError, Json, JsonEvent, Parser,
     StackElement,
 };
+use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::json;
 use rustc_serialize::{Decodable, Encodable};
 
@@ -17,7 +18,7 @@
 use std::string;
 use Animal::*;
 
-#[derive(RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Decodable, Eq, PartialEq, Debug)]
 struct OptionData {
     opt: Option<usize>,
 }
@@ -48,20 +49,20 @@ fn test_decode_option_malformed() {
     );
 }
 
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
 enum Animal {
     Dog,
     Frog(string::String, isize),
 }
 
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
 struct Inner {
     a: (),
     b: usize,
     c: Vec<string::String>,
 }
 
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
 struct Outer {
     inner: Vec<Inner>,
 }
@@ -568,7 +569,7 @@ fn test_decode_struct() {
     );
 }
 
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
 struct FloatStruct {
     f: f64,
     a: Vec<f64>,
@@ -616,7 +617,7 @@ fn test_multiline_errors() {
     assert_eq!(from_str("{\n  \"foo\":\n \"bar\""), Err(SyntaxError(EOFWhileParsingObject, 3, 8)));
 }
 
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
 #[allow(dead_code)]
 struct DecodeStruct {
     x: f64,
@@ -624,12 +625,12 @@ struct DecodeStruct {
     z: string::String,
     w: Vec<DecodeStruct>,
 }
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
 enum DecodeEnum {
     A(f64),
     B(string::String),
 }
-fn check_err<T: Decodable>(to_parse: &'static str, expected: DecoderError) {
+fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected: DecoderError) {
     let res: DecodeResult<T> = match from_str(to_parse) {
         Err(e) => Err(ParseError(e)),
         Ok(json) => Decodable::decode(&mut Decoder::new(json)),
@@ -933,7 +934,7 @@ fn indents(source: &str) -> usize {
 #[test]
 fn test_hashmap_with_enum_key() {
     use std::collections::HashMap;
-    #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)]
+    #[derive(Encodable, Eq, Hash, PartialEq, Decodable, Debug)]
     enum Enum {
         Foo,
         #[allow(dead_code)]
@@ -1254,7 +1255,7 @@ fn test_to_json() {
 #[test]
 fn test_encode_hashmap_with_arbitrary_key() {
     use std::collections::HashMap;
-    #[derive(PartialEq, Eq, Hash, RustcEncodable)]
+    #[derive(PartialEq, Eq, Hash, Encodable)]
     struct ArbitraryType(usize);
     let mut hm: HashMap<ArbitraryType, bool> = HashMap::new();
     hm.insert(ArbitraryType(1), true);
index c827391700709dd62cb9c3f8b6a0fd6641c98c51..13b3676a56cd51b40cd0621633a440e886e84b45 100644 (file)
@@ -1,10 +1,11 @@
 #![allow(rustc::internal)]
 
+use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::opaque::{Decoder, Encoder};
 use rustc_serialize::{Decodable, Encodable};
 use std::fmt::Debug;
 
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 struct Struct {
     a: (),
     b: u8,
@@ -27,11 +28,13 @@ struct Struct {
     q: Option<u32>,
 }
 
-fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) {
+fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + PartialEq + Debug>(
+    values: Vec<T>,
+) {
     let mut encoder = Encoder::new(Vec::new());
 
     for value in &values {
-        Encodable::encode(&value, &mut encoder).unwrap();
+        Encodable::encode(value, &mut encoder).unwrap();
     }
 
     let data = encoder.into_inner();
@@ -225,7 +228,7 @@ fn test_struct() {
     }]);
 }
 
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 enum Enum {
     Variant1,
     Variant2(usize, f32),
index 35c227df8500a98832284eae2e53009f0b704ab9..208bba1d962282d8cd5761fb2f9123dbf1d4b612 100644 (file)
@@ -11,7 +11,8 @@ path = "lib.rs"
 [dependencies]
 bitflags = "1.2.1"
 getopts = "0.2"
-log = { package = "tracing", version = "0.1" }
+rustc_macros = { path = "../librustc_macros" }
+tracing = "0.1"
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
index ace233611223ce9b5a052a07f43f0d5754dbfe48..0eec12aa03f2d72c4708b9d8800e3c01dfe41ed8 100644 (file)
@@ -2,10 +2,10 @@
 //! compilation. This is used for incremental compilation tests and debug
 //! output.
 
-use log::debug;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::{Span, Symbol};
 use std::sync::{Arc, Mutex};
+use tracing::debug;
 
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
 pub enum CguReuse {
index 9fcdd46539c46f15aee8c50306f9f58af128ea18..1808a0ca59bea7a62a96832e04950ee63a12a2e5 100644 (file)
@@ -39,7 +39,7 @@ pub struct Config {
 }
 
 bitflags! {
-    #[derive(Default, RustcEncodable, RustcDecodable)]
+    #[derive(Default, Encodable, Decodable)]
     pub struct SanitizerSet: u8 {
         const ADDRESS = 1 << 0;
         const LEAK    = 1 << 1;
@@ -194,7 +194,8 @@ pub fn enabled(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable)]
 pub enum SymbolManglingVersion {
     Legacy,
     V0,
@@ -209,7 +210,8 @@ pub enum DebugInfo {
     Full,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Encodable, Decodable)]
 pub enum OutputType {
     Bitcode,
     Assembly,
@@ -672,7 +674,7 @@ pub enum EntryFnType {
 
 impl_stable_hash_via_hash!(EntryFnType);
 
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
 pub enum CrateType {
     Executable,
     Dylib,
@@ -1876,7 +1878,7 @@ fn parse_pretty_inner(efmt: ErrorOutputType, name: &str, extended: bool) -> PpMo
                 }
             }
         };
-        log::debug!("got unpretty option: {:?}", first);
+        tracing::debug!("got unpretty option: {:?}", first);
         first
     }
 }
index 8fe71b71caed1f92944ef66db883b4b2b6d9a30d..284fca652ece73b2b075d089cf76d924099f8150 100644 (file)
@@ -8,8 +8,8 @@
 use std::path::{Path, PathBuf};
 
 use crate::search_paths::{PathKind, SearchPath, SearchPathFile};
-use log::debug;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use tracing::debug;
 
 #[derive(Copy, Clone)]
 pub enum FileMatch {
index be9d2e7be27774ce5da48fb5ccf093ac74a58c18..c2ea141a06fe31b71f9419b9d6155646c3f8bc68 100644 (file)
@@ -3,6 +3,8 @@
 
 #[macro_use]
 extern crate bitflags;
+#[macro_use]
+extern crate rustc_macros;
 
 pub mod cgu_reuse_tracker;
 pub mod utils;
index 4ff06acaa1fd4eedcb7fc5799599a465673c04f6..e12364b7dac7cb355917994aa0855998076e3dec 100644 (file)
@@ -33,7 +33,7 @@ fn new(path: PathBuf) -> SearchPathFile {
     }
 }
 
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)]
 pub enum PathKind {
     Native,
     Crate,
index 9191f7e8d76be85458c205e8c585432af937322b..f10f9b2ce93c5bb35fe74b1771bbae3204e235bf 100644 (file)
@@ -437,6 +437,7 @@ pub fn opt_span_warn<S: Into<MultiSpan>>(&self, opt_sp: Option<S>, msg: &str) {
         }
     }
     /// Delay a span_bug() call until abort_if_errors()
+    #[track_caller]
     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().delay_span_bug(sp, msg)
     }
@@ -1453,14 +1454,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         "aarch64-unknown-linux-gnu",
         "x86_64-apple-darwin",
         "x86_64-fuchsia",
+        "x86_64-unknown-freebsd",
         "x86_64-unknown-linux-gnu",
     ];
     const LSAN_SUPPORTED_TARGETS: &[&str] =
         &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
     const MSAN_SUPPORTED_TARGETS: &[&str] =
-        &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
-    const TSAN_SUPPORTED_TARGETS: &[&str] =
-        &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+        &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
+    const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-unknown-linux-gnu",
+        "x86_64-apple-darwin",
+        "x86_64-unknown-freebsd",
+        "x86_64-unknown-linux-gnu",
+    ];
 
     // Sanitizers can only be used on some tested platforms.
     for s in sess.opts.debugging_opts.sanitizer {
index b97308c22cb7d0343cdc23e0efa03c360f5968fb..15447c01d1e55a5080e31c53fc84aacf6a3e8baa 100644 (file)
@@ -10,7 +10,7 @@ pub fn time<R>(&self, what: &'static str, f: impl FnOnce() -> R) -> R {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 pub enum NativeLibKind {
     /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) included
     /// when linking a final binary, but not when archiving an rlib.
index 2db417ce0e12953ed44fb532cc71bde91fcc6507..dd4928d4e324b41547c264105b78ce53b2074683 100644 (file)
@@ -18,6 +18,6 @@ rustc_arena = { path = "../librustc_arena" }
 scoped-tls = "1.0"
 unicode-width = "0.1.4"
 cfg-if = "0.1.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 sha-1 = "0.8"
 md-5 = "0.8"
index a874f81868f153ab6f373101b30136841687b10e..aae778217d3f1116a2b1e02ec4f65d341b9bffe2 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
 use rustc_macros::HashStable_Generic;
-use rustc_serialize::{Decoder, Encoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::borrow::Borrow;
 use std::fmt;
 
@@ -84,13 +84,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 /// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
 /// Therefore, make sure to include the context when encode a `CrateNum`.
-impl rustc_serialize::UseSpecializedEncodable for CrateNum {
-    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
-        e.emit_u32(self.as_u32())
+impl<E: Encoder> Encodable<E> for CrateNum {
+    default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        s.emit_u32(self.as_u32())
     }
 }
-impl rustc_serialize::UseSpecializedDecodable for CrateNum {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
+
+impl<D: Decoder> Decodable<D> for CrateNum {
+    default fn decode(d: &mut D) -> Result<CrateNum, D::Error> {
         Ok(CrateNum::from_u32(d.read_u32()?))
     }
 }
@@ -104,8 +105,8 @@ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
     }
 }
 
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub struct DefPathHash(pub Fingerprint);
 
 impl Borrow<Fingerprint> for DefPathHash {
@@ -120,16 +121,26 @@ fn borrow(&self) -> &Fingerprint {
     /// particular definition. It should really be considered an interned
     /// shorthand for a particular DefPath.
     pub struct DefIndex {
-        DEBUG_FORMAT = "DefIndex({})",
+        ENCODABLE = custom // (only encodable in metadata)
 
+        DEBUG_FORMAT = "DefIndex({})",
         /// The crate root is always assigned index 0 by the AST Map code,
         /// thanks to `NodeCollector::new`.
         const CRATE_DEF_INDEX = 0,
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
-impl rustc_serialize::UseSpecializedDecodable for DefIndex {}
+impl<E: Encoder> Encodable<E> for DefIndex {
+    default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+        panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
+    }
+}
+
+impl<D: Decoder> Decodable<D> for DefIndex {
+    default fn decode(_: &mut D) -> Result<DefIndex, D::Error> {
+        panic!("cannot decode `DefIndex` with `{}`", std::any::type_name::<D>());
+    }
+}
 
 /// A `DefId` identifies a particular *definition*, by combining a crate
 /// index and a def index.
@@ -168,19 +179,24 @@ pub fn is_top_level_module(self) -> bool {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for DefId {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        let krate = u64::from(self.krate.as_u32());
-        let index = u64::from(self.index.as_u32());
-        s.emit_u64((krate << 32) | index)
+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_field("index", 1, |s| self.index.encode(s))
+        })
     }
 }
-impl rustc_serialize::UseSpecializedDecodable for DefId {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
-        let def_id = d.read_u64()?;
-        let krate = CrateNum::from_u32((def_id >> 32) as u32);
-        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
-        Ok(DefId { krate, index })
+
+impl<D: Decoder> Decodable<D> for DefId {
+    default fn decode(d: &mut D) -> Result<DefId, D::Error> {
+        d.read_struct("DefId", 2, |d| {
+            Ok(DefId {
+                krate: d.read_struct_field("krate", 0, Decodable::decode)?,
+                index: d.read_struct_field("index", 1, Decodable::decode)?,
+            })
+        })
     }
 }
 
@@ -239,8 +255,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for LocalDefId {}
-impl rustc_serialize::UseSpecializedDecodable for LocalDefId {}
+impl<E: Encoder> Encodable<E> for LocalDefId {
+    fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+        self.to_def_id().encode(s)
+    }
+}
+
+impl<D: Decoder> Decodable<D> for LocalDefId {
+    fn decode(d: &mut D) -> Result<LocalDefId, D::Error> {
+        DefId::decode(d).map(|d| d.expect_local())
+    }
+}
 
 impl<CTX: HashStableContext> HashStable<CTX> for DefId {
     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
index b1ac7f04321eb99dd0146c8e24c2b699c9268f1f..4d0c92f51d7ca7063c934486a78c7947e2b4b511 100644 (file)
@@ -5,7 +5,7 @@
 use rustc_macros::HashStable_Generic;
 
 /// The edition of the compiler (RFC 2052)
-#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)]
+#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
 #[derive(HashStable_Generic)]
 pub enum Edition {
     // editions must be kept in order, oldest to newest
index f52b2195c2f6e25d6bc797e24511808c43a08374..942c6648340ef9226a8a30b394836396eafc8ceb 100644 (file)
 use crate::{Span, DUMMY_SP};
 
 use crate::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use log::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_macros::HashStable_Generic;
-use rustc_serialize::{
-    Decodable, Decoder, Encodable, Encoder, UseSpecializedDecodable, UseSpecializedEncodable,
-};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use tracing::*;
 
 /// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct SyntaxContext(u32);
 
-#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
+#[derive(Debug, Encodable, Decodable, Clone)]
 pub struct SyntaxContextData {
     outer_expn: ExpnId,
     outer_transparency: Transparency,
@@ -62,7 +60,7 @@ pub struct SyntaxContextData {
 
 /// A property of a macro expansion that determines how identifiers
 /// produced by that expansion are resolved.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub enum Transparency {
     /// Identifier produced by a transparent expansion is always resolved at call-site.
@@ -664,7 +662,7 @@ pub fn fresh_expansion_with_transparency(
 
 /// A subset of properties from both macro definition and macro call available through global data.
 /// Avoid using this if you have access to the original definition or call structures.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
 pub struct ExpnData {
     // --- The part unique to each expansion.
     /// The kind of this expansion - macro or compiler desugaring.
@@ -766,7 +764,7 @@ pub fn is_root(&self) -> bool {
 }
 
 /// Expansion kind.
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum ExpnKind {
     /// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
     Root,
@@ -794,7 +792,7 @@ pub fn descr(&self) -> String {
 }
 
 /// The kind of macro invocation or definition.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub enum MacroKind {
     /// A bang macro `foo!()`.
@@ -830,7 +828,7 @@ pub fn article(self) -> &'static str {
 }
 
 /// The kind of AST transform.
-#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum AstPass {
     StdImports,
     TestHarness,
@@ -848,7 +846,7 @@ fn descr(self) -> &'static str {
 }
 
 /// The kind of compiler desugaring.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum DesugaringKind {
     /// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
     /// However, we do not want to blame `c` for unreachability but rather say that `i`
@@ -867,7 +865,7 @@ pub enum DesugaringKind {
 }
 
 /// A location in the desugaring of a `for` loop
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
 pub enum ForLoopLoc {
     Head,
     IntoIter,
@@ -888,9 +886,6 @@ fn descr(self) -> &'static str {
     }
 }
 
-impl UseSpecializedEncodable for ExpnId {}
-impl UseSpecializedDecodable for ExpnId {}
-
 #[derive(Default)]
 pub struct HygieneEncodeContext {
     /// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata.
@@ -1137,6 +1132,7 @@ pub fn for_all_expns_in<E, F: FnMut(u32, ExpnId, &ExpnData) -> Result<(), E>>(
     }
     Ok(())
 }
+
 pub fn for_all_data<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Result<(), E>>(
     mut f: F,
 ) -> Result<(), E> {
@@ -1147,6 +1143,18 @@ pub fn for_all_data<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Res
     Ok(())
 }
 
+impl<E: Encoder> Encodable<E> for ExpnId {
+    default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+        panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
+    }
+}
+
+impl<D: Decoder> Decodable<D> for ExpnId {
+    default fn decode(_: &mut D) -> Result<Self, D::Error> {
+        panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
+    }
+}
+
 pub fn for_all_expn_data<E, F: FnMut(u32, &ExpnData) -> Result<(), E>>(mut f: F) -> Result<(), E> {
     let all_data = HygieneData::with(|data| data.expn_data.clone());
     for (i, data) in all_data.into_iter().enumerate() {
@@ -1218,5 +1226,14 @@ pub fn incr_comp(ctxt: &'a HygieneDecodeContext) -> Self {
     }
 }
 
-impl UseSpecializedEncodable for SyntaxContext {}
-impl UseSpecializedDecodable for SyntaxContext {}
+impl<E: Encoder> Encodable<E> for SyntaxContext {
+    default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+        panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
+    }
+}
+
+impl<D: Decoder> Decodable<D> for SyntaxContext {
+    default fn decode(_: &mut D) -> Result<Self, D::Error> {
+        panic!("cannot decode `SyntaxContext` with `{}`", std::any::type_name::<D>());
+    }
+}
index 697d88ad0639598ea392fa345260a1eac0749ce0..c654dade2abd4ae60f9897e5eede270a153e9969 100644 (file)
@@ -15,8 +15,7 @@
 #![feature(option_expect_none)]
 #![feature(refcell_take)]
 
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
 extern crate rustc_macros;
 
 use rustc_data_structures::AtomicRef;
@@ -105,8 +104,8 @@ pub fn with_default_session_globals<R>(f: impl FnOnce() -> R) -> R {
 //
 // FIXME: We should use this enum or something like it to get rid of the
 // use of magic `/rust/1.x/...` paths across the board.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
+#[derive(HashStable_Generic, Decodable, Encodable)]
 pub enum RealFileName {
     Named(PathBuf),
     /// For de-virtualized paths (namely paths into libstd that have been mapped
@@ -152,8 +151,8 @@ pub fn stable_name(&self) -> &Path {
 }
 
 /// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
+#[derive(HashStable_Generic, Decodable, Encodable)]
 pub enum FileName {
     Real(RealFileName),
     /// Call to `quote!`.
@@ -333,7 +332,7 @@ fn cmp(&self, rhs: &Self) -> Ordering {
 ///   the error, and would be rendered with `^^^`.
 /// - They can have a *label*. In this case, the label is written next
 ///   to the mark in the snippet when we render.
-#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)]
 pub struct MultiSpan {
     primary_spans: Vec<Span>,
     span_labels: Vec<(Span, String)>,
@@ -698,23 +697,22 @@ fn default() -> Self {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for Span {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+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))
         })
     }
 }
-
-impl rustc_serialize::UseSpecializedDecodable for Span {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
-        d.read_struct("Span", 2, |d| {
+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)?;
-            Ok(Span::with_root_ctxt(lo, hi))
+
+            Ok(Span::new(lo, hi, SyntaxContext::root()))
         })
     }
 }
@@ -889,7 +887,7 @@ fn from(spans: Vec<Span>) -> MultiSpan {
 }
 
 /// Identifies an offset of a multi-byte character in a `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
 pub struct MultiByteChar {
     /// The absolute offset of the character in the `SourceMap`.
     pub pos: BytePos,
@@ -898,7 +896,7 @@ pub struct MultiByteChar {
 }
 
 /// Identifies an offset of a non-narrow character in a `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
 pub enum NonNarrowChar {
     /// Represents a zero-width character.
     ZeroWidth(BytePos),
@@ -960,7 +958,7 @@ fn sub(self, rhs: BytePos) -> Self {
 }
 
 /// Identifies an offset of a character that was normalized away from `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
 pub struct NormalizedPos {
     /// The absolute offset of the character in the `SourceMap`.
     pub pos: BytePos,
@@ -1012,7 +1010,7 @@ pub fn get_source(&self) -> Option<&Lrc<String>> {
 #[derive(Debug)]
 pub struct OffsetOverflowError;
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 pub enum SourceFileHashAlgorithm {
     Md5,
     Sha1,
@@ -1033,8 +1031,8 @@ fn from_str(s: &str) -> Result<SourceFileHashAlgorithm, ()> {
 rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm);
 
 /// The hash of the on-disk source file used for debug info.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub struct SourceFileHash {
     pub kind: SourceFileHashAlgorithm,
     value: [u8; 20],
@@ -1113,8 +1111,8 @@ pub struct SourceFile {
     pub cnum: CrateNum,
 }
 
-impl Encodable for SourceFile {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+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("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
@@ -1183,8 +1181,8 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
     }
 }
 
-impl Decodable for SourceFile {
-    fn decode<D: Decoder>(d: &mut D) -> Result<SourceFile, D::Error> {
+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))?;
             let name_was_remapped: bool =
@@ -1585,14 +1583,14 @@ fn sub(self, rhs: BytePos) -> BytePos {
     }
 }
 
-impl Encodable for BytePos {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u32(self.0)
     }
 }
 
-impl Decodable for BytePos {
-    fn decode<D: Decoder>(d: &mut D) -> Result<BytePos, D::Error> {
+impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos {
+    fn decode(d: &mut D) -> Result<BytePos, D::Error> {
         Ok(BytePos(d.read_u32()?))
     }
 }
index e062c7766e7dcc2774b49c424e8251d6ff0c6ab8..7c656db22ed8c18b6846cf8a5e18459cd49ac68e 100644 (file)
@@ -19,9 +19,9 @@
 use std::path::{Path, PathBuf};
 use std::sync::atomic::Ordering;
 
-use log::debug;
 use std::fs;
 use std::io;
+use tracing::debug;
 
 #[cfg(test)]
 mod tests;
@@ -75,7 +75,7 @@ fn deref(&self) -> &Self::Target {
     impl<T> !DerefMut for MonotonicVec<T> {}
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
 pub struct Spanned<T> {
     pub node: T,
     pub span: Span,
@@ -118,7 +118,7 @@ fn read_file(&self, path: &Path) -> io::Result<String> {
 // This is a `SourceFile` identifier that is used to correlate `SourceFile`s between
 // subsequent compilation sessions (which is something we need to do during
 // incremental compilation).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
 pub struct StableSourceFileId(u128);
 
 // FIXME: we need a more globally consistent approach to the problem solved by
index caa6de09664bcf1a38607114bcd31d980c3b89ae..7843c04f25596e2f70d8cca544b9c918bf9a415d 100644 (file)
@@ -5,9 +5,8 @@
 use rustc_arena::DroplessArena;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_macros::{symbols, HashStable_Generic};
+use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
 
 use std::cmp::{Ord, PartialEq, PartialOrd};
 use std::fmt;
     }
 }
 
-#[derive(Copy, Clone, Eq, HashStable_Generic)]
+#[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
 pub struct Ident {
     pub name: Symbol,
     pub span: Span,
@@ -1289,26 +1288,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl UseSpecializedEncodable for Ident {
-    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("Ident", 2, |s| {
-            s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
-            s.emit_struct_field("span", 1, |s| self.span.encode(s))
-        })
-    }
-}
-
-impl UseSpecializedDecodable for Ident {
-    fn default_decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
-        d.read_struct("Ident", 2, |d| {
-            Ok(Ident {
-                name: d.read_struct_field("name", 0, Decodable::decode)?,
-                span: d.read_struct_field("span", 1, Decodable::decode)?,
-            })
-        })
-    }
-}
-
 /// This is the most general way to print identifiers.
 /// AST pretty-printer is used as a fallback for turning AST structures into token streams for
 /// proc macros. Additionally, proc macros may stringify their input and expect it survive the
@@ -1452,15 +1431,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl Encodable for Symbol {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for Symbol {
+    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         self.with(|string| s.emit_str(string))
     }
 }
 
-impl Decodable for Symbol {
+impl<D: Decoder> Decodable<D> for Symbol {
     #[inline]
-    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
+    fn decode(d: &mut D) -> Result<Symbol, D::Error> {
         Ok(Symbol::intern(&d.read_str()?))
     }
 }
@@ -1549,7 +1528,7 @@ pub mod sym {
     use super::Symbol;
     use std::convert::TryInto;
 
-    symbols!();
+    define_symbols!();
 
     // Used from a macro in `librustc_feature/accepted.rs`
     pub use super::kw::MacroRules as macro_rules;
index 757d86bd95afdbdf3b5b0c3c7803c1aca91c14d8..b44c0e4e027ce92c9191bb6e7030224064c0a166 100644 (file)
@@ -10,7 +10,7 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 punycode = "0.4.0"
 rustc-demangle = "0.1.16"
 
index 90c89ea6b0a86243b8be7e564c50abb1a5c139a8..2ae13b501e9412d532d9f095917c7e4d805521d9 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::util::common::record_time;
 
-use log::debug;
+use tracing::debug;
 
 use std::fmt::{self, Write};
 use std::mem::{self, discriminant};
index 2579cf53d3d509bb71e062ef7115c9e154fe90d0..296b40c4e395da37ebb507ea61ae7668b2c8bcba 100644 (file)
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
 
-use log::debug;
+use tracing::debug;
 
 mod legacy;
 mod v0;
@@ -173,7 +173,7 @@ fn compute_symbol_name(
             let disambiguator = tcx.sess.local_crate_disambiguator();
             return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
-        let hir_id = tcx.hir().as_local_hir_id(def_id);
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         match tcx.hir().get(hir_id) {
             Node::ForeignItem(_) => true,
             _ => false,
index 21796e8498568436fa5bab7129cfdfd547c8f146..d2b50f44e43d9170f7dd097fc96b683db70b71b6 100644 (file)
@@ -10,7 +10,7 @@ path = "lib.rs"
 
 [dependencies]
 bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_macros = { path = "../librustc_macros" }
 rustc_serialize = { path = "../librustc_serialize" }
index b3e5f5c0c74b163e90d55d521ac17a93e1050059..4b565dd246f6da06feea1d999f18fe13ba63f533 100644 (file)
@@ -235,7 +235,7 @@ pub enum Endian {
 }
 
 /// Size of a type in bytes.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Size {
     raw: u64,
@@ -358,7 +358,7 @@ fn add_assign(&mut self, other: Size) {
 }
 
 /// Alignment of a type in bytes (always a power of two).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Align {
     pow2: u8,
@@ -415,7 +415,7 @@ pub fn restrict_for_offset(self, offset: Size) -> Align {
 }
 
 /// A pair of alignments, ABI-mandated and preferred.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct AbiAndPrefAlign {
     pub abi: Align,
index ccec17817d37df6b0de2920cbe2a7d95fb862fef..c22644bf813a4a0e0ddb6bf6e2b623e1b104e4b3 100644 (file)
@@ -13,7 +13,7 @@ macro_rules! def_reg_class {
             $class:ident,
         )*
     }) => {
-        #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
+        #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
         #[allow(non_camel_case_types)]
         pub enum $arch_regclass {
             $($class,)*
@@ -62,7 +62,7 @@ macro_rules! def_regs {
         )*
     }) => {
         #[allow(unreachable_code)]
-        #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
+        #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
         #[allow(non_camel_case_types)]
         pub enum $arch_reg {
             $($reg,)*
@@ -163,7 +163,7 @@ macro_rules! types {
 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
 
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
 pub enum InlineAsmArch {
     X86,
     X86_64,
@@ -193,17 +193,7 @@ fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
     }
 }
 
-#[derive(
-    Copy,
-    Clone,
-    RustcEncodable,
-    RustcDecodable,
-    Debug,
-    Eq,
-    PartialEq,
-    Hash,
-    HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
 pub enum InlineAsmReg {
     X86(X86InlineAsmReg),
     Arm(ArmInlineAsmReg),
@@ -293,17 +283,7 @@ pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
     }
 }
 
-#[derive(
-    Copy,
-    Clone,
-    RustcEncodable,
-    RustcDecodable,
-    Debug,
-    Eq,
-    PartialEq,
-    Hash,
-    HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
 pub enum InlineAsmRegClass {
     X86(X86InlineAsmRegClass),
     Arm(ArmInlineAsmRegClass),
@@ -429,17 +409,7 @@ pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
     }
 }
 
-#[derive(
-    Copy,
-    Clone,
-    RustcEncodable,
-    RustcDecodable,
-    Debug,
-    Eq,
-    PartialEq,
-    Hash,
-    HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
 pub enum InlineAsmRegOrRegClass {
     Reg(InlineAsmReg),
     RegClass(InlineAsmRegClass),
index 1d0dc660ee616ec37d5178ebad623d64958c1a7c..5788e1e838598629e7cff3baa489f8ae5ceeb27b 100644 (file)
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
 extern crate rustc_macros;
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 
 pub mod abi;
 pub mod asm;
index a5c874bb4ac050a2c305b4f9b95cd3137d6a0079..1e45739ca22b4a76f61c33be87661d35d4f19f5e 100644 (file)
@@ -5,8 +5,8 @@
 #[cfg(test)]
 mod tests;
 
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
 pub enum Abi {
     // N.B., this ordering MUST match the AbiDatas array below.
     // (This is ensured by the test indices_are_correct().)
index d12afe5a40bcc8882bb09cae3db63a8a684da149..33c9008bb14059361ca6a7571707042e41c8f896 100644 (file)
@@ -1,8 +1,10 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_gnu_base::opts();
     base.cpu = "pentium4".to_string();
+    base.pre_link_args
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
     base.max_atomic_width = Some(64);
     base.eliminate_frame_pointer = false; // Required for backtraces
     base.linker = Some("i686-w64-mingw32-gcc".to_string());
index 4e582fb8c63ab61af0885a4d5ee9943a4d4dbb9b..1c6d2e061bc036a5486e37b3ce6f92d9770157c2 100644 (file)
@@ -1,8 +1,10 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_uwp_gnu_base::opts();
     base.cpu = "pentium4".to_string();
+    base.pre_link_args
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
     base.max_atomic_width = Some(64);
     base.eliminate_frame_pointer = false; // Required for backtraces
 
index 961a438fd233cc175c5019a5d984ab5a0eb2de58..fa29ff3f8d80f6df5fd1d97ca1602ff97e37a62d 100644 (file)
@@ -161,7 +161,7 @@ pub fn desc(&self) -> &str {
     ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
 pub enum PanicStrategy {
     Unwind,
     Abort,
@@ -185,7 +185,7 @@ fn to_json(&self) -> Json {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub enum RelroLevel {
     Full,
     Partial,
@@ -229,7 +229,7 @@ fn to_json(&self) -> Json {
     }
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub enum MergeFunctions {
     Disabled,
     Trampolines,
@@ -1734,7 +1734,7 @@ macro_rules! target_option_val {
 }
 
 /// Either a target triple string or a path to a JSON file.
-#[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable)]
 pub enum TargetTriple {
     TargetTriple(String),
     TargetPath(PathBuf),
index 69236e98e58d7890befe267b1076a2cfd6268f23..a864918655fb80c026bfd4fcbc432df2b6b5a51b 100644 (file)
@@ -1,5 +1,5 @@
 use crate::spec::crt_objects::{self, CrtObjectsFallback};
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut pre_link_args = LinkArgs::new();
@@ -19,51 +19,48 @@ pub fn opts() -> TargetOptions {
     let mut late_link_args_static = LinkArgs::new();
     // Order of `late_link_args*` was found through trial and error to work with various
     // mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
-    late_link_args.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            "-lmsvcrt".to_string(),
-            "-lmingwex".to_string(),
-            "-lmingw32".to_string(),
-            // mingw's msvcrt is a weird hybrid import library and static library.
-            // And it seems that the linker fails to use import symbols from msvcrt
-            // that are required from functions in msvcrt in certain cases. For example
-            // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
-            // The library is purposely listed twice to fix that.
-            //
-            // See https://github.com/rust-lang/rust/pull/47483 for some more details.
-            "-lmsvcrt".to_string(),
-            "-luser32".to_string(),
-            "-lkernel32".to_string(),
-        ],
-    );
-    late_link_args_dynamic.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            // If any of our crates are dynamically linked then we need to use
-            // the shared libgcc_s-dw2-1.dll. This is required to support
-            // unwinding across DLL boundaries.
-            "-lgcc_s".to_string(),
-            "-lgcc".to_string(),
-            "-lkernel32".to_string(),
-        ],
-    );
-    late_link_args_static.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            // If all of our crates are statically linked then we can get away
-            // with statically linking the libgcc unwinding code. This allows
-            // binaries to be redistributed without the libgcc_s-dw2-1.dll
-            // dependency, but unfortunately break unwinding across DLL
-            // boundaries when unwinding across FFI boundaries.
-            "-lgcc_eh".to_string(),
-            "-l:libpthread.a".to_string(),
-            "-lgcc".to_string(),
-            // libpthread depends on libmsvcrt, so we need to link it *again*.
-            "-lmsvcrt".to_string(),
-            "-lkernel32".to_string(),
-        ],
-    );
+    let mingw_libs = vec![
+        "-lmsvcrt".to_string(),
+        "-lmingwex".to_string(),
+        "-lmingw32".to_string(),
+        // mingw's msvcrt is a weird hybrid import library and static library.
+        // And it seems that the linker fails to use import symbols from msvcrt
+        // that are required from functions in msvcrt in certain cases. For example
+        // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
+        // The library is purposely listed twice to fix that.
+        //
+        // See https://github.com/rust-lang/rust/pull/47483 for some more details.
+        "-lmsvcrt".to_string(),
+        "-luser32".to_string(),
+        "-lkernel32".to_string(),
+    ];
+    late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
+    late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
+    let dynamic_unwind_libs = vec![
+        // If any of our crates are dynamically linked then we need to use
+        // the shared libgcc_s-dw2-1.dll. This is required to support
+        // unwinding across DLL boundaries.
+        "-lgcc_s".to_string(),
+        "-lgcc".to_string(),
+        "-lkernel32".to_string(),
+    ];
+    late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
+    late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
+    let static_unwind_libs = vec![
+        // If all of our crates are statically linked then we can get away
+        // with statically linking the libgcc unwinding code. This allows
+        // binaries to be redistributed without the libgcc_s-dw2-1.dll
+        // dependency, but unfortunately break unwinding across DLL
+        // boundaries when unwinding across FFI boundaries.
+        "-lgcc_eh".to_string(),
+        "-l:libpthread.a".to_string(),
+        "-lgcc".to_string(),
+        // libpthread depends on libmsvcrt, so we need to link it *again*.
+        "-lmsvcrt".to_string(),
+        "-lkernel32".to_string(),
+    ];
+    late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
+    late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
 
     TargetOptions {
         // FIXME(#13846) this should be enabled for windows
index e12a37144da5edf3a830980795a61036b2bb143c..fd55a0fc6a15e8ecf6bbb8cb5fa79bb7102e98cc 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let base = super::windows_gnu_base::opts();
@@ -8,22 +8,21 @@ pub fn opts() -> TargetOptions {
     let mut late_link_args = LinkArgs::new();
     let late_link_args_dynamic = LinkArgs::new();
     let late_link_args_static = LinkArgs::new();
-    late_link_args.insert(
-        LinkerFlavor::Gcc,
-        vec![
-            //"-lwinstorecompat".to_string(),
-            //"-lmingwex".to_string(),
-            //"-lwinstorecompat".to_string(),
-            "-lwinstorecompat".to_string(),
-            "-lruntimeobject".to_string(),
-            "-lsynchronization".to_string(),
-            "-lvcruntime140_app".to_string(),
-            "-lucrt".to_string(),
-            "-lwindowsapp".to_string(),
-            "-lmingwex".to_string(),
-            "-lmingw32".to_string(),
-        ],
-    );
+    let mingw_libs = vec![
+        //"-lwinstorecompat".to_string(),
+        //"-lmingwex".to_string(),
+        //"-lwinstorecompat".to_string(),
+        "-lwinstorecompat".to_string(),
+        "-lruntimeobject".to_string(),
+        "-lsynchronization".to_string(),
+        "-lvcruntime140_app".to_string(),
+        "-lucrt".to_string(),
+        "-lwindowsapp".to_string(),
+        "-lmingwex".to_string(),
+        "-lmingw32".to_string(),
+    ];
+    late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
+    late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs.clone());
 
     TargetOptions {
         executables: false,
index eb97fa56814d85c7469439488f9ed7a472d27515..99af483f1d4152e5d7cc601acdc9289ffef3376d 100644 (file)
@@ -1,9 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_gnu_base::opts();
     base.cpu = "x86-64".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.pre_link_args
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
     base.max_atomic_width = Some(64);
     base.linker = Some("x86_64-w64-mingw32-gcc".to_string());
 
index ad6002f6b89e40fb4fe4526958871be4da67d334..3bd18f23f6f88a78edd0fd19667f4ec55d0a2a46 100644 (file)
@@ -1,9 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_uwp_gnu_base::opts();
     base.cpu = "x86-64".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+    base.pre_link_args
+        .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
     base.max_atomic_width = Some(64);
 
     Ok(Target {
index c43fe3f2c0c89db989228afd0516ab6ed882f105..444023baa695f532619f6f1f57043b70e5e7a2c6 100644 (file)
@@ -11,7 +11,7 @@ doctest = false
 
 [dependencies]
 rustc_parse_format = { path = "../librustc_parse_format" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_attr = { path = "../librustc_attr" }
 rustc_middle = { path = "../librustc_middle" }
 rustc_ast = { path = "../librustc_ast" }
index 4692fa04ed58718466a0e8d7cf8cc94eb36edacb..b5882df47294ee2a83542f9c423752f22a60a099 100644 (file)
@@ -24,7 +24,7 @@
 #[macro_use]
 extern crate rustc_data_structures;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
index b84ad93341e8186f773a51d7e94501d8da3cb7a5..379c976df69e3f63abe51435b538eb55e0e431eb 100644 (file)
@@ -1039,7 +1039,7 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T)
                     // }
                     // ```
                     if let Some(def_id) = def_id.as_local() {
-                        let opaque_hir_id = tcx.hir().as_local_hir_id(def_id);
+                        let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                         let parent_def_id = self.parent_def_id;
                         let def_scope_default = || {
                             let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
@@ -1205,7 +1205,7 @@ pub fn may_define_opaque_type(
     def_id: LocalDefId,
     opaque_hir_id: hir::HirId,
 ) -> bool {
-    let mut hir_id = tcx.hir().as_local_hir_id(def_id);
+    let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     // Named opaque types can be defined by any siblings or children of siblings.
     let scope = tcx.hir().get_defining_scope(opaque_hir_id);
index a75240042ad76cfc08a947c1c3dbd3d4d5becec0..0097097707f320e012cf0b8cea5ad09c659bc435 100644 (file)
@@ -41,7 +41,7 @@ fn environment<'tcx>(
 
     let clauses = predicates.into_iter().map(ChalkEnvironmentClause::Predicate);
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let node = tcx.hir().get(hir_id);
 
     enum NodeKind {
index 349fa68a4da9914a02488692301f6eb735eb75c3..e597843e6ce91105077e73c122b8be13c14b768a 100644 (file)
@@ -568,7 +568,8 @@ fn report_selection_error(
                             self.tcx.sess.source_map().guess_head_span(
                                 self.tcx.hir().span_if_local(closure_def_id).unwrap(),
                             );
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id.expect_local());
+                        let hir_id =
+                            self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
                         let mut err = struct_span_err!(
                             self.tcx.sess,
                             closure_span,
index e29e740f136697c58c7527ce184085e9ebd07f33..7513ff6b37ef82087eceef0c02c42075f0182cfa 100644 (file)
@@ -535,7 +535,7 @@ fn get_closure_name(
             };
 
         let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id.as_local()?);
+        let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?);
         let parent_node = hir.get_parent_node(hir_id);
         match hir.find(parent_node) {
             Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
@@ -1383,7 +1383,7 @@ fn maybe_note_obligation_cause_for_async_await(
 
         let generator_body = generator_did
             .as_local()
-            .map(|def_id| hir.as_local_hir_id(def_id))
+            .map(|def_id| hir.local_def_id_to_hir_id(def_id))
             .and_then(|hir_id| hir.maybe_body_owned_by(hir_id))
             .map(|body_id| hir.body(body_id));
         let mut visitor = AwaitsVisitor::default();
@@ -1535,7 +1535,7 @@ fn note_obligation_cause_for_async_await(
                             .tcx
                             .parent(generator_did)
                             .and_then(|parent_did| parent_did.as_local())
-                            .map(|parent_did| hir.as_local_hir_id(parent_did))
+                            .map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
                             .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
                             .map(|name| {
                                 format!("future returned by `{}` is not {}", name, trait_name)
index 717b7e2fe574f05c7da7942b98e5d4fa0b4dd034..316181ce7d4a9291f53f19464a9e0ad16dbac0bb 100644 (file)
@@ -324,8 +324,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty,
@@ -353,9 +352,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             }
 
             ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-
-                // (*) This is kind of hacky -- we need to be able to
+                // This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
                 // otherwise we wind up a need to normalize when doing
                 // trait matching (since you can have a trait
index 59fa4c1598d4184bf4db52b1f0f3021f34ef0c1e..93652329305a5bc98482ff0b0eaeee2aaa5f5d5c 100644 (file)
@@ -101,8 +101,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.kind {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
-                // (*)
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
                     Reveal::UserFacing => ty,
@@ -140,8 +139,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             }
 
             ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
-                // (*)
-                // (*) This is kind of hacky -- we need to be able to
+                // This is kind of hacky -- we need to be able to
                 // handle normalization within binders because
                 // otherwise we wind up a need to normalize when doing
                 // trait matching (since you can have a trait
index 9b737d464174a44b77eb0b0c00712b832eb656b6..4d81a3baa0edcedba098eca69d66807028800f1e 100644 (file)
@@ -451,7 +451,7 @@ fn report_conflicting_impls(
             };
             tcx.struct_span_lint_hir(
                 lint,
-                tcx.hir().as_local_hir_id(impl_def_id),
+                tcx.hir().local_def_id_to_hir_id(impl_def_id),
                 impl_span,
                 decorate,
             )
index cc8997078e0f09e8be8d249074b31370ec3a8513..f626bb0b7e365eb3d9453b60e70d6327bd715171 100644 (file)
@@ -53,10 +53,14 @@ pub fn label_with_exp_info(
                 diag.span_label(*sp, format!("referenced here ({})", use_desc));
             }
         }
-        diag.span_label(
-            self.bottom().1,
-            format!("trait alias used in trait object type ({})", use_desc),
-        );
+        if self.top().1 != self.bottom().1 {
+            // When the trait object is in a return type these two spans match, we don't want
+            // redundant labels.
+            diag.span_label(
+                self.bottom().1,
+                format!("trait alias used in trait object type ({})", use_desc),
+            );
+        }
     }
 
     pub fn trait_ref(&self) -> ty::PolyTraitRef<'tcx> {
index f8487982e3d49e0057d0263e7e6c41d7ccc36cf8..f5545f562938fd8b925bf17d8152256c6adddd16 100644 (file)
@@ -9,7 +9,7 @@ name = "rustc_traits"
 path = "lib.rs"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_hir = { path = "../librustc_hir" }
index b8e23760ba5d4aeba071b7f9abb4170e28801dab..6fea4732dda3fd6a18c713f4621f16316de12a45 100644 (file)
@@ -8,7 +8,7 @@
 #![recursion_limit = "256"]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
index 6cdb3530002783ce4e61c47673d174ecd8853d6d..adc9740c2c173d14579d6c4c6a7a3e4b8b6727a3 100644 (file)
@@ -9,7 +9,7 @@ name = "rustc_ty"
 path = "lib.rs"
 
 [dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
index 1e0c4055af3c5a476a1dec21b5e9bf042e18ff62..d0bd88af1ffd1f4abc376e7139e37609bcadd954 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
-use log::debug;
+use tracing::debug;
 
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
index 8f3b20c7aaf406ff682857c34c5b55ac77d375bf..6e9042d1ba7c84518aae084c1016f4b539e076c7 100644 (file)
@@ -12,7 +12,7 @@
 #[macro_use]
 extern crate rustc_middle;
 #[macro_use]
-extern crate log;
+extern crate tracing;
 
 use rustc_middle::ty::query::Providers;
 
index b31f9f3c7b14f9c30f6fb91f103be0df2775f268..0f1dee7e2e006f6e5068cddec25eafbb89ba92e2 100644 (file)
@@ -126,7 +126,7 @@ fn associated_item_from_impl_item_ref(
 }
 
 fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
-    let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let parent_id = tcx.hir().get_parent_item(id);
     let parent_def_id = tcx.hir().local_def_id(parent_id);
     let parent_item = tcx.hir().expect_item(parent_id);
@@ -164,7 +164,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
 }
 
 fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let item = tcx.hir().expect_item(hir_id);
     if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
         defaultness
@@ -198,7 +198,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain
 }
 
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
-    let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let item = tcx.hir().expect_item(id);
     match item.kind {
         hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
@@ -268,7 +268,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
 
     let body_id = def_id
         .as_local()
-        .map(|def_id| tcx.hir().as_local_hir_id(def_id))
+        .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
         .map_or(hir::CRATE_HIR_ID, |id| {
             tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
         });
@@ -360,7 +360,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> {
 
 /// Check if a function is async.
 fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
 
     let node = tcx.hir().get(hir_id);
 
index 963deda162d62e61e3b3a35e9c1480f80a47f531..82c6ac7a0cd73a2b84003898e1c8b32db6cde517 100644 (file)
@@ -12,7 +12,7 @@ doctest = false
 
 [dependencies]
 rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 rustc_middle = { path = "../librustc_middle" }
 rustc_attr = { path = "../librustc_attr" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index 2be100ae33662174e16a127c54c18e04a0e580ef..5170a060c5fe04191b71b6700cff6114464fbdd3 100644 (file)
@@ -170,7 +170,7 @@ pub fn ast_region_to_region(
         def: Option<&ty::GenericParamDef>,
     ) -> ty::Region<'tcx> {
         let tcx = self.tcx();
-        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().as_local_hir_id(def_id));
+        let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
 
         let r = match tcx.named_region(lifetime.hir_id) {
             Some(rl::Region::Static) => tcx.lifetimes.re_static,
@@ -1623,6 +1623,7 @@ fn conv_object_ty_poly_trait_ref(
         span: Span,
         trait_bounds: &[hir::PolyTraitRef<'_>],
         lifetime: &hir::Lifetime,
+        borrowed: bool,
     ) -> Ty<'tcx> {
         let tcx = self.tcx();
 
@@ -1665,6 +1666,20 @@ fn conv_object_ty_poly_trait_ref(
                 "additional use",
             );
             first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
+            err.help(&format!(
+                "consider creating a new trait with all of these as super-traits and using that \
+                 trait here instead: `trait NewTrait: {} {{}}`",
+                regular_traits
+                    .iter()
+                    .map(|t| t.trait_ref().print_only_trait_path().to_string())
+                    .collect::<Vec<_>>()
+                    .join(" + "),
+            ));
+            err.note(
+                "auto-traits like `Send` and `Sync` are traits that have special properties; \
+                 for more information on them, visit \
+                 <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+            );
             err.emit();
         }
 
@@ -1837,15 +1852,20 @@ fn conv_object_ty_poly_trait_ref(
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(None, span).unwrap_or_else(|| {
-                        // FIXME: these can be redundant with E0106, but not always.
-                        struct_span_err!(
+                        let mut err = struct_span_err!(
                             tcx.sess,
                             span,
                             E0228,
                             "the lifetime bound for this object type cannot be deduced \
                              from context; please supply an explicit bound"
-                        )
-                        .emit();
+                        );
+                        if borrowed {
+                            // We will have already emitted an error E0106 complaining about a
+                            // missing named lifetime in `&dyn Trait`, so we elide this one.
+                            err.delay_as_bug();
+                        } else {
+                            err.emit();
+                        }
                         tcx.lifetimes.re_static
                     })
                 }
@@ -2099,7 +2119,7 @@ fn find_bound_for_assoc_item(
 
         debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
 
-        let param_hir_id = tcx.hir().as_local_hir_id(ty_param_def_id);
+        let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
         let param_name = tcx.hir().ty_param_name(param_hir_id);
         self.one_bound_for_assoc_type(
             || {
@@ -2483,7 +2503,7 @@ fn qpath_to_ty(
 
             let parent_def_id = def_id
                 .and_then(|def_id| {
-                    def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+                    def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
                 })
                 .map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
 
@@ -2819,7 +2839,7 @@ pub fn res_to_ty(
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(path.segments);
 
-                let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                 let item_id = tcx.hir().get_parent_node(hir_id);
                 let item_def_id = tcx.hir().local_def_id(item_id);
                 let generics = tcx.generics_of(item_def_id);
@@ -2873,6 +2893,12 @@ pub fn res_to_ty(
     /// Parses the programmer's textual representation of a type into our
     /// internal notion of a type.
     pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+        self.ast_ty_to_ty_inner(ast_ty, false)
+    }
+
+    /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
+    /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
+    fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
         debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
 
         let tcx = self.tcx();
@@ -2885,7 +2911,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
             hir::TyKind::Rptr(ref region, ref mt) => {
                 let r = self.ast_region_to_region(region, None);
                 debug!("ast_ty_to_ty: r={:?}", r);
-                let t = self.ast_ty_to_ty(&mt.ty);
+                let t = self.ast_ty_to_ty_inner(&mt.ty, true);
                 tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
             }
             hir::TyKind::Never => tcx.types.never,
@@ -2903,7 +2929,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
                 ))
             }
             hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
-                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
+                self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
             }
             hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
index 255f611cfa3572c2f5aca33850d0b608afb36e39..c7f9e9d63e03c576a21a595dd72144437b5d5040 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Span;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::ArgKind;
@@ -76,60 +76,44 @@ fn check_closure(
         let generator_types =
             check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1;
 
-        let base_substs = InternalSubsts::identity_for_item(
+        let parent_substs = InternalSubsts::identity_for_item(
             self.tcx,
             self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
         );
-        // HACK(eddyb) this hardcodes indices into substs but it should rely on
-        // `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead.
-        // That would also remove the need for most of the inference variables,
-        // as they immediately unified with the actual type below, including
-        // the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods.
-        let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 };
-        let substs =
-            base_substs.extend_to(self.tcx, expr_def_id.to_def_id(), |param, _| match param.kind {
-                GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"),
-                GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx {
-                    self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(
-                        |upvars| {
-                            upvars.iter().map(|(&var_hir_id, _)| {
-                                // Create type variables (for now) to represent the transformed
-                                // types of upvars. These will be unified during the upvar
-                                // inference phase (`upvar.rs`).
-                                self.infcx.next_ty_var(TypeVariableOrigin {
-                                    // FIXME(eddyb) distinguish upvar inference variables from the rest.
-                                    kind: TypeVariableOriginKind::ClosureSynthetic,
-                                    span: self.tcx.hir().span(var_hir_id),
-                                })
-                            })
-                        },
-                    ))
-                } else {
-                    // Create type variables (for now) to represent the various
-                    // pieces of information kept in `{Closure,Generic}Substs`.
-                    // They will either be unified below, or later during the upvar
-                    // inference phase (`upvar.rs`)
+
+        let tupled_upvars_ty =
+            self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| {
+                upvars.iter().map(|(&var_hir_id, _)| {
+                    // Create type variables (for now) to represent the transformed
+                    // types of upvars. These will be unified during the upvar
+                    // inference phase (`upvar.rs`).
                     self.infcx.next_ty_var(TypeVariableOrigin {
+                        // FIXME(eddyb) distinguish upvar inference variables from the rest.
                         kind: TypeVariableOriginKind::ClosureSynthetic,
-                        span: expr.span,
+                        span: self.tcx.hir().span(var_hir_id),
                     })
-                }
-                .into(),
-                GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
-            });
+                })
+            }));
+
         if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
         {
-            let generator_substs = substs.as_generator();
-            self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty());
-            self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty());
-            self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty());
-            self.demand_eqtype(expr.span, interior, generator_substs.witness());
-
-            // HACK(eddyb) this forces the types equated above into `substs` but
-            // it should rely on `GeneratorSubsts` providing a constructor, instead.
-            let substs = self.resolve_vars_if_possible(&substs);
+            let generator_substs = ty::GeneratorSubsts::new(
+                self.tcx,
+                ty::GeneratorSubstsParts {
+                    parent_substs,
+                    resume_ty,
+                    yield_ty,
+                    return_ty: liberated_sig.output(),
+                    witness: interior,
+                    tupled_upvars_ty,
+                },
+            );
 
-            return self.tcx.mk_generator(expr_def_id.to_def_id(), substs, movability);
+            return self.tcx.mk_generator(
+                expr_def_id.to_def_id(),
+                generator_substs.substs,
+                movability,
+            );
         }
 
         // Tuple up the arguments and insert the resulting function type into
@@ -149,18 +133,29 @@ fn check_closure(
             expr_def_id, sig, opt_kind
         );
 
-        let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
-        self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty());
+        let closure_kind_ty = match opt_kind {
+            Some(kind) => kind.to_ty(self.tcx),
 
-        if let Some(kind) = opt_kind {
-            self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty());
-        }
+            // Create a type variable (for now) to represent the closure kind.
+            // It will be unified during the upvar inference phase (`upvar.rs`)
+            None => self.infcx.next_ty_var(TypeVariableOrigin {
+                // FIXME(eddyb) distinguish closure kind inference variables from the rest.
+                kind: TypeVariableOriginKind::ClosureSynthetic,
+                span: expr.span,
+            }),
+        };
 
-        // HACK(eddyb) this forces the types equated above into `substs` but
-        // it should rely on `ClosureSubsts` providing a constructor, instead.
-        let substs = self.resolve_vars_if_possible(&substs);
+        let closure_substs = ty::ClosureSubsts::new(
+            self.tcx,
+            ty::ClosureSubstsParts {
+                parent_substs,
+                closure_kind_ty,
+                closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig),
+                tupled_upvars_ty,
+            },
+        );
 
-        let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), substs);
+        let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs);
 
         debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);
 
index db8cdfc5b20d65ea7160c9b6f3bcc3637d38762f..f0802c45ae030b5ea47d14b33170fd39a53d5e57 100644 (file)
@@ -1502,7 +1502,7 @@ fn add_impl_trait_explanation<'a>(
                 let ty = AstConv::ast_ty_to_ty(fcx, ty);
                 // Get the `impl Trait`'s `DefId`.
                 if let ty::Opaque(def_id, _) = ty.kind {
-                    let hir_id = fcx.tcx.hir().as_local_hir_id(def_id.expect_local());
+                    let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
                     // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
                     // get the `Trait`'s `DefId`.
                     if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
index b739e2fe1fbc4ffecb0aed169e2a8064bf34526d..7adcd7b472e0d061dc24259f3e187fd4d8da716e 100644 (file)
@@ -77,7 +77,7 @@ fn compare_predicate_entailment<'tcx>(
     // This node-id should be used for the `body_id` field on each
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
-    let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+    let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
 
     // We sometimes modify the span further down.
     let mut cause = ObligationCause::new(
@@ -401,7 +401,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     trait_sig: ty::FnSig<'tcx>,
 ) -> (Span, Option<Span>) {
     let tcx = infcx.tcx;
-    let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+    let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
     let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
         ImplItemKind::Fn(ref impl_m_sig, _) => {
             (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
@@ -412,7 +412,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
     match *terr {
         TypeError::Mutability => {
             if let Some(def_id) = trait_m.def_id.as_local() {
-                let trait_m_hir_id = tcx.hir().as_local_hir_id(def_id);
+                let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                 let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
                     TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
                     _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
@@ -440,7 +440,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>(
         }
         TypeError::Sorts(ExpectedFound { .. }) => {
             if let Some(def_id) = trait_m.def_id.as_local() {
-                let trait_m_hir_id = tcx.hir().as_local_hir_id(def_id);
+                let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                 let (trait_m_output, trait_m_iter) =
                     match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
                         TraitItemKind::Fn(ref trait_m_sig, _) => {
@@ -589,7 +589,7 @@ fn compare_number_of_generics<'tcx>(
             err_occurred = true;
 
             let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
-                let trait_hir_id = tcx.hir().as_local_hir_id(def_id);
+                let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                 let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
                 if trait_item.generics.params.is_empty() {
                     (Some(vec![trait_item.generics.span]), vec![])
@@ -614,7 +614,7 @@ fn compare_number_of_generics<'tcx>(
                 (trait_span.map(|s| vec![s]), vec![])
             };
 
-            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id.expect_local());
+            let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
             let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
             let impl_item_impl_trait_spans: Vec<Span> = impl_item
                 .generics
@@ -706,7 +706,7 @@ fn compare_number_of_method_arguments<'tcx>(
     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
     if trait_number_args != impl_number_args {
         let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
-            let trait_id = tcx.hir().as_local_hir_id(def_id);
+            let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
             match tcx.hir().expect_trait_item(trait_id).kind {
                 TraitItemKind::Fn(ref trait_m_sig, _) => {
                     let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
@@ -729,7 +729,7 @@ fn compare_number_of_method_arguments<'tcx>(
         } else {
             trait_item_span
         };
-        let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+        let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
         let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
             ImplItemKind::Fn(ref impl_m_sig, _) => {
                 let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
@@ -811,7 +811,7 @@ fn compare_synthetic_generics<'tcx>(
         impl_m_type_params.zip(trait_m_type_params)
     {
         if impl_synthetic != trait_synthetic {
-            let impl_hir_id = tcx.hir().as_local_hir_id(impl_def_id.expect_local());
+            let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local());
             let impl_span = tcx.hir().span(impl_hir_id);
             let trait_span = tcx.def_span(trait_def_id);
             let mut err = struct_span_err!(
@@ -832,10 +832,10 @@ fn compare_synthetic_generics<'tcx>(
                         // FIXME: this is obviously suboptimal since the name can already be used
                         // as another generic argument
                         let new_name = tcx.sess.source_map().span_to_snippet(trait_span).ok()?;
-                        let trait_m = tcx.hir().as_local_hir_id(trait_m.def_id.as_local()?);
+                        let trait_m = tcx.hir().local_def_id_to_hir_id(trait_m.def_id.as_local()?);
                         let trait_m = tcx.hir().trait_item(hir::TraitItemId { hir_id: trait_m });
 
-                        let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id.as_local()?);
+                        let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
 
                         // in case there are no generics, take the spot between the function name
@@ -869,7 +869,7 @@ fn compare_synthetic_generics<'tcx>(
                 (None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
                     err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
                     (|| {
-                        let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id.as_local()?);
+                        let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
                         let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
                         let input_tys = match impl_m.kind {
                             hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
@@ -962,7 +962,7 @@ fn nested_visit_map(
 
         // Create a parameter environment that represents the implementation's
         // method.
-        let impl_c_hir_id = tcx.hir().as_local_hir_id(impl_c.def_id.expect_local());
+        let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
 
         // Compute placeholder form of impl and trait const tys.
         let impl_ty = tcx.type_of(impl_c.def_id);
@@ -1011,7 +1011,7 @@ fn nested_visit_map(
             );
 
             let trait_c_hir_id =
-                trait_c.def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id));
+                trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
             let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
                 // Add a label to the Span containing just the type of the const
                 match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
@@ -1101,7 +1101,7 @@ fn compare_type_predicate_entailment<'tcx>(
     // This `HirId` should be used for the `body_id` field on each
     // `ObligationCause` (and the `FnCtxt`). This is what
     // `regionck_item` expects.
-    let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
+    let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
     let cause = ObligationCause::new(
         impl_ty_span,
         impl_ty_hir_id,
@@ -1240,7 +1240,7 @@ fn compare_projection_bounds<'tcx>(
         let infcx = &inh.infcx;
         let mut selcx = traits::SelectionContext::new(&infcx);
 
-        let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
+        let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
         let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
         let cause = ObligationCause::new(
             impl_ty_span,
index 258c5b77df25bc21c938fdee530147ba7f4b4a3c..4ea76a4a9e2abb462ce0cd3c6d8148f5c2032edd 100644 (file)
@@ -34,6 +34,7 @@ pub fn emit_coerce_suggestions(
         }
         self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
         self.suggest_missing_await(err, expr, expected, expr_ty);
+        self.suggest_missing_parentheses(err, expr);
         self.note_need_for_fn_pointer(err, expected, expr_ty);
     }
 
index 9ef9164191675cf6432dd918200323153b8fc085..434886538fb4d99b4a36bcfccf7405e13187ae39 100644 (file)
@@ -70,7 +70,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     drop_impl_ty: Ty<'tcx>,
     self_type_did: DefId,
 ) -> Result<(), ErrorReported> {
-    let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did);
+    let drop_impl_hir_id = tcx.hir().local_def_id_to_hir_id(drop_impl_did);
 
     // check that the impl type can be made to match the trait type.
 
@@ -183,7 +183,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // absent. So we report an error that the Drop impl injected a
     // predicate that is not present on the struct definition.
 
-    let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did);
+    let self_type_hir_id = tcx.hir().local_def_id_to_hir_id(self_type_did);
 
     // We can assume the predicates attached to struct/enum definition
     // hold.
index e7eaca62bdd8e31c6fcf5e1fdb861ab221cde7c2..e88f13a1f3ab68576acd1f10a5cd42dadfecbd93 100644 (file)
@@ -1606,7 +1606,7 @@ fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::
         }
         let param_def_id = generic_param.def_id;
         let param_hir_id = match param_def_id.as_local() {
-            Some(x) => self.tcx.hir().as_local_hir_id(x),
+            Some(x) => self.tcx.hir().local_def_id_to_hir_id(x),
             None => return,
         };
         let param_span = self.tcx.hir().span(param_hir_id);
index 106df847a05cff8ed93e835827a5c11a61fb5ec0..9078dc40041aa376c9648aca6b14791d442677bd 100644 (file)
@@ -649,6 +649,10 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'t
                     self.assemble_inherent_impl_for_primitive(lang_def_id);
                 }
             }
+            ty::Array(_, _) => {
+                let lang_def_id = lang_items.array_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+            }
             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => {
                 let (lang_def_id1, lang_def_id2) = match mutbl {
                     hir::Mutability::Not => {
index e69102d1995d3f05d4d85d58600ae15f39ee3218..e941c844a6d9058113a018e0d2fa6ab561275399 100644 (file)
@@ -579,7 +579,9 @@ macro_rules! report_function {
                             {
                                 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind {
                                     let node = def.did.as_local().map(|def_id| {
-                                        self.tcx.hir().get(self.tcx.hir().as_local_hir_id(def_id))
+                                        self.tcx
+                                            .hir()
+                                            .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
                                     });
                                     if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
                                         if let Some(g) = kind.generics() {
@@ -859,7 +861,7 @@ fn suggest_use_candidates(
         candidates: Vec<DefId>,
     ) {
         let module_did = self.tcx.parent_module(self.body_id);
-        let module_id = self.tcx.hir().as_local_hir_id(module_did);
+        let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
         let krate = self.tcx.hir().krate();
         let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
         if let Some(span) = span {
@@ -975,7 +977,7 @@ fn suggest_traits_to_import<'b>(
                                 let id = item
                                     .def_id
                                     .as_local()
-                                    .map(|def_id| self.tcx.hir().as_local_hir_id(def_id));
+                                    .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
                                 if let Some(hir::Node::TraitItem(hir::TraitItem {
                                     kind: hir::TraitItemKind::Fn(fn_sig, method),
                                     ..
@@ -1062,7 +1064,7 @@ fn suggest_traits_to_import<'b>(
                 let type_param = generics.type_param(param, self.tcx);
                 let hir = &self.tcx.hir();
                 if let Some(def_id) = type_param.def_id.as_local() {
-                    let id = hir.as_local_hir_id(def_id);
+                    let id = hir.local_def_id_to_hir_id(def_id);
                     // Get the `hir::Param` to verify whether it already has any bounds.
                     // We do this to avoid suggesting code that ends up as `T: FooBar`,
                     // instead we suggest `T: Foo + Bar` in that case.
index a40b6860f7765d7da49774f51ef87504cee3d9d2..a625b5ea40567dc625602a55ac7e682275388352 100644 (file)
@@ -974,7 +974,7 @@ fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tc
 /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
 fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
     let fallback = move || {
-        let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id));
+        let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
         tcx.ty_error_with_message(span, "diagnostic only typeck table used")
     };
     typeck_with_fallback(tcx, def_id, fallback)
@@ -992,7 +992,7 @@ fn typeck_with_fallback<'tcx>(
         return tcx.typeck(outer_def_id);
     }
 
-    let id = tcx.hir().as_local_hir_id(def_id);
+    let id = tcx.hir().local_def_id_to_hir_id(def_id);
     let span = tcx.hir().span(id);
 
     // Figure out what primary body this item has.
@@ -1333,7 +1333,7 @@ fn check_fn<'a, 'tcx>(
     }
 
     let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
-    let outer_hir_id = hir.as_local_hir_id(outer_def_id);
+    let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id);
     GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
 
     // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
@@ -1444,7 +1444,7 @@ fn check_fn<'a, 'tcx>(
     // Check that the main return type implements the termination trait.
     if let Some(term_id) = tcx.lang_items().termination() {
         if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) {
-            let main_id = hir.as_local_hir_id(def_id);
+            let main_id = hir.local_def_id_to_hir_id(def_id);
             if main_id == fn_id {
                 let substs = tcx.mk_substs_trait(declared_ret_ty, &[]);
                 let trait_ref = ty::TraitRef::new(term_id, substs);
@@ -1622,7 +1622,7 @@ fn check_opaque<'tcx>(
 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
 /// in "inheriting lifetimes".
 fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
-    let item = tcx.hir().expect_item(tcx.hir().as_local_hir_id(def_id));
+    let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
     debug!(
         "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
         def_id, span, item
@@ -1729,7 +1729,7 @@ fn get_owner_return_paths(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
 ) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let id = tcx.hir().get_parent_item(hir_id);
     tcx.hir()
         .find(id)
@@ -1833,7 +1833,7 @@ fn binding_opaque_type_cycle_error(
     let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
     err.span_label(span, "cannot resolve opaque type");
     // Find the the owner that declared this `impl Trait` type.
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let mut prev_hir_id = hir_id;
     let mut hir_id = tcx.hir().get_parent_node(hir_id);
     while let Some(node) = tcx.hir().find(hir_id) {
@@ -1858,7 +1858,7 @@ fn binding_opaque_type_cycle_error(
                 source: hir::LocalSource::Normal,
                 ..
             }) => {
-                let hir_id = tcx.hir().as_local_hir_id(def_id);
+                let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
                 let typeck_results =
                     tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
                 if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) {
@@ -2874,7 +2874,7 @@ pub fn check_enum<'tcx>(
         // Check for duplicate discriminant values
         if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
             let variant_did = def.variants[VariantIdx::new(i)].def_id;
-            let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did.expect_local());
+            let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
             let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
             let i_span = match variant_i.disr_expr {
                 Some(ref expr) => tcx.hir().span(expr.hir_id),
@@ -2935,7 +2935,7 @@ fn default_constness_for_trait_bounds(&self) -> hir::Constness {
 
     fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
         let tcx = self.tcx;
-        let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         let item_id = tcx.hir().ty_param_owner(hir_id);
         let item_def_id = tcx.hir().local_def_id(item_id);
         let generics = tcx.generics_of(item_def_id);
@@ -5401,6 +5401,14 @@ fn suggest_missing_await(
         }
     }
 
+    fn suggest_missing_parentheses(&self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>) {
+        let sp = self.tcx.sess.source_map().start_point(expr.span);
+        if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+            // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+            self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
+        }
+    }
+
     fn note_need_for_fn_pointer(
         &self,
         err: &mut DiagnosticBuilder<'_>,
index fd516c88ec61aac2896f340e66d4baee1236c065..66fb01a54f5741256a76bc28222eb5b1375128ed 100644 (file)
@@ -933,7 +933,7 @@ fn suggest_constraining_param(
     let param_def_id = generics.type_param(&p, tcx).def_id;
     if let Some(generics) = param_def_id
         .as_local()
-        .map(|id| hir.as_local_hir_id(id))
+        .map(|id| hir.local_def_id_to_hir_id(id))
         .and_then(|id| hir.find(hir.get_parent_item(id)))
         .as_ref()
         .and_then(|node| node.generics())
index 50d9a1ebd2c249d6671862e9af6a37cfc726e959..2bde5d2c78cc195378fb8e645afb44672628cd43 100644 (file)
@@ -71,7 +71,7 @@ fn with_fcx<F>(&mut self, f: F)
 /// not included it frequently leads to confusing errors in fn bodies. So it's better to check
 /// the types first.
 pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let item = tcx.hir().expect_item(hir_id);
 
     debug!(
@@ -190,7 +190,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
 }
 
 pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let trait_item = tcx.hir().expect_trait_item(hir_id);
 
     let method_sig = match trait_item.kind {
@@ -264,7 +264,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
 }
 
 pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let impl_item = tcx.hir().expect_impl_item(hir_id);
 
     let method_sig = match impl_item.kind {
@@ -902,7 +902,7 @@ fn check_opaque_types<'fcx, 'tcx>(
                 let generics = tcx.generics_of(def_id);
 
                 let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
-                    tcx.hir().as_local_hir_id(local_id)
+                    tcx.hir().local_def_id_to_hir_id(local_id)
                 } else {
                     // Opaque types from other crates won't have defining uses in this crate.
                     return ty;
index 82ee48f0b53461448e4565705e1a08999f6e9893..50e2d6a94bb71082b07763d69b10fddeca049eba 100644 (file)
@@ -433,7 +433,7 @@ fn visit_generator_interior_types(&mut self) {
 
     fn visit_opaque_types(&mut self, span: Span) {
         for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
-            let hir_id = self.tcx().hir().as_local_hir_id(def_id.expect_local());
+            let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local());
             let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
index 81daf064bb36866a74d90663460cbfd2958766de..4fda8932e213b0d294e1712dc94587b123eb2d23 100644 (file)
@@ -88,7 +88,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
             // Note that if we carry through to the `extern_mod_stmt_cnum` query
             // below it'll cause a panic because `def_id` is actually bogus at this
             // point in time otherwise.
-            if tcx.hir().find(tcx.hir().as_local_hir_id(def_id)).is_none() {
+            if tcx.hir().find(tcx.hir().local_def_id_to_hir_id(def_id)).is_none() {
                 return false;
             }
             true
@@ -113,7 +113,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
 
     for extern_crate in &crates_to_lint {
         let def_id = extern_crate.def_id.expect_local();
-        let id = tcx.hir().as_local_hir_id(def_id);
+        let id = tcx.hir().local_def_id_to_hir_id(def_id);
         let item = tcx.hir().expect_item(id);
 
         // If the crate is fully unused, we suggest removing it altogether.
index 8c6161a62647346b780450776524de5e5228a51d..56a737964c0479809caa9ba85642d015bec8aefb 100644 (file)
@@ -54,7 +54,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
         return;
     }
 
-    let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
     let sp = match tcx.hir().expect_item(impl_hir_id).kind {
         ItemKind::Impl { self_ty, .. } => self_ty.span,
         _ => bug!("expected Drop impl item"),
@@ -73,7 +73,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
 fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
 
-    let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
 
     let self_type = tcx.type_of(impl_did);
     debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
@@ -146,7 +146,7 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefI
 fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
 
-    let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
     let span = tcx.hir().span(impl_hir_id);
 
     let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span));
@@ -315,7 +315,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
 
     // this provider should only get invoked for local def-ids
-    let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local());
+    let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
     let span = tcx.hir().span(impl_hir_id);
 
     let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span));
index 93ee87f6c572ee5bd164247dcb11fefcabfe8789..cd7429f166f26aa6fc141461aa70ea9d1282a9fa 100644 (file)
@@ -112,6 +112,16 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     item.span,
                 );
             }
+            ty::Array(_, _) => {
+                self.check_primitive_impl(
+                    def_id,
+                    lang_items.array_impl(),
+                    None,
+                    "array",
+                    "[T; N]",
+                    item.span,
+                );
+            }
             ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
                 if matches!(inner.kind, ty::Slice(_)) =>
             {
index b47ef34600404c1c7e5d37d48af1fb8fca744eee..da1f3ea62f239716d15bf11a25ec6c6cf4fdb9dd 100644 (file)
@@ -275,7 +275,7 @@ pub fn to_ty(&self, ast_ty: &'tcx hir::Ty<'tcx>) -> Ty<'tcx> {
     }
 
     pub fn hir_id(&self) -> hir::HirId {
-        self.tcx.hir().as_local_hir_id(self.item_def_id.expect_local())
+        self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local())
     }
 
     pub fn node(&self) -> hir::Node<'tcx> {
@@ -490,7 +490,7 @@ fn type_param_predicates(
     // written inline like `<T: Foo>` or in a where-clause like
     // `where T: Foo`.
 
-    let param_id = tcx.hir().as_local_hir_id(def_id);
+    let param_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let param_owner = tcx.hir().ty_param_owner(param_id);
     let param_owner_def_id = tcx.hir().local_def_id(param_owner);
     let generics = tcx.generics_of(param_owner_def_id);
@@ -512,7 +512,7 @@ fn type_param_predicates(
         .unwrap_or_default();
     let mut extend = None;
 
-    let item_hir_id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+    let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
     let ast_generics = match tcx.hir().get(item_hir_id) {
         Node::TraitItem(item) => &item.generics,
 
@@ -824,7 +824,7 @@ fn convert_variant(
     parent_did: LocalDefId,
 ) -> ty::VariantDef {
     let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
-    let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did));
+    let hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.unwrap_or(parent_did));
     let fields = def
         .fields()
         .iter()
@@ -878,7 +878,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
     use rustc_hir::*;
 
     let def_id = def_id.expect_local();
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let item = match tcx.hir().get(hir_id) {
         Node::Item(item) => item,
         _ => bug!(),
@@ -965,7 +965,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef {
 /// the transitive super-predicates are converted.
 fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
     debug!("super_predicates(trait_def_id={:?})", trait_def_id);
-    let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id.expect_local());
+    let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
 
     let item = match tcx.hir().get(trait_hir_id) {
         Node::Item(item) => item,
@@ -1016,7 +1016,7 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi
 }
 
 fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let item = tcx.hir().expect_item(hir_id);
 
     let (is_auto, unsafety) = match item.kind {
@@ -1194,7 +1194,7 @@ fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
 fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
     use rustc_hir::*;
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
 
     let node = tcx.hir().get(hir_id);
     let parent_def_id = match node {
@@ -1499,7 +1499,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
     use rustc_hir::*;
 
     let def_id = def_id.expect_local();
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
@@ -1597,7 +1597,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
 fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
     let icx = ItemCtxt::new(tcx, def_id);
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     match tcx.hir().expect_item(hir_id).kind {
         hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
             let selfty = tcx.type_of(def_id);
@@ -1608,7 +1608,7 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
 }
 
 fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
     let item = tcx.hir().expect_item(hir_id);
     match &item.kind {
@@ -1738,7 +1738,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
         }
     }
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     let node = tcx.hir().get(hir_id);
 
     let mut is_trait = None;
@@ -2590,7 +2590,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
     if !codegen_fn_attrs.no_sanitize.is_empty() {
         if codegen_fn_attrs.inline == InlineAttr::Always {
             if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
-                let hir_id = tcx.hir().as_local_hir_id(id.expect_local());
+                let hir_id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
                 tcx.struct_span_lint_hir(
                     lint::builtin::INLINE_NO_SANITIZE,
                     hir_id,
@@ -2718,7 +2718,7 @@ fn check_target_feature_safe_fn(tcx: TyCtxt<'_>, id: DefId, attr_span: Span) {
 /// Checks the function annotated with `#[target_feature]` is not a safe
 /// trait method implementation, reporting an error if it is.
 fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
-    let hir_id = tcx.hir().as_local_hir_id(id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(id);
     let node = tcx.hir().get(hir_id);
     if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
         let parent_id = tcx.hir().get_parent_item(hir_id);
index 17444c6d0ac957442c7760123e1a2f47bf7638a7..f1478c8c952f87c7cd103ce12d22b1bdb0994057 100644 (file)
@@ -23,7 +23,7 @@
 pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
     use hir::*;
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
         let parent_node_id = tcx.hir().get_parent_node(hir_id);
@@ -138,7 +138,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     let def_id = def_id.expect_local();
     use rustc_hir::*;
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
     let icx = ItemCtxt::new(tcx, def_id.to_def_id());
 
@@ -564,7 +564,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         }
     }
 
-    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let scope = tcx.hir().get_defining_scope(hir_id);
     let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
 
@@ -617,7 +617,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
 ///    by the time we borrow check, and it's not clear how we should handle
 ///    those.
 fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
-    let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
+    let scope = tcx.hir().get_defining_scope(tcx.hir().local_def_id_to_hir_id(opaque_ty_id));
     let scope_def_id = tcx.hir().local_def_id(scope);
 
     let opaque_ty_def_id = opaque_ty_id.to_def_id();
@@ -653,7 +653,7 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty
     if concrete_ty.has_erased_regions() {
         // FIXME(impl_trait_in_bindings) Handle this case.
         tcx.sess.span_fatal(
-            tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
+            tcx.hir().span(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)),
             "lifetimes in impl Trait types in bindings are not currently supported",
         );
     }
index 8257c6ce92547b8d51378a9797845c1a6b8a3385..3746e5778aacdb740694fc3adf08952e710cff8e 100644 (file)
@@ -336,7 +336,7 @@ fn check_predicates<'tcx>(
         if let Some(obligations) = wf::obligations(
             infcx,
             tcx.param_env(impl1_def_id),
-            tcx.hir().as_local_hir_id(impl1_def_id),
+            tcx.hir().local_def_id_to_hir_id(impl1_def_id),
             arg,
             span,
         ) {
index 49843fa43dd8c8e7fc4dd5f1008cc0dca37ce9f7..4248253172598c877d82b0554e95e9faa6d0d69c 100644 (file)
@@ -69,7 +69,7 @@
 #![recursion_limit = "256"]
 
 #[macro_use]
-extern crate log;
+extern crate tracing;
 
 #[macro_use]
 extern crate rustc_middle;
@@ -153,7 +153,7 @@ fn require_same_types<'tcx>(
 }
 
 fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
-    let main_id = tcx.hir().as_local_hir_id(main_def_id);
+    let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
     let main_span = tcx.def_span(main_def_id);
     let main_t = tcx.type_of(main_def_id);
     match main_t.kind {
@@ -249,7 +249,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
 }
 
 fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
-    let start_id = tcx.hir().as_local_hir_id(start_def_id);
+    let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
     let start_span = tcx.def_span(start_def_id);
     let start_t = tcx.type_of(start_def_id);
     match start_t.kind {
index 15c72f8704f65edb8b37418485a0ebd8df24ef12..762d4216f7060bf5115ff9e60b869cbf247f84e7 100644 (file)
@@ -57,7 +57,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
 
         debug!("InferVisitor::visit_item(item={:?})", item_did);
 
-        let hir_id = self.tcx.hir().as_local_hir_id(item_did);
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(item_did);
         let item = match self.tcx.hir().get(hir_id) {
             Node::Item(item) => item,
             _ => bug!(),
index 5dc7ac9fa0d4e9a9b4e6339ecb8adaed9fc2859d..94926f480e23e3227ef8b2d2e3d47fc9133bf528 100644 (file)
@@ -18,7 +18,7 @@ pub fn provide(providers: &mut Providers) {
 }
 
 fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
-    let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+    let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
 
     match tcx.hir().get(id) {
         Node::Item(item) => match item.kind {
index b810c9824ce66eb5379362cbd49857f29b7037ca..535530a2ed494cb5e7bd44289ce3f679262954c4 100644 (file)
@@ -137,7 +137,7 @@ fn build_constraints_for_item(&mut self, def_id: LocalDefId) {
             return;
         }
 
-        let id = tcx.hir().as_local_hir_id(def_id);
+        let id = tcx.hir().local_def_id_to_hir_id(def_id);
         let inferred_start = self.terms_cx.inferred_starts[&id];
         let current_item = &CurrentItem { inferred_start };
         match tcx.type_of(def_id).kind {
@@ -375,7 +375,7 @@ fn add_constraints_from_substs(
         }
 
         let (local, remote) = if let Some(def_id) = def_id.as_local() {
-            let id = self.tcx().hir().as_local_hir_id(def_id);
+            let id = self.tcx().hir().local_def_id_to_hir_id(def_id);
             (Some(self.terms_cx.inferred_starts[&id]), None)
         } else {
             (None, Some(self.tcx().variances_of(def_id)))
index b307363dc3ab05a8e648bc8c00efe8e4073a7523..a893f69c48adab6536ebb1614a9090b5570cacb9 100644 (file)
@@ -39,7 +39,7 @@ fn crate_variances(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateVariancesMap<'_
 }
 
 fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
-    let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+    let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
     let unsupported = || {
         // Variance not relevant.
         span_bug!(tcx.hir().span(id), "asked to compute variance for wrong kind of item")
index 6e15485756d98abd0e19b8a905785eba90b2947f..f61a783de694be6e499067e6578e26bad09f19d0 100644 (file)
@@ -94,7 +94,9 @@ fn lang_items(tcx: TyCtxt<'_>) -> Vec<(hir::HirId, Vec<ty::Variance>)> {
     all.into_iter() // iterating over (Option<DefId>, Variance)
         .filter(|&(ref d, _)| d.is_some())
         .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
-        .filter_map(|(d, v)| d.as_local().map(|d| tcx.hir().as_local_hir_id(d)).map(|n| (n, v))) // (HirId, Variance)
+        .filter_map(|(d, v)| {
+            d.as_local().map(|d| tcx.hir().local_def_id_to_hir_id(d)).map(|n| (n, v))
+        }) // (HirId, Variance)
         .collect()
 }
 
index 1f576a17dd9d665cfe1d147e1ec0b7108b41773c..cb7c62e3a5ac64759916b85a6e53b399ce03769e 100644 (file)
@@ -356,7 +356,7 @@ pub fn build_impl(
     }
 
     let for_ = if let Some(did) = did.as_local() {
-        let hir_id = tcx.hir().as_local_hir_id(did);
+        let hir_id = tcx.hir().local_def_id_to_hir_id(did);
         match tcx.hir().expect_item(hir_id).kind {
             hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx),
             _ => panic!("did given to build_impl was not an impl"),
@@ -377,7 +377,7 @@ pub fn build_impl(
 
     let predicates = tcx.explicit_predicates_of(did);
     let (trait_items, generics) = if let Some(did) = did.as_local() {
-        let hir_id = tcx.hir().as_local_hir_id(did);
+        let hir_id = tcx.hir().local_def_id_to_hir_id(did);
         match tcx.hir().expect_item(hir_id).kind {
             hir::ItemKind::Impl { ref generics, ref items, .. } => (
                 items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
@@ -500,7 +500,7 @@ fn fill_in(
 
 pub fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
     if let Some(did) = did.as_local() {
-        let hir_id = cx.tcx.hir().as_local_hir_id(did);
+        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did);
         rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id)
     } else {
         cx.tcx.rendered_const(did)
@@ -513,7 +513,7 @@ fn build_const(cx: &DocContext<'_>, did: DefId) -> clean::Constant {
         expr: print_inlined_const(cx, did),
         value: clean::utils::print_evaluated_const(cx, did),
         is_literal: did.as_local().map_or(false, |did| {
-            clean::utils::is_literal_expr(cx, cx.tcx.hir().as_local_hir_id(did))
+            clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did))
         }),
     }
 }
index 801d06e61016961ef8a808004708c727044ddfbf..3ad357e583cf1d0fbfa4e1a19181bc23197841f9 100644 (file)
@@ -1382,7 +1382,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Type {
                 if let Res::Def(DefKind::TyAlias, def_id) = path.res {
                     // Substitute private type aliases
                     if let Some(def_id) = def_id.as_local() {
-                        let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
+                        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
                         if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) {
                             alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
                         }
index c22538f21f69fbefb567942de1fc61e8bbdb63ee..a7d03fcabf546bf473ff20e2c6571d449526a50b 100644 (file)
@@ -388,7 +388,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V
             Bool => tcx.lang_items().bool_impl(),
             Str => tcx.lang_items().str_impl(),
             Slice => tcx.lang_items().slice_impl(),
-            Array => tcx.lang_items().slice_impl(),
+            Array => tcx.lang_items().array_impl(),
             Tuple => None,
             Unit => None,
             RawPointer => tcx.lang_items().const_ptr_impl(),
@@ -471,7 +471,7 @@ pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     match n.val {
         ty::ConstKind::Unevaluated(def, _, promoted) => {
             let mut s = if let Some(def) = def.as_local() {
-                let hir_id = cx.tcx.hir().as_local_hir_id(def.did);
+                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
                 inline::print_inlined_const(cx, def.did)
index b13acaae1bf234048cfd2858a33a01312808486d..c21fd8da0ed9af4953e0cf1c274b5147eb41641d 100644 (file)
@@ -143,13 +143,13 @@ pub fn next_def_id(&self, crate_num: CrateNum) -> DefId {
         def_id
     }
 
-    /// Like the function of the same name on the HIR map, but skips calling it on fake DefIds.
+    /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
     /// (This avoids a slice-index-out-of-bounds panic.)
     pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
         if self.all_fake_def_ids.borrow().contains(&def_id) {
             None
         } else {
-            def_id.as_local().map(|def_id| self.tcx.hir().as_local_hir_id(def_id))
+            def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
         }
     }
 
@@ -400,7 +400,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 }
 
                 let hir = tcx.hir();
-                let body = hir.body(hir.body_owned_by(hir.as_local_hir_id(def_id)));
+                let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id)));
                 debug!("visiting body for {:?}", def_id);
                 EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
index 4cfd81ffbce9da6423f61167ecb6da85394241de..b2589e5b806e8673947695f64cc28eb62417a786 100644 (file)
@@ -655,7 +655,7 @@ fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
             (Some(h), _) => h,
             (None, Some(item_did)) => {
                 match item_did.as_local() {
-                    Some(item_did) => self.tcx.hir().as_local_hir_id(item_did),
+                    Some(item_did) => self.tcx.hir().local_def_id_to_hir_id(item_did),
                     None => {
                         // If non-local, no need to check anything.
                         return;
index 062bd61a7d00279b22ac8a581da9698fbf8e256e..f7fc3579d67a701f7f316169c5bf1e5a06bf76f4 100644 (file)
@@ -813,8 +813,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                 {
                     use rustc_hir::def_id::LOCAL_CRATE;
 
-                    let hir_src = self.cx.tcx.hir().as_local_hir_id(src_id);
-                    let hir_dst = self.cx.tcx.hir().as_local_hir_id(dst_id);
+                    let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
+                    let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
 
                     if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
                         && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
index 3000afde0c25d6172fd91d4ce669fd5657c9a538..a40b45f9a7e2c2f75471c095740183c3f53f998b 100644 (file)
@@ -55,6 +55,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
         lang_items.bool_impl(),
         lang_items.char_impl(),
         lang_items.str_impl(),
+        lang_items.array_impl(),
         lang_items.slice_impl(),
         lang_items.slice_u8_impl(),
         lang_items.str_alloc_impl(),
index cf57ffd0b4b305532d41bcda67bd6942a4ed0e9b..be80193db8c3bd4c619320d7a2e72ed1efc1c496 100644 (file)
@@ -323,7 +323,7 @@ fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool
         }
 
         let res_hir_id = match res_did.as_local() {
-            Some(n) => tcx.hir().as_local_hir_id(n),
+            Some(n) => tcx.hir().local_def_id_to_hir_id(n),
             None => return false,
         };
 
index 7c8481540aae41d259bd79eaa99be4b45634a040..4d15e31df15a3edbe90d443e8833e47b2e1bb65f 100644 (file)
@@ -38,6 +38,11 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
   CoverageMappingWriter.write(OS);
 }
 
+extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
+  StringRef FuncNameRef(FuncName);
+  return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
+}
+
 extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
   StringRef NameRef(Name);
   return IndexedInstrProf::ComputeHash(NameRef);
index 758c6c4da9293c6c807896e9a051342ad78a8b98..493c1b9f0ba6b9a2655d506a4c62b551a21b4fe1 100644 (file)
@@ -18,7 +18,7 @@ pub fn naked_empty() {
 // CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
 pub fn naked_with_args(a: isize) {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
+    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
     // CHECK: ret void
 }
@@ -39,7 +39,7 @@ pub fn naked_with_return() -> isize {
 #[naked]
 pub fn naked_with_args_and_return(a: isize) -> isize {
     // CHECK-NEXT: {{.+}}:
-    // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
+    // CHECK-NEXT: %a = alloca i{{[0-9]+}}
     &a; // keep variable in an alloca
     // CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
     a
diff --git a/src/test/debuginfo/function-arguments-naked.rs b/src/test/debuginfo/function-arguments-naked.rs
deleted file mode 100644 (file)
index 5f3a1eb..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-// min-lldb-version: 310
-
-// We have to ignore android because of this issue:
-// https://github.com/rust-lang/rust/issues/74847
-// ignore-android
-//
-// We need to use inline assembly, so just use one platform
-// only-x86_64
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:info args
-// gdb-check:No arguments.
-// gdb-command:continue
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:frame variable
-// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
-// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
-// lldb-command:continue
-
-
-#![feature(asm)]
-#![feature(naked_functions)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-fn main() {
-    naked(111, 222);
-}
-
-#[naked]
-extern "C" fn naked(x: usize, y: usize) {
-    unsafe { asm!("ret"); } // #break
-}
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.32bit
new file mode 100644 (file)
index 0000000..968890e
--- /dev/null
@@ -0,0 +1,156 @@
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+  
+  fn bar(_1: i32) -> (bool, bool, bool, bool) {
+      debug i => _1;                       // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+      let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+      let _2: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+      let _6: ();                          // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+      let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+      let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+      let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+              let _4: bool;                // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+              scope 3 {
+                  debug c => _4;           // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+                  let _5: bool;            // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  scope 4 {
+                      debug d => _5;       // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          StorageLive(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+          StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+          StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x00))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+      }
+  
+      bb1: {
+          _2 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb2: {
+          _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+          StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          StorageLive(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          _8 = _3;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          StorageLive(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          _9 = _4;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          StorageLive(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          _10 = _5;                        // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          (_0.0: bool) = move _7;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.1: bool) = move _8;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.2: bool) = move _9;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.3: bool) = move _10;         // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          StorageDead(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff.64bit
new file mode 100644 (file)
index 0000000..968890e
--- /dev/null
@@ -0,0 +1,156 @@
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+  
+  fn bar(_1: i32) -> (bool, bool, bool, bool) {
+      debug i => _1;                       // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+      let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+      let _2: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+      let _6: ();                          // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+      let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+      let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+      let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+      scope 1 {
+          debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          scope 2 {
+              debug b => _3;               // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+              let _4: bool;                // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+              scope 3 {
+                  debug c => _4;           // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+                  let _5: bool;            // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  scope 4 {
+                      debug d => _5;       // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+          StorageLive(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+          StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+          StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+          StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++         _2 = Ne(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _3 = Eq(_1, const 7_i32);        // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000007))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x00))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+      }
+  
+      bb1: {
+          _2 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb2: {
+          _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+          StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+          StorageLive(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          _8 = _3;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+          StorageLive(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          _9 = _4;                         // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+          StorageLive(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          _10 = _5;                        // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+          (_0.0: bool) = move _7;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.1: bool) = move _8;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.2: bool) = move _9;          // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          (_0.3: bool) = move _10;         // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+          StorageDead(_10);                // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_9);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_8);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+          StorageDead(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_3);                 // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.32bit
new file mode 100644 (file)
index 0000000..a33db00
--- /dev/null
@@ -0,0 +1,66 @@
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+  
+  fn foo(_1: std::option::Option<()>) -> () {
+      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5:25
+      let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
++         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++                                          // ty::Const
++                                          // + ty: isize
++                                          // + val: Value(Scalar(0x00000000))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) }
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+      }
+  
+      bb1: {
+          _2 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          _2 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb3: {
+          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+      }
+  
+      bb4: {
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+      }
+  
+      bb5: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff.64bit
new file mode 100644 (file)
index 0000000..3eb5b01
--- /dev/null
@@ -0,0 +1,66 @@
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+  
+  fn foo(_1: std::option::Option<()>) -> () {
+      debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+      let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5:25
+      let mut _2: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+-         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
++         _2 = Eq(_3, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++                                          // ty::Const
++                                          // + ty: isize
++                                          // + val: Value(Scalar(0x0000000000000000))
++                                          // mir::Constant
++                                          // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++                                          // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) }
++         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+      }
+  
+      bb1: {
+          _2 = const false;                // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          _2 = const true;                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      }
+  
+      bb3: {
+          switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+      }
+  
+      bb4: {
+          _0 = const ();                   // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+                                           // ty::Const
+                                           // + ty: ()
+                                           // + val: Value(Scalar(<ZST>))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
+                                           // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+          goto -> bb5;                     // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+      }
+  
+      bb5: {
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+          return;                          // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_reduce_branches.rs b/src/test/mir-opt/matches_reduce_branches.rs
new file mode 100644 (file)
index 0000000..ebc88d2
--- /dev/null
@@ -0,0 +1,42 @@
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
+// EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
+
+fn foo(bar: Option<()>) {
+    if matches!(bar, None) {
+      ()
+    }
+}
+
+fn bar(i: i32) -> (bool, bool, bool, bool) {
+    let a;
+    let b;
+    let c;
+    let d;
+
+    match i {
+        7 => {
+            a = false;
+            b = true;
+            c = false;
+            d = true;
+            ()
+        }
+        _ => {
+            a = true;
+            b = false;
+            c = false;
+            d = true;
+            ()
+        }
+    };
+
+    (a, b, c, d)
+}
+
+
+fn main() {
+  let _ = foo(None);
+  let _ = foo(Some(()));
+  let _ = bar(0);
+}
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit
new file mode 100644 (file)
index 0000000..c41bd99
--- /dev/null
@@ -0,0 +1,40 @@
+- // MIR for `exhaustive_match` before MatchBranchSimplification
++ // MIR for `exhaustive_match` after MatchBranchSimplification
+  
+  fn exhaustive_match(_1: E) -> u8 {
+      debug e => _1;                       // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
+      let mut _0: u8;                      // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
+      let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+  
+      bb0: {
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+      }
+  
+      bb1: {
+          _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
+                                           // ty::Const
+                                           // + ty: u8
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:14:17: 14:18
+                                           // + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+      }
+  
+      bb2: {
+          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
+                                           // ty::Const
+                                           // + ty: u8
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:13:17: 13:18
+                                           // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+      }
+  
+      bb3: {
+          return;                          // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit
new file mode 100644 (file)
index 0000000..c41bd99
--- /dev/null
@@ -0,0 +1,40 @@
+- // MIR for `exhaustive_match` before MatchBranchSimplification
++ // MIR for `exhaustive_match` after MatchBranchSimplification
+  
+  fn exhaustive_match(_1: E) -> u8 {
+      debug e => _1;                       // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
+      let mut _0: u8;                      // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
+      let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+  
+      bb0: {
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+      }
+  
+      bb1: {
+          _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
+                                           // ty::Const
+                                           // + ty: u8
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:14:17: 14:18
+                                           // + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+      }
+  
+      bb2: {
+          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
+                                           // ty::Const
+                                           // + ty: u8
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:13:17: 13:18
+                                           // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+      }
+  
+      bb3: {
+          return;                          // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit
new file mode 100644 (file)
index 0000000..2c4bbc8
--- /dev/null
@@ -0,0 +1,40 @@
+- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
++ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
+  
+  fn exhaustive_match_i8(_1: E) -> i8 {
+      debug e => _1;                       // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
+      let mut _0: i8;                      // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
+      let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+  
+      bb0: {
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+      }
+  
+      bb1: {
+          _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
+                                           // ty::Const
+                                           // + ty: i8
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:22:17: 22:18
+                                           // + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+      }
+  
+      bb2: {
+          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
+                                           // ty::Const
+                                           // + ty: i8
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:21:17: 21:18
+                                           // + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+      }
+  
+      bb3: {
+          return;                          // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit
new file mode 100644 (file)
index 0000000..2c4bbc8
--- /dev/null
@@ -0,0 +1,40 @@
+- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
++ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
+  
+  fn exhaustive_match_i8(_1: E) -> i8 {
+      debug e => _1;                       // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
+      let mut _0: i8;                      // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
+      let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+  
+      bb0: {
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+      }
+  
+      bb1: {
+          _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
+                                           // ty::Const
+                                           // + ty: i8
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:22:17: 22:18
+                                           // + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+      }
+  
+      bb2: {
+          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
+                                           // ty::Const
+                                           // + ty: i8
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+                                           // + span: $DIR/matches_u8.rs:21:17: 21:18
+                                           // + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+      }
+  
+      bb3: {
+          return;                          // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/matches_u8.rs b/src/test/mir-opt/matches_u8.rs
new file mode 100644 (file)
index 0000000..78373be
--- /dev/null
@@ -0,0 +1,32 @@
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
+// EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
+
+pub enum E {
+    A,
+    B,
+}
+
+#[no_mangle]
+pub fn exhaustive_match(e: E) -> u8 {
+    match e {
+        E::A => 0,
+        E::B => 1,
+    }
+}
+
+#[no_mangle]
+pub fn exhaustive_match_i8(e: E) -> i8 {
+    match e {
+        E::A => 0,
+        E::B => 1,
+    }
+}
+
+fn main() {
+  assert_eq!(exhaustive_match(E::A), 0);
+  assert_eq!(exhaustive_match(E::B), 1);
+
+  assert_eq!(exhaustive_match_i8(E::A), 0);
+  assert_eq!(exhaustive_match_i8(E::B), 1);
+}
index df47305b547a82e7070dd9f126b65b68e1ea1ef8..4392cfec080dcb0fdcef38d0de01feb6d3ccc6df 100644 (file)
 
 # FIXME(richkadel): Debug the following problem, and reenable on Windows (by
 # removing the `# ignore-msvc` directive above). The current implementation
-# generates a segfault when running the instrumented `main` executable,
-# after the `main` program code executes, but before the process terminates.
-# This most likely points to a problem generating the LLVM "main.profraw"
+# generates a segfault when running the instrumented `testprog` executable,
+# after the `main()` function completes, but before the process terminates.
+# This most likely points to a problem generating the LLVM "testprog.profraw"
 # file.
 
 -include ../tools.mk
 
+UNAME = $(shell uname)
+
+ifeq ($(UNAME),Darwin)
+       INSTR_PROF_DATA_SUFFIX=,regular,live_support
+       DATA_SECTION_PREFIX=__DATA,
+       LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+else
+       INSTR_PROF_DATA_SUFFIX=
+       DATA_SECTION_PREFIX=
+       LLVM_COV_SECTION_PREFIX=
+endif
+
 # This test makes sure that LLVM coverage maps are genereated in LLVM IR.
 
 COMMON_FLAGS=-Zinstrument-coverage
 
 all:
        # Compile the test program with instrumentation, and also generate LLVM IR
-       $(RUSTC) $(COMMON_FLAGS) main.rs
+       $(RUSTC) $(COMMON_FLAGS) testprog.rs \
+                       --emit=link,llvm-ir
+
+       # check the LLVM IR
+ifdef IS_WIN32
+       cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+                       -check-prefixes=CHECK,WIN32 \
+                       -DPRIVATE_GLOBAL="internal global" \
+                       -DINSTR_PROF_DATA=".lprfd$$M" \
+                       -DINSTR_PROF_NAME=".lprfn$$M" \
+                       -DINSTR_PROF_CNTS=".lprfc$$M" \
+                       -DINSTR_PROF_VALS=".lprfv$$M" \
+                       -DINSTR_PROF_VNODES=".lprfnd$$M" \
+                       -DINSTR_PROF_COVMAP=".lcovmap$$M" \
+                       -DINSTR_PROF_ORDERFILE=".lorderfile$$M"
+else
+       cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+                       -check-prefixes=CHECK \
+                       -DPRIVATE_GLOBAL="private global" \
+                       -DINSTR_PROF_DATA="$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)" \
+                       -DINSTR_PROF_NAME="$(DATA_SECTION_PREFIX)__llvm_prf_names" \
+                       -DINSTR_PROF_CNTS="$(DATA_SECTION_PREFIX)__llvm_prf_cnts" \
+                       -DINSTR_PROF_VALS="$(DATA_SECTION_PREFIX)__llvm_prf_vals" \
+                       -DINSTR_PROF_VNODES="$(DATA_SECTION_PREFIX)__llvm_prf_vnds" \
+                       -DINSTR_PROF_COVMAP="$(LLVM_COV_SECTION_PREFIX)__llvm_covmap" \
+                       -DINSTR_PROF_ORDERFILE="$(DATA_SECTION_PREFIX)__llvm_orderfile"
+endif
 
        # Run it in order to generate some profiling data,
        # with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
        # output the coverage stats for this run.
-       LLVM_PROFILE_FILE="$(TMPDIR)"/main.profraw \
-         $(call RUN,main)
+       LLVM_PROFILE_FILE="$(TMPDIR)"/testprog.profraw \
+                       $(call RUN,testprog)
 
        # Postprocess the profiling data so it can be used by the llvm-cov tool
        "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
-         "$(TMPDIR)"/main.profraw \
-               -o "$(TMPDIR)"/main.profdata
+                       "$(TMPDIR)"/testprog.profraw \
+                       -o "$(TMPDIR)"/testprog.profdata
 
        # Generate a coverage report using `llvm-cov show`. The output ordering
        # can be non-deterministic, so ignore the return status. If the test fails
        # when comparing the JSON `export`, the `show` output may be useful when
        # debugging.
        "$(LLVM_BIN_DIR)"/llvm-cov show \
-         --Xdemangler="$(RUST_DEMANGLER)" \
-         --show-line-counts-or-regions \
-         --instr-profile="$(TMPDIR)"/main.profdata \
-               $(call BIN,"$(TMPDIR)"/main) \
+                       --Xdemangler="$(RUST_DEMANGLER)" \
+                       --show-line-counts-or-regions \
+                       --instr-profile="$(TMPDIR)"/testprog.profdata \
+                       $(call BIN,"$(TMPDIR)"/testprog) \
                > "$(TMPDIR)"/actual_show_coverage.txt
 
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/actual_show_coverage.txt typical_show_coverage.txt
+else
        # Compare the show coverage output
        $(DIFF) typical_show_coverage.txt "$(TMPDIR)"/actual_show_coverage.txt || \
-         >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+               >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+endif
 
        # Generate a coverage report in JSON, using `llvm-cov export`, and fail if
        # there are differences from the expected output.
        "$(LLVM_BIN_DIR)"/llvm-cov export \
-         --summary-only \
-         --instr-profile="$(TMPDIR)"/main.profdata \
-               $(call BIN,"$(TMPDIR)"/main) \
+                       --summary-only \
+                       --instr-profile="$(TMPDIR)"/testprog.profdata \
+                       $(call BIN,"$(TMPDIR)"/testprog) \
                | "$(PYTHON)" prettify_json.py \
                > "$(TMPDIR)"/actual_export_coverage.json
 
+ifdef RUSTC_BLESS_TEST
+       cp "$(TMPDIR)"/actual_export_coverage.json expected_export_coverage.json
+else
        # Check that the exported JSON coverage data matches what we expect
        $(DIFF) expected_export_coverage.json "$(TMPDIR)"/actual_export_coverage.json
+endif
index 9d739a89114e2c37f359977e4ca0fb6e9e09df92..5881cf4b7dbbc6eefa64b4f83e9a26b17e1bb830 100644 (file)
@@ -3,7 +3,7 @@
     {
       "files": [
         {
-          "filename": "main.rs",
+          "filename": "testprog.rs",
           "summary": {
             "functions": {
               "count": 7,
diff --git a/src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt b/src/test/run-make-fulldeps/instrument-coverage/filecheck-patterns.txt
new file mode 100644 (file)
index 0000000..5a7cc9a
--- /dev/null
@@ -0,0 +1,51 @@
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Zinstrument-coverage.
+
+WIN32:      $__llvm_profile_runtime_user = comdat any
+
+CHECK:      @__llvm_coverage_mapping = internal constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
+
+WIN32:      @__llvm_profile_runtime = external global i32
+
+CHECK:      @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK:      @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK:      @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK:      @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog4main to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK:      @__llvm_prf_nm = private constant
+CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK:      @llvm.used = appending global
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
+WIN32-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__profd__R{{[a-zA-Z0-9_]*}}testprog4main to i8*)
+CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
+CHECK-SAME: section "llvm.metadata"
+
+CHECK:      define hidden { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT: start:
+CHECK-NOT:  bb{{[0-9]+}}:
+CHECK:      %pgocount = load i64, i64* getelementptr inbounds
+CHECK-SAME: * @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK:      declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WIN32:      define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WIN32-NEXT: %1 = load i32, i32* @__llvm_profile_runtime
+WIN32-NEXT: ret i32 %1
+WIN32-NEXT: }
+
+CHECK:      attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WIN32:      attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
\ No newline at end of file
diff --git a/src/test/run-make-fulldeps/instrument-coverage/main.rs b/src/test/run-make-fulldeps/instrument-coverage/main.rs
deleted file mode 100644 (file)
index 358c256..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-pub fn will_be_called() -> &'static str {
-    let val = "called";
-    println!("{}", val);
-    val
-}
-
-pub fn will_not_be_called() -> bool {
-    println!("should not have been called");
-    false
-}
-
-pub fn print<T>(left: &str, value: T, right: &str)
-where
-    T: std::fmt::Display,
-{
-    println!("{}{}{}", left, value, right);
-}
-
-pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
-where
-    F: FnOnce(&T)
-{
-    if should_wrap {
-        wrapper(&inner)
-    }
-}
-
-fn main() {
-    let less = 1;
-    let more = 100;
-
-    if less < more {
-        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
-        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
-    } else {
-        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
-    }
-}
diff --git a/src/test/run-make-fulldeps/instrument-coverage/testprog.rs b/src/test/run-make-fulldeps/instrument-coverage/testprog.rs
new file mode 100644 (file)
index 0000000..358c256
--- /dev/null
@@ -0,0 +1,38 @@
+pub fn will_be_called() -> &'static str {
+    let val = "called";
+    println!("{}", val);
+    val
+}
+
+pub fn will_not_be_called() -> bool {
+    println!("should not have been called");
+    false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+    T: std::fmt::Display,
+{
+    println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+    F: FnOnce(&T)
+{
+    if should_wrap {
+        wrapper(&inner)
+    }
+}
+
+fn main() {
+    let less = 1;
+    let more = 100;
+
+    if less < more {
+        wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+        wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+    } else {
+        wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+    }
+}
index 9c593d0809d484ce3dfc1cf934148496b1ce8b07..ae123afff04000652fa3feee1e539d007bf267a4 100644 (file)
    25|      2|    }
    26|      2|}
   ------------------
-  | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#0}, &str>:
+  | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#0}, &str>:
   |   22|      1|{
   |   23|      1|    if should_wrap {
   |   24|      1|        wrapper(&inner)
   |   25|      1|    }
   |   26|      1|}
   ------------------
-  | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#1}, &str>:
+  | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#1}, &str>:
   |   22|      1|{
   |   23|      1|    if should_wrap {
   |   24|      1|        wrapper(&inner)
index b11d4c4cab7cf54c5f1f5de18a50cf3b15372149..e72fe5a50913a226f649e4c8ee0a7e69f67719fb 100644 (file)
@@ -1,6 +1,5 @@
 # needs-sanitizer-support
 # needs-sanitizer-address
-# only-linux
 
 -include ../tools.mk
 
index c2ebd2a6d8cacbf49ad9c02f92ec1f3e8252b448..b9a3f829555af02058754178f103053f44b611f6 100644 (file)
@@ -1,6 +1,5 @@
 # needs-sanitizer-support
 # needs-sanitizer-address
-# only-linux
 
 -include ../tools.mk
 
index 5ceff16471cee99fde034adabf0d53e8fadd9eeb..4894f65b114cdd55ffdd74abc77384b2dfe1dd21 100644 (file)
@@ -1,6 +1,5 @@
 # needs-sanitizer-support
 # needs-sanitizer-address
-# only-linux
 
 -include ../tools.mk
 
index 789ab686e3f8e53513294207086475f51e852f93..483eeed0b39f0507eea36248a07d7ac5aadc1c4d 100644 (file)
@@ -1,4 +1,4 @@
-#![ crate_name = "test" ]
+#![crate_name = "test"]
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 #![feature(associated_type_defaults)]
 extern crate krate2 as krate3;
 
 use rustc_graphviz::RenderOption;
-use std::collections::{HashMap,HashSet};
 use std::cell::RefCell;
+use std::collections::{HashMap, HashSet};
 use std::io::Write;
 
-
 use sub::sub2 as msalias;
 use sub::sub2;
 use sub::sub2::nested_struct as sub_struct;
@@ -32,7 +31,7 @@
 // buglink test - see issue #1337.
 
 fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
-    let s = sub_struct{ field2: 45u32, };
+    let s = sub_struct { field2: 45u32 };
 
     // import tests
     fn foo(x: &Write) {}
@@ -82,7 +81,7 @@ pub struct nested_struct {
 
         pub enum nested_enum {
             Nest2 = 2,
-            Nest3 = 3
+            Nest3 = 3,
         }
     }
 }
@@ -103,7 +102,9 @@ struct some_fields {
 type SF = some_fields;
 
 trait SuperTrait {
-    fn qux(&self) { panic!(); }
+    fn qux(&self) {
+        panic!();
+    }
 }
 
 trait SomeTrait: SuperTrait {
@@ -131,8 +132,7 @@ fn Method(&self, x: u32) -> u32 {
     }
 }
 
-impl SuperTrait for some_fields {
-}
+impl SuperTrait for some_fields {}
 
 impl SubTrait for some_fields {}
 
@@ -145,17 +145,14 @@ fn stat2(x: &some_fields) -> u32 {
         42
     }
 
-    fn align_to<T>(&mut self) {
-
-    }
+    fn align_to<T>(&mut self) {}
 
     fn test(&mut self) {
         self.align_to::<bool>();
     }
 }
 
-impl SuperTrait for nofields {
-}
+impl SuperTrait for nofields {}
 impl SomeTrait for nofields {
     fn Method(&self, x: u32) -> u32 {
         self.Method(x);
@@ -181,59 +178,70 @@ enum SomeEnum<'a> {
     Ints(isize, isize),
     Floats(f64, f64),
     Strings(&'a str, &'a str, &'a str),
-    MyTypes(MyType, MyType)
+    MyTypes(MyType, MyType),
 }
 
 #[derive(Copy, Clone)]
 enum SomeOtherEnum {
     SomeConst1,
     SomeConst2,
-    SomeConst3
+    SomeConst3,
 }
 
 enum SomeStructEnum {
-    EnumStruct{a:isize, b:isize},
-    EnumStruct2{f1:MyType, f2:MyType},
-    EnumStruct3{f1:MyType, f2:MyType, f3:SomeEnum<'static>}
+    EnumStruct { a: isize, b: isize },
+    EnumStruct2 { f1: MyType, f2: MyType },
+    EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
 }
 
 fn matchSomeEnum(val: SomeEnum) {
     match val {
-        SomeEnum::Ints(int1, int2) => { println(&(int1+int2).to_string()); }
-        SomeEnum::Floats(float1, float2) => { println(&(float2*float1).to_string()); }
-        SomeEnum::Strings(.., s3) => { println(s3); }
-        SomeEnum::MyTypes(mt1, mt2) => { println(&(mt1.field1 - mt2.field1).to_string()); }
+        SomeEnum::Ints(int1, int2) => {
+            println(&(int1 + int2).to_string());
+        }
+        SomeEnum::Floats(float1, float2) => {
+            println(&(float2 * float1).to_string());
+        }
+        SomeEnum::Strings(.., s3) => {
+            println(s3);
+        }
+        SomeEnum::MyTypes(mt1, mt2) => {
+            println(&(mt1.field1 - mt2.field1).to_string());
+        }
     }
 }
 
 fn matchSomeStructEnum(se: SomeStructEnum) {
     match se {
-        SomeStructEnum::EnumStruct{a:a, ..} => println(&a.to_string()),
-        SomeStructEnum::EnumStruct2{f1:f1, f2:f_2} => println(&f_2.field1.to_string()),
-        SomeStructEnum::EnumStruct3{f1, ..} => println(&f1.field1.to_string()),
+        SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
+        SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
+        SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
     }
 }
 
-
 fn matchSomeStructEnum2(se: SomeStructEnum) {
     use SomeStructEnum::*;
     match se {
-        EnumStruct{a: ref aaa, ..} => println(&aaa.to_string()),
-        EnumStruct2{f1, f2: f2} => println(&f1.field1.to_string()),
-        EnumStruct3{f1, f3: SomeEnum::Ints(..), f2} => println(&f1.field1.to_string()),
-        _ => {},
+        EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
+        EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
+        EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
+        _ => {}
     }
 }
 
 fn matchSomeOtherEnum(val: SomeOtherEnum) {
     use SomeOtherEnum::{SomeConst2, SomeConst3};
     match val {
-        SomeOtherEnum::SomeConst1 => { println("I'm const1."); }
-        SomeConst2 | SomeConst3 => { println("I'm const2 or const3."); }
+        SomeOtherEnum::SomeConst1 => {
+            println("I'm const1.");
+        }
+        SomeConst2 | SomeConst3 => {
+            println("I'm const2 or const3.");
+        }
     }
 }
 
-fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
+fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
     SameDir2::hello(43);
 
     println(&yy.to_string());
@@ -248,8 +256,8 @@ fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
     let x = 32.0f32;
     let _ = (x + ((x * x) + 1.0).sqrt()).ln();
 
-    let s: Box<SomeTrait> = box some_fields {field1: 43};
-    let s2: Box<some_fields> =  box some_fields {field1: 43};
+    let s: Box<SomeTrait> = box some_fields { field1: 43 };
+    let s2: Box<some_fields> = box some_fields { field1: 43 };
     let s3 = box nofields;
 
     s.Method(43);
@@ -302,8 +310,9 @@ macro_rules! internal_vars {
     }
 }
 
-fn main() { // foo
-    let s = box some_fields {field1: 43};
+fn main() {
+    // foo
+    let s = box some_fields { field1: 43 };
     hello((43, "a".to_string()), *s);
     sub::sub2::hello();
     sub2::sub3::hello();
@@ -324,26 +333,24 @@ macro_rules! variable_str(($name:expr) => (
     let vs = variable_str!(32);
 
     let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
-    let _ = blah {
-        used_link_args: RefCell::new([]),
-    };
+    let _ = blah { used_link_args: RefCell::new([]) };
     let s1 = nofields;
-    let s2 = SF { field1: 55};
-    let s3: some_fields = some_fields{ field1: 55};
-    let s4: msalias::nested_struct = sub::sub2::nested_struct{ field2: 55};
-    let s4: msalias::nested_struct = sub2::nested_struct{ field2: 55};
+    let s2 = SF { field1: 55 };
+    let s3: some_fields = some_fields { field1: 55 };
+    let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
+    let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
     println(&s2.field1.to_string());
-    let s5: MyType = box some_fields{ field1: 55};
-    let s = SameDir::SameStruct{name: "Bob".to_string()};
-    let s = SubDir::SubStruct{name:"Bob".to_string()};
+    let s5: MyType = box some_fields { field1: 55 };
+    let s = SameDir::SameStruct { name: "Bob".to_string() };
+    let s = SubDir::SubStruct { name: "Bob".to_string() };
     let s6: SomeEnum = SomeEnum::MyTypes(box s2.clone(), s5);
     let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
     matchSomeEnum(s6);
     matchSomeEnum(s7);
     let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
     matchSomeOtherEnum(s8);
-    let s9: SomeStructEnum = SomeStructEnum::EnumStruct2{ f1: box some_fields{ field1:10 },
-                                                          f2: box s2 };
+    let s9: SomeStructEnum =
+        SomeStructEnum::EnumStruct2 { f1: box some_fields { field1: 10 }, f2: box s2 };
     matchSomeStructEnum(s9);
 
     for x in &vec![1, 2, 3] {
@@ -404,8 +411,7 @@ impl<'a> Pattern<'a> for CharEqPattern {
 
 struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
 
-pub trait Error {
-}
+pub trait Error {}
 
 impl Error + 'static {
     pub fn is<T: Error + 'static>(&self) -> bool {
@@ -419,8 +425,7 @@ pub fn is<T: Error + 'static>(&self) -> bool {
     }
 }
 extern crate rustc_serialize;
-#[derive(Clone, Copy, Hash, RustcEncodable, RustcDecodable,
-         PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
+#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
 struct AllDerives(i32);
 
 fn test_format_args() {
@@ -433,9 +438,8 @@ fn test_format_args() {
     print!("x is {}, y is {1}, name is {n}", x, y, n = name);
 }
 
-
 union TestUnion {
-    f1: u32
+    f1: u32,
 }
 
 struct FrameBuffer;
@@ -454,5 +458,5 @@ trait Foo {
     type Bar = FrameBuffer;
 }
 
-#[doc(include="extra-docs.md")]
+#[doc(include = "extra-docs.md")]
 struct StructWithDocs;
diff --git a/src/test/ui-fulldeps/derive-no-std-not-supported.rs b/src/test/ui-fulldeps/derive-no-std-not-supported.rs
deleted file mode 100644 (file)
index 1299d82..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![feature(rustc_private)]
-#![no_std]
-
-extern crate rustc_serialize;
-
-#[derive(RustcEncodable)]
-struct Bar {
-    x: u32,
-}
-
-#[derive(RustcDecodable)]
-struct Baz {
-    x: u32,
-}
-
-fn main() {
-    Bar { x: 0 };
-    Baz { x: 0 };
-}
index 2b349ae9556c3bf6aa02eee4ae386fde9598ee17..119fa3d6fa8efcf9ad60ab93805879dce4061812 100644 (file)
@@ -1,16 +1,17 @@
 // run-pass
 
 #![allow(unused_imports)]
-
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 struct A {
     foo: Box<[bool]>,
 }
index c2aecbdc16793342e10ce43114ed86a58bffc9b6..9dedf990f25ece259c2f8925cd78ab6a28fe8555 100644 (file)
@@ -3,32 +3,29 @@
 #![allow(unused_imports)]
 // This briefly tests the capability of `Cell` and `RefCell` to implement the
 // `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]`
-
-
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
-use std::cell::{Cell, RefCell};
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
+use std::cell::{Cell, RefCell};
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 struct A {
-    baz: isize
+    baz: isize,
 }
 
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
 struct B {
     foo: Cell<bool>,
     bar: RefCell<A>,
 }
 
 fn main() {
-    let obj = B {
-        foo: Cell::new(true),
-        bar: RefCell::new( A { baz: 2 } )
-    };
+    let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
     let s = json::encode(&obj).unwrap();
     let obj2: B = json::decode(&s).unwrap();
     assert_eq!(obj.foo.get(), obj2.foo.get());
index 5ba34a7af6bf53337e7578f1ab9cf6ac7539c446..921767af981ad6e10062da418868ba91ad99a3c9 100644 (file)
@@ -2,33 +2,29 @@
 
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
 mod submod {
+    use rustc_macros::{Decodable, Encodable};
+
     // if any of these are implemented without global calls for any
     // function calls, then being in a submodule will (correctly)
     // cause errors about unrecognised module `std` (or `extra`)
-    #[derive(PartialEq, PartialOrd, Eq, Ord,
-               Hash,
-               Clone,
-               Debug,
-               RustcEncodable, RustcDecodable)]
-    enum A { A1(usize), A2(isize) }
+    #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
+    enum A {
+        A1(usize),
+        A2(isize),
+    }
 
-    #[derive(PartialEq, PartialOrd, Eq, Ord,
-               Hash,
-               Clone,
-               Debug,
-               RustcEncodable, RustcDecodable)]
-    struct B { x: usize, y: isize }
+    #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
+    struct B {
+        x: usize,
+        y: isize,
+    }
 
-    #[derive(PartialEq, PartialOrd, Eq, Ord,
-               Hash,
-               Clone,
-               Debug,
-               RustcEncodable, RustcDecodable)]
+    #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
     struct C(usize, isize);
-
 }
 
 pub fn main() {}
index 85ef217e7671e490bfc7ec5977b291e62202f2b9..8486b8b6e481a3e300696e90f800fd962100a0cc 100644 (file)
@@ -2,8 +2,11 @@
 
 #![allow(non_upper_case_globals)]
 #![feature(rustc_private)]
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
+use rustc_macros::{Decodable, Encodable};
+
 pub const other: u8 = 1;
 pub const f: u8 = 1;
 pub const d: u8 = 1;
@@ -11,8 +14,7 @@
 pub const state: u8 = 1;
 pub const cmp: u8 = 1;
 
-#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,RustcDecodable,RustcEncodable,Hash)]
+#[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)]
 struct Foo {}
 
-fn main() {
-}
+fn main() {}
index fc85765eea4a53af898cbd706d7a08b679cd9d96..6e5eb54629ccde87b9ce5437b39fd819197e2657 100644 (file)
@@ -3,18 +3,18 @@
 
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
-         Default, Debug, RustcEncodable, RustcDecodable)]
+use rustc_macros::{Decodable, Encodable};
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
 struct S {}
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
-         Default, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
 struct Z();
 
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
-         Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 enum E {
     V {},
     U,
index 7b0abba4d16c80e09077a04f9548970b1653dd05..6d64aeeda7e117ce26ca4227b4ebfb52f2acc35a 100644 (file)
@@ -3,26 +3,27 @@
 #![allow(unused_must_use)]
 #![allow(dead_code)]
 #![allow(unused_imports)]
-
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
-use std::io::Cursor;
-use std::io::prelude::*;
 use std::fmt;
+use std::io::prelude::*;
+use std::io::Cursor;
 use std::slice;
 
-use rustc_serialize::{Encodable, Encoder};
+use rustc_macros::Encodable;
 use rustc_serialize::json;
 use rustc_serialize::opaque;
+use rustc_serialize::{Encodable, Encoder};
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct Foo {
     baz: bool,
 }
 
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
 struct Bar {
     froboz: usize,
 }
@@ -33,19 +34,19 @@ enum WireProtocol {
     // ...
 }
 
-fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
+fn encode_json<T: for<'a> Encodable<json::Encoder<'a>>>(val: &T, wr: &mut Cursor<Vec<u8>>) {
     write!(wr, "{}", json::as_json(val));
 }
-fn encode_opaque<T: Encodable>(val: &T, wr: Vec<u8>) {
+fn encode_opaque<T: Encodable<opaque::Encoder>>(val: &T, wr: Vec<u8>) {
     let mut encoder = opaque::Encoder::new(wr);
     val.encode(&mut encoder);
 }
 
 pub fn main() {
-    let target = Foo{baz: false,};
+    let target = Foo { baz: false };
     let proto = WireProtocol::JSON;
     match proto {
         WireProtocol::JSON => encode_json(&target, &mut Cursor::new(Vec::new())),
-        WireProtocol::Opaque => encode_opaque(&target, Vec::new())
+        WireProtocol::Opaque => encode_opaque(&target, Vec::new()),
     }
 }
index 1898b12c70385db118de60c15cf0d429532c92cf..be88a593962cc0f969c7b88e584b52744eb90e17 100644 (file)
@@ -4,12 +4,14 @@
 #![allow(unused_imports)]
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 extern crate rustc_serialize;
 
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
 use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+#[derive(Encodable, Decodable, PartialEq, Debug)]
 struct UnitLikeStruct;
 
 pub fn main() {
index e3d4b0eb4460d5815f4351bb8a0f611d77ef1e67..5adc2c482f5e8977d55ccd1fda82aaad09e214e0 100644 (file)
@@ -3,20 +3,19 @@
 #![allow(unused_imports)]
 #![allow(unused_must_use)]
 // pretty-expanded FIXME #23616
-
 #![feature(rustc_private)]
 
 extern crate rustc_serialize;
 
-use std::fmt;
-use rustc_serialize::{Encoder, Encodable};
 use rustc_serialize::json;
+use rustc_serialize::{Encodable, Encoder};
+use std::fmt;
 
-struct Foo<T: Encodable> {
+struct Foo<T: for<'a> Encodable<json::Encoder<'a>>> {
     v: T,
 }
 
-impl<T: Encodable> Drop for Foo<T> {
+impl<T: for<'a> Encodable<json::Encoder<'a>>> Drop for Foo<T> {
     fn drop(&mut self) {
         json::encode(&self.v);
     }
index 51e134fbf88719be0e656dc9f734118f264c9e95..044a0c5000e31a80308eb120cdf82861e9880742 100644 (file)
@@ -5,11 +5,18 @@
 
 extern crate rustc_serialize;
 
-use rustc_serialize::{Encodable, Decodable};
+use rustc_serialize::{json, Decodable, Encodable};
 use std::fmt::Display;
 
-pub trait Entity : Decodable + Encodable + Sized {
-    type Key: Clone + Decodable + Encodable + ToString + Display + Eq + Ord + Sized;
+pub trait Entity: Decodable<json::Decoder> + for<'a> Encodable<json::Encoder<'a>> + Sized {
+    type Key: Clone
+        + Decodable<json::Decoder>
+        + for<'a> Encodable<json::Encoder<'a>>
+        + ToString
+        + Display
+        + Eq
+        + Ord
+        + Sized;
 
     fn id(&self) -> Self::Key;
 
@@ -20,7 +27,10 @@ pub struct DbRef<E: Entity> {
     pub id: E::Key,
 }
 
-impl<E> DbRef<E> where E: Entity {
+impl<E> DbRef<E>
+where
+    E: Entity,
+{
     fn get(self) -> Option<E> {
         E::find_by_id(self.id)
     }
index 96157c2f426c0d876d37946a27401a30ea3f2a6a..4fd192497a0a322965a6aa40fb908a811d49ad92 100644 (file)
@@ -1,14 +1,13 @@
 // run-pass
 
 #![allow(dead_code)]
-
 #![feature(rustc_private)]
 
 extern crate rustc_serialize;
 
 use rustc_serialize::{json, Decodable};
 
-trait JD : Decodable {}
+trait JD: Decodable<json::Decoder> {}
 
 fn exec<T: JD>() {
     let doc = json::from_str("").unwrap();
index b49135cb60b2946a2f64b397f6f66b788445e650..452110a65e4aa18ac966be2213c89c5b4a921696 100644 (file)
@@ -2,11 +2,13 @@
 
 #![feature(rustc_private)]
 
+extern crate rustc_macros;
 #[allow(dead_code)]
-
 extern crate rustc_serialize;
 
-#[derive(RustcDecodable, RustcEncodable,Debug)]
+use rustc_macros::{Decodable, Encodable};
+
+#[derive(Decodable, Encodable, Debug)]
 struct A {
     a: String,
 }
index f9951170acd665f2c88c90e20f1c93ed98805c72..49003c74450f1aee25b22f20d5b0514329611365 100644 (file)
@@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/missing-associated-types.rs:12:32
    |
 LL | type Foo<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Y<Rhs>;
-   |                     --------   ^^^^^^^^
-   |                     |          |
-   |                     |          additional non-auto trait
-   |                     |          trait alias used in trait object type (additional use)
+   |                     --------   ^^^^^^^^ additional non-auto trait
+   |                     |
    |                     first non-auto trait
-   |                     trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Y<Rhs> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
   --> $DIR/missing-associated-types.rs:12:21
@@ -31,12 +31,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/missing-associated-types.rs:15:32
    |
 LL | type Bar<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Z<Rhs>;
-   |                     --------   ^^^^^^^^
-   |                     |          |
-   |                     |          additional non-auto trait
-   |                     |          trait alias used in trait object type (additional use)
+   |                     --------   ^^^^^^^^ additional non-auto trait
+   |                     |
    |                     first non-auto trait
-   |                     trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Z<Rhs> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from trait `Z`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
   --> $DIR/missing-associated-types.rs:15:21
@@ -67,12 +67,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/missing-associated-types.rs:18:32
    |
 LL | type Baz<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Y<Rhs>;
-   |                     --------   ^^^^^^^^
-   |                     |          |
-   |                     |          additional non-auto trait
-   |                     |          trait alias used in trait object type (additional use)
+   |                     --------   ^^^^^^^^ additional non-auto trait
+   |                     |
    |                     first non-auto trait
-   |                     trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Y<Rhs> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
   --> $DIR/missing-associated-types.rs:18:21
@@ -95,12 +95,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/missing-associated-types.rs:21:32
    |
 LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
-   |                     --------   ^^^^^^^^
-   |                     |          |
-   |                     |          additional non-auto trait
-   |                     |          trait alias used in trait object type (additional use)
+   |                     --------   ^^^^^^^^ additional non-auto trait
+   |                     |
    |                     first non-auto trait
-   |                     trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Fine<Rhs> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0191]: the value of the associated types `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
   --> $DIR/missing-associated-types.rs:21:21
index c7b0fbeb0e39bcc819fc0cf305b36a576af10396..d0942f78bb86c7ec73caea9beb17ad804813b403 100644 (file)
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
index 59ed68c2a773fba2dfc0e22cb0da1b4ba5eb72ef..dc06fd74a4bb55a3468f17a68780e023f2a8a3b1 100644 (file)
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
index 90edbe2de6bff0bb733e408561fa483b01e4d5a1..93984f1c372fa8ef0dfde0acbef52d76e6e94458 100644 (file)
@@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/bad-sized.rs:4:28
    |
 LL |     let x: Vec<dyn Trait + Sized> = Vec::new();
-   |                    -----   ^^^^^
-   |                    |       |
-   |                    |       additional non-auto trait
-   |                    |       trait alias used in trait object type (additional use)
+   |                    -----   ^^^^^ additional non-auto trait
+   |                    |
    |                    first non-auto trait
-   |                    trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Trait + std::marker::Sized {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
   --> $DIR/bad-sized.rs:4:12
index f9c6e201b1762dfe0d6a65e3764c271c92ffea18..facc0bcf5130cbec26a14771efe01117b0b36315 100644 (file)
@@ -1,7 +1,9 @@
 // check-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 trait Trait {}
 
diff --git a/src/test/ui/const-generics/apit-with-const-param.stderr b/src/test/ui/const-generics/apit-with-const-param.stderr
deleted file mode 100644 (file)
index 4389e47..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/apit-with-const-param.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr
new file mode 100644 (file)
index 0000000..cf4487b
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:9:38
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                      ^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:20:10
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |          ^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
new file mode 100644 (file)
index 0000000..61d2347
--- /dev/null
@@ -0,0 +1,27 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/array-size-in-generic-struct-param.rs:9:48
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                                ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/array-size-in-generic-struct-param.rs:20:15
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |               ^^^ non-trivial anonymous constants must not depend on the parameter `CFG`
+   |
+   = help: it is currently only allowed to use either `CFG` or `{ CFG }` as generic constants
+
+error: using `Config` as const generic parameters is forbidden
+  --> $DIR/array-size-in-generic-struct-param.rs:18:21
+   |
+LL | struct B<const CFG: Config> {
+   |                     ^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 3 previous errors
+
index 5c02e585dc8ba1270a9330c4e3ff07da1ee714ad..aa1a3b9cf28889dd13c7971671978c196831fe31 100644 (file)
@@ -1,9 +1,14 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #[allow(dead_code)]
 struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-//~^ ERROR constant expression depends on a generic parameter
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
 
 #[derive(PartialEq, Eq)]
 struct Config {
@@ -11,7 +16,10 @@ struct Config {
 }
 
 struct B<const CFG: Config> {
-    arr: [u8; CFG.arr_size], //~ ERROR constant expression depends on a generic parameter
+    //[min]~^ ERROR using `Config` as const generic parameters is forbidden
+    arr: [u8; CFG.arr_size],
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial
 }
 
 const C: Config = Config { arr_size: 5 };
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr
deleted file mode 100644 (file)
index ad67a87..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/array-size-in-generic-struct-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
-  --> $DIR/array-size-in-generic-struct-param.rs:5:38
-   |
-LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-   |                                      ^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/array-size-in-generic-struct-param.rs:14:10
-   |
-LL |     arr: [u8; CFG.arr_size],
-   |          ^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
index f137be2d6a6faf97e594df1c0b71ae552c830ba8..d13ae12c03bc2fbd599499c241e9aad7628a87bf 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub trait Foo {
     fn foo(&self);
diff --git a/src/test/ui/const-generics/broken-mir-1.stderr b/src/test/ui/const-generics/broken-mir-1.stderr
deleted file mode 100644 (file)
index a5532bd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/broken-mir-1.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 2cd035639ee5cca80eb7d322b95638e1c71d560f..2f9afe0b46433c821dadd52b0d7d59deb90209ba 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 use std::fmt::Debug;
 
diff --git a/src/test/ui/const-generics/broken-mir-2.stderr b/src/test/ui/const-generics/broken-mir-2.stderr
deleted file mode 100644 (file)
index c36ef84..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/broken-mir-2.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/cannot-infer-const-args.full.stderr
new file mode 100644 (file)
index 0000000..0531397
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-const-args.rs:12:5
+   |
+LL |     foo();
+   |     ^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/cannot-infer-const-args.min.stderr
new file mode 100644 (file)
index 0000000..0531397
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-const-args.rs:12:5
+   |
+LL |     foo();
+   |     ^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
index 2f6ad2654c12c4dfda97f22e6497bb6c9f704d8d..2d74b4788bf4b61c4eab058198a1f4930bfcc891 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn foo<const X: usize>() -> usize {
     0
diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr
deleted file mode 100644 (file)
index b29d27e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/cannot-infer-const-args.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-const-args.rs:9:5
-   |
-LL |     foo();
-   |     ^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0282`.
index b28768a5163ddf655cedc60f485984084e93d05e..a3c295f73c7eadc2ec6c20fe5ea254778935446f 100644 (file)
@@ -1,6 +1,9 @@
 // run-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn foo<const N: usize>(v: &[u8; N]) -> &[u8] {
     v
index 18ebba49f6f91e0cc3aaeb51c47afdcbf83cd3d8..7771bf336016a466c36aad7dad9ea18c6adb4212 100644 (file)
@@ -1,8 +1,10 @@
 // Test that a concrete const type i.e. A<2>, can be used as an argument type in a function
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct A<const N: usize>; // ok
 
diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr
deleted file mode 100644 (file)
index c8f3a8b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/concrete-const-as-fn-arg.rs:4:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index c1ddf9a33140d63260398799cbda052925238e68..edb403ce8fd667cb6367cc0195a8ec8ac875e7b2 100644 (file)
@@ -1,9 +1,11 @@
 // Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>,
 // is callable.
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub struct A<const N: u32>;
 
diff --git a/src/test/ui/const-generics/concrete-const-impl-method.stderr b/src/test/ui/const-generics/concrete-const-impl-method.stderr
deleted file mode 100644 (file)
index 5edb4f4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/concrete-const-impl-method.rs:5:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 9d8aaed54bd75896f3074bf2b50eb401624774b3..77b68052fc0bb226ec323407e109a7fb164628e4 100644 (file)
@@ -1,7 +1,10 @@
+// Checks that `impl Trait<{anon_const}> for Type` evaluates successfully.
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 trait IsZeroTrait<const IS_ZERO: bool>{}
 
diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr
deleted file mode 100644 (file)
index 9ac3345..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/condition-in-trait-const-arg.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 5ea2cf92fdc6084f034cfcf905ab73f30d5ee9ed..5c438efd82a0c1a46e62f1ad7eb4a5c7ce70f4c5 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn const_u32_identity<const X: u32>() -> u32 {
     X
diff --git a/src/test/ui/const-generics/const-arg-in-fn.stderr b/src/test/ui/const-generics/const-arg-in-fn.stderr
deleted file mode 100644 (file)
index bb66849..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-arg-in-fn.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index bc09ba2ab553bbec5fb1cfbef12a853c9a22344a..dc34621b90500f16365402a274cc6cf04a09e924 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full
+// FIXME(#75323) Omitted min revision for now due to ICE.
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
 #![allow(dead_code)]
 
 fn test<const N: usize>() {}
diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr b/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr
deleted file mode 100644 (file)
index 53a7550..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-argument-non-static-lifetime.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/const-expression-parameter.full.stderr b/src/test/ui/const-generics/const-expression-parameter.full.stderr
new file mode 100644 (file)
index 0000000..496af9c
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `,` or `>`, found `+`
+  --> $DIR/const-expression-parameter.rs:16:22
+   |
+LL |     i32_identity::<1 + 2>();
+   |                      ^ expected one of `,` or `>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/const-expression-parameter.min.stderr b/src/test/ui/const-generics/const-expression-parameter.min.stderr
new file mode 100644 (file)
index 0000000..496af9c
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `,` or `>`, found `+`
+  --> $DIR/const-expression-parameter.rs:16:22
+   |
+LL |     i32_identity::<1 + 2>();
+   |                      ^ expected one of `,` or `>`
+
+error: aborting due to previous error
+
index e0b66a7c14c3aafbdb24e73323e468193189903f..7a1eaf9f939084263d240594c7d72f8ab9e44c92 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn i32_identity<const X: i32>() -> i32 {
     5
diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr
deleted file mode 100644 (file)
index e421c22..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error: expected one of `,` or `>`, found `+`
-  --> $DIR/const-expression-parameter.rs:13:22
-   |
-LL |     i32_identity::<1 + 2>();
-   |                      ^ expected one of `,` or `>`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-expression-parameter.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
-
index bbc55815e9a208b77fe4cd906f49f21f470257d4..add1290b1d9758a6fcb0235d686c4d1d04ab008e 100644 (file)
@@ -1,6 +1,10 @@
+// Checks that `const fn` with const params can be used.
 // run-pass
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 const fn const_u32_identity<const X: u32>() -> u32 {
     X
diff --git a/src/test/ui/const-generics/const-fn-with-const-param.stderr b/src/test/ui/const-generics/const-fn-with-const-param.stderr
deleted file mode 100644 (file)
index 109b500..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-fn-with-const-param.rs:2:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 3e43387163b62da5b680a3bd8ba2ec4aa3a6a2a3..34edd0b4a8e870f86a8a3c55f89df476b38214d0 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Foo<T, const N: usize>([T; N]);
 
diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.stderr b/src/test/ui/const-generics/const-generic-array-wrapper.stderr
deleted file mode 100644 (file)
index 47448bb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-generic-array-wrapper.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 22f9bd2a0f0b2556c318d86bd1af5c1f6e32b7a6..a954c0263521695593882ff40c83ae28a8c6d611 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #[derive(Debug)]
 struct S<const N: usize>;
diff --git a/src/test/ui/const-generics/const-generic-type_name.stderr b/src/test/ui/const-generics/const-generic-type_name.stderr
deleted file mode 100644 (file)
index f161739..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-generic-type_name.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 19c4120eb2f148eb24dda3e0f8227b26cf8f3474..3982f7a7f125cc32feff0ba09995c20c3f00548f 100644 (file)
@@ -1,7 +1,9 @@
 // check-pass
+// revisions: full min
 
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Foo<const A: usize, const B: usize>;
 
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.full.stderr
new file mode 100644 (file)
index 0000000..aa29d61
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:11:19
+   |
+LL | struct A<const N: &u8>;
+   |                   ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:16:15
+   |
+LL | impl<const N: &u8> A<N> {
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:19:21
+   |
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:24:15
+   |
+LL | impl<const N: &u8> B for A<N> {}
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:28:17
+   |
+LL | fn bar<const N: &u8>() {}
+   |                 ^ explicit lifetime name needed here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
new file mode 100644 (file)
index 0000000..bdd1da9
--- /dev/null
@@ -0,0 +1,78 @@
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:11:19
+   |
+LL | struct A<const N: &u8>;
+   |                   ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:16:15
+   |
+LL | impl<const N: &u8> A<N> {
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:19:21
+   |
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:24:15
+   |
+LL | impl<const N: &u8> B for A<N> {}
+   |               ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/const-param-elided-lifetime.rs:28:17
+   |
+LL | fn bar<const N: &u8>() {}
+   |                 ^ explicit lifetime name needed here
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/const-param-elided-lifetime.rs:11:19
+   |
+LL | struct A<const N: &u8>;
+   |                   ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/const-param-elided-lifetime.rs:16:15
+   |
+LL | impl<const N: &u8> A<N> {
+   |               ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/const-param-elided-lifetime.rs:24:15
+   |
+LL | impl<const N: &u8> B for A<N> {}
+   |               ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/const-param-elided-lifetime.rs:28:17
+   |
+LL | fn bar<const N: &u8>() {}
+   |                 ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/const-param-elided-lifetime.rs:19:21
+   |
+LL |     fn foo<const M: &u8>(&self) {}
+   |                     ^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
index 5e6b6c4dabe0238210a203d8db01e5b1d6af433b..814b71d4b741f8e5fcf8359223c70773d51d8956 100644 (file)
@@ -2,23 +2,31 @@
 // behaviour of trait bounds where `fn foo<T: Ord<&u8>>() {}` is illegal. Though we could change
 // elided lifetimes within the type of a const generic parameters to be 'static, like elided
 // lifetimes within const/static items.
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct A<const N: &u8>;
 //~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
 trait B {}
 
-impl<const N: &u8> A<N> { //~ ERROR `&` without an explicit lifetime name cannot be used here
+impl<const N: &u8> A<N> {
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
     fn foo<const M: &u8>(&self) {}
     //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
 }
 
 impl<const N: &u8> B for A<N> {}
 //~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
 
 fn bar<const N: &u8>() {}
 //~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.stderr
deleted file mode 100644 (file)
index 8c50fb7..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:9:19
-   |
-LL | struct A<const N: &u8>;
-   |                   ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:13:15
-   |
-LL | impl<const N: &u8> A<N> {
-   |               ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:14:21
-   |
-LL |     fn foo<const M: &u8>(&self) {}
-   |                     ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:18:15
-   |
-LL | impl<const N: &u8> B for A<N> {}
-   |               ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:21:17
-   |
-LL | fn bar<const N: &u8>() {}
-   |                 ^ explicit lifetime name needed here
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-param-elided-lifetime.rs:6:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 5 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0637`.
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr
new file mode 100644 (file)
index 0000000..5a126f5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/const-param-from-outer-fn.rs:9:9
+   |
+LL | fn foo<const X: u32>() {
+   |              - const parameter from outer function
+LL |     fn bar() -> u32 {
+   |        --- try adding a local generic parameter in this method instead
+LL |         X
+   |         ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr
new file mode 100644 (file)
index 0000000..5a126f5
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/const-param-from-outer-fn.rs:9:9
+   |
+LL | fn foo<const X: u32>() {
+   |              - const parameter from outer function
+LL |     fn bar() -> u32 {
+   |        --- try adding a local generic parameter in this method instead
+LL |         X
+   |         ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
index 4b8e2db7233e4bd2a3eef99fcdad9cbadfac69d7..e1376c6e108b8fc776091d3f6c11e560f08c41d7 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn foo<const X: u32>() {
     fn bar() -> u32 {
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.stderr
deleted file mode 100644 (file)
index 30bd1d7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/const-param-from-outer-fn.rs:6:9
-   |
-LL | fn foo<const X: u32>() {
-   |              - const parameter from outer function
-LL |     fn bar() -> u32 {
-   |        --- try adding a local generic parameter in this method instead
-LL |         X
-   |         ^ use of generic parameter from outer function
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-param-from-outer-fn.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0401`.
index 6874072571108b8a8f9c6dfcff85b046064ddc25..9d31162c1c6f4ec6672fc09fc7280c55a451ad06 100644 (file)
@@ -1,8 +1,12 @@
+// Check that const parameters are permitted in traits.
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
-trait Trait<const T: ()> {}
+
+trait Trait<const T: u8> {}
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-in-trait.stderr b/src/test/ui/const-generics/const-param-in-trait.stderr
deleted file mode 100644 (file)
index a2e367b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-param-in-trait.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.full.stderr
new file mode 100644 (file)
index 0000000..f7ad579
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:12:52
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                                    ^ the type must not depend on the parameter `N`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:16:40
+   |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+   |                                        ^ the type must not depend on the parameter `N`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
new file mode 100644 (file)
index 0000000..103f4c3
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:12:52
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                                    ^ the type must not depend on the parameter `N`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-const-param.rs:16:40
+   |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+   |                                        ^ the type must not depend on the parameter `N`
+
+error: using `[u8; _]` as const generic parameters is forbidden
+  --> $DIR/const-param-type-depends-on-const-param.rs:12:47
+   |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+   |                                               ^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `[u8; _]` as const generic parameters is forbidden
+  --> $DIR/const-param-type-depends-on-const-param.rs:16:35
+   |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+   |                                   ^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
index 5aa3617d1d7e03cfad9bca418e47bda023a0edb4..d21a7cec117ee43cd4f7175a9a3f5678db3b340d 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 // Currently, const parameters cannot depend on other generic parameters,
 // as our current implementation can't really support this.
@@ -8,8 +11,10 @@
 
 pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
 //~^ ERROR: the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
 
 pub struct SelfDependent<const N: [u8; N]>;
 //~^ ERROR: the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr
deleted file mode 100644 (file)
index f6606ae..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/const-param-type-depends-on-const-param.rs:9:52
-   |
-LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
-   |                                                    ^ the type must not depend on the parameter `N`
-
-error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/const-param-type-depends-on-const-param.rs:12:40
-   |
-LL | pub struct SelfDependent<const N: [u8; N]>;
-   |                                        ^ the type must not depend on the parameter `N`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-param-type-depends-on-const-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0770`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.full.stderr
new file mode 100644 (file)
index 0000000..ba99c87
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:12:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                                  ^ the type must not depend on the parameter `T`
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:12:22
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                      ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.min.stderr
new file mode 100644 (file)
index 0000000..ba99c87
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0770]: the type of const parameters must not depend on other generic parameters
+  --> $DIR/const-param-type-depends-on-type-param.rs:12:34
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                                  ^ the type must not depend on the parameter `T`
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/const-param-type-depends-on-type-param.rs:12:22
+   |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+   |                      ^ unused parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
index 7fe04a43412a1edd26c4f33e141083bc7525e168..93ae111751236431243c4f7353fed704368d6676 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 // Currently, const parameters cannot depend on other generic parameters,
 // as our current implementation can't really support this.
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr
deleted file mode 100644 (file)
index d081dcb..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:34
-   |
-LL | pub struct Dependent<T, const X: T>([(); X]);
-   |                                  ^ the type must not depend on the parameter `T`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-param-type-depends-on-type-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0392]: parameter `T` is never used
-  --> $DIR/const-param-type-depends-on-type-param.rs:9:22
-   |
-LL | pub struct Dependent<T, const X: T>([(); X]);
-   |                      ^ unused parameter
-   |
-   = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-Some errors have detailed explanations: E0392, E0770.
-For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr
new file mode 100644 (file)
index 0000000..0f4f007
--- /dev/null
@@ -0,0 +1,14 @@
+error: const parameter `x` should have an upper case name
+  --> $DIR/const-parameter-uppercase-lint.rs:9:15
+   |
+LL | fn noop<const x: u32>() {
+   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
+   |
+note: the lint level is defined here
+  --> $DIR/const-parameter-uppercase-lint.rs:7:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr
new file mode 100644 (file)
index 0000000..0f4f007
--- /dev/null
@@ -0,0 +1,14 @@
+error: const parameter `x` should have an upper case name
+  --> $DIR/const-parameter-uppercase-lint.rs:9:15
+   |
+LL | fn noop<const x: u32>() {
+   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
+   |
+note: the lint level is defined here
+  --> $DIR/const-parameter-uppercase-lint.rs:7:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index 54a33e2181284224e7a905f9f45657927e3435ae..b9bd6666af39d06bde3500d52675776e553bbf16 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #![deny(non_upper_case_globals)]
 
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
deleted file mode 100644 (file)
index b7febed..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-parameter-uppercase-lint.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: const parameter `x` should have an upper case name
-  --> $DIR/const-parameter-uppercase-lint.rs:6:15
-   |
-LL | fn noop<const x: u32>() {
-   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
-   |
-note: the lint level is defined here
-  --> $DIR/const-parameter-uppercase-lint.rs:4:9
-   |
-LL | #![deny(non_upper_case_globals)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
index bde80f4a1ed0948d23705b192ec14e0a2822535c..cd34cfc0478c7b255d95b221eff644558fbeb6c0 100644 (file)
@@ -1,7 +1,10 @@
+// Check that arrays can be used with generic const and type.
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #![allow(dead_code, unused_variables)]
 
diff --git a/src/test/ui/const-generics/const-types.stderr b/src/test/ui/const-generics/const-types.stderr
deleted file mode 100644 (file)
index 4628c90..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/const-types.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 36272ae86199d68808dd29390d2bf95e7e786ea3..13fd87f1e3e574a565606e9ff5be2022d96c69fd 100644 (file)
@@ -1,7 +1,10 @@
+// Check that deriving debug on struct with const is permitted.
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #[derive(Debug)]
 struct X<const N: usize> {
diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr
deleted file mode 100644 (file)
index 8f7ab82..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/derive-debug-array-wrapper.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/different_byref.full.stderr b/src/test/ui/const-generics/different_byref.full.stderr
new file mode 100644 (file)
index 0000000..4463ed7
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_byref.rs:13:9
+   |
+LL |     x = Const::<{ [4] }> {};
+   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected type `[3_usize]`
+              found type `[4_usize]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr
new file mode 100644 (file)
index 0000000..7704911
--- /dev/null
@@ -0,0 +1,11 @@
+error: using `[usize; 1]` as const generic parameters is forbidden
+  --> $DIR/different_byref.rs:8:23
+   |
+LL | struct Const<const V: [usize; 1]> {}
+   |                       ^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
index 78964eb3dee6e781d21857ba721b8415f3d4e567..ec85ed775d4f5debdc24da912e4ac961f36c10c9 100644 (file)
@@ -1,11 +1,15 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Check that different const types are different.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Const<const V: [usize; 1]> {}
+//[min]~^ using `[usize; 1]` as const generic parameters is forbidden
 
 fn main() {
     let mut x = Const::<{ [3] }> {};
     x = Const::<{ [4] }> {};
-    //~^ ERROR mismatched types
-
+    //[full]~^ ERROR mismatched types
 }
diff --git a/src/test/ui/const-generics/different_byref.stderr b/src/test/ui/const-generics/different_byref.stderr
deleted file mode 100644 (file)
index a3f331e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/different_byref.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0308]: mismatched types
-  --> $DIR/different_byref.rs:8:9
-   |
-LL |     x = Const::<{ [4] }> {};
-   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
-   |
-   = note: expected type `[3_usize]`
-              found type `[4_usize]`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref_simple.full.stderr b/src/test/ui/const-generics/different_byref_simple.full.stderr
new file mode 100644 (file)
index 0000000..b6729c8
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_byref_simple.rs:12:9
+   |
+LL |     u = ConstUsize::<4> {};
+   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected struct `ConstUsize<3_usize>`
+              found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref_simple.min.stderr b/src/test/ui/const-generics/different_byref_simple.min.stderr
new file mode 100644 (file)
index 0000000..b6729c8
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_byref_simple.rs:12:9
+   |
+LL |     u = ConstUsize::<4> {};
+   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected struct `ConstUsize<3_usize>`
+              found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref_simple.rs b/src/test/ui/const-generics/different_byref_simple.rs
new file mode 100644 (file)
index 0000000..93289f9
--- /dev/null
@@ -0,0 +1,14 @@
+// Check that different const types are different.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct ConstUsize<const V: usize> {}
+
+fn main() {
+    let mut u = ConstUsize::<3> {};
+    u = ConstUsize::<4> {};
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/fn-const-param-call.full.stderr b/src/test/ui/const-generics/fn-const-param-call.full.stderr
new file mode 100644 (file)
index 0000000..f1bd8de
--- /dev/null
@@ -0,0 +1,14 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:12:25
+   |
+LL | struct Wrapper<const F: fn() -> u32>;
+   |                         ^^^^^^^^^^^
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:14:15
+   |
+LL | impl<const F: fn() -> u32> Wrapper<F> {
+   |               ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/fn-const-param-call.min.stderr b/src/test/ui/const-generics/fn-const-param-call.min.stderr
new file mode 100644 (file)
index 0000000..83acd04
--- /dev/null
@@ -0,0 +1,20 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:12:25
+   |
+LL | struct Wrapper<const F: fn() -> u32>;
+   |                         ^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-call.rs:14:15
+   |
+LL | impl<const F: fn() -> u32> Wrapper<F> {
+   |               ^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
index 90c438b05cb816459e5e4a1b9190e11559ea0a1c..bba6c1f7a16f42be62249cb86e4bf5b7582235fe 100644 (file)
@@ -1,5 +1,9 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Check that functions cannot be used as const parameters.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn function() -> u32 {
     17
diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr
deleted file mode 100644 (file)
index b581124..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fn-const-param-call.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:8:25
-   |
-LL | struct Wrapper<const F: fn() -> u32>;
-   |                         ^^^^^^^^^^^
-
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-call.rs:10:15
-   |
-LL | impl<const F: fn() -> u32> Wrapper<F> {
-   |               ^^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/fn-const-param-infer.full.stderr b/src/test/ui/const-generics/fn-const-param-infer.full.stderr
new file mode 100644 (file)
index 0000000..4bdc9b8
--- /dev/null
@@ -0,0 +1,8 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-infer.rs:7:25
+   |
+LL | struct Checked<const F: fn(usize) -> bool>;
+   |                         ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/fn-const-param-infer.min.stderr b/src/test/ui/const-generics/fn-const-param-infer.min.stderr
new file mode 100644 (file)
index 0000000..27d1101
--- /dev/null
@@ -0,0 +1,11 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/fn-const-param-infer.rs:7:25
+   |
+LL | struct Checked<const F: fn(usize) -> bool>;
+   |                         ^^^^^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
index 14fa3b494b3fcef1dade36b2d5f66352b3d65945..3ed75e7b00dd7608a16f771e365537effc938ec2 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Checked<const F: fn(usize) -> bool>;
 //~^ ERROR: using function pointers as const generic parameters
diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr
deleted file mode 100644 (file)
index 7aaa41e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fn-const-param-infer.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/fn-const-param-infer.rs:4:25
-   |
-LL | struct Checked<const F: fn(usize) -> bool>;
-   |                         ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
index 8e16221ed4bd25beb197066eed44eb0dc4bd47b4..950684aaa8dc1959e9ab09f7a0b3e5db967b0312 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 use std::fmt::Display;
 
diff --git a/src/test/ui/const-generics/fn-taking-const-generic-array.stderr b/src/test/ui/const-generics/fn-taking-const-generic-array.stderr
deleted file mode 100644 (file)
index 52fd0a8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/fn-taking-const-generic-array.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr
new file mode 100644 (file)
index 0000000..adcaa75
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/forbid-non-structural_match-types.rs:15:19
+   |
+LL | struct D<const X: C>;
+   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
new file mode 100644 (file)
index 0000000..25aa354
--- /dev/null
@@ -0,0 +1,27 @@
+error: using `A` as const generic parameters is forbidden
+  --> $DIR/forbid-non-structural_match-types.rs:10:19
+   |
+LL | struct B<const X: A>; // ok
+   |                   ^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `C` as const generic parameters is forbidden
+  --> $DIR/forbid-non-structural_match-types.rs:15:19
+   |
+LL | struct D<const X: C>;
+   |                   ^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/forbid-non-structural_match-types.rs:15:19
+   |
+LL | struct D<const X: C>;
+   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0741`.
index 514e215ba1aa2f5f2b869448694b6e8b6153515e..86540db2d03a0a1538de360c3232dc84fbf6dcd8 100644 (file)
@@ -1,13 +1,18 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 #[derive(PartialEq, Eq)]
 struct A;
 
 struct B<const X: A>; // ok
+//[min]~^ ERROR using `A` as const generic parameters is forbidden
 
 struct C;
 
 struct D<const X: C>; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]`
+//[min]~^ ERROR using `C` as const generic parameters is forbidden
 
 fn main() {}
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr
deleted file mode 100644 (file)
index 600be64..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/forbid-non-structural_match-types.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
-  --> $DIR/forbid-non-structural_match-types.rs:11:19
-   |
-LL | struct D<const X: C>;
-   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr
new file mode 100644 (file)
index 0000000..0ac51e8
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0044]: foreign items may not have const parameters
+  --> $DIR/foreign-item-const-parameter.rs:8:5
+   |
+LL |     fn foo<const X: usize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+   |
+   = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+  --> $DIR/foreign-item-const-parameter.rs:10:5
+   |
+LL |     fn bar<T, const X: usize>(_: T);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+   |
+   = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr
new file mode 100644 (file)
index 0000000..0ac51e8
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0044]: foreign items may not have const parameters
+  --> $DIR/foreign-item-const-parameter.rs:8:5
+   |
+LL |     fn foo<const X: usize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+   |
+   = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+  --> $DIR/foreign-item-const-parameter.rs:10:5
+   |
+LL |     fn bar<T, const X: usize>(_: T);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+   |
+   = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
index 41113780de32e4550d866d3c5f86f84f36bd1cca..44b6d0332c3f9026bb7ff65c8f382124bab60a58 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 extern "C" {
     fn foo<const X: usize>(); //~ ERROR foreign items may not have const parameters
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.stderr
deleted file mode 100644 (file)
index ee94794..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/foreign-item-const-parameter.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0044]: foreign items may not have const parameters
-  --> $DIR/foreign-item-const-parameter.rs:5:5
-   |
-LL |     fn foo<const X: usize>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
-   |
-   = help: replace the const parameters with concrete consts
-
-error[E0044]: foreign items may not have type or const parameters
-  --> $DIR/foreign-item-const-parameter.rs:7:5
-   |
-LL |     fn bar<T, const X: usize>(_: T);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
-   |
-   = help: replace the type or const parameters with concrete types or consts
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0044`.
index 4c2aee59ffebef14ec73eb5b337cdbad45952d8e..05cabc46baa3479edf32bc6a73ea96b60c5933d6 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct S<const X: u32>;
 
diff --git a/src/test/ui/const-generics/impl-const-generic-struct.stderr b/src/test/ui/const-generics/impl-const-generic-struct.stderr
deleted file mode 100644 (file)
index 9d68df0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/impl-const-generic-struct.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
new file mode 100644 (file)
index 0000000..6b902e2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0107]: wrong number of const arguments: expected 2, found 1
+  --> $DIR/incorrect-number-of-const-args.rs:12:5
+   |
+LL |     foo::<0>();
+   |     ^^^^^^^^ expected 2 const arguments
+
+error[E0107]: wrong number of const arguments: expected 2, found 3
+  --> $DIR/incorrect-number-of-const-args.rs:13:17
+   |
+LL |     foo::<0, 0, 0>();
+   |                 ^ unexpected const argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
new file mode 100644 (file)
index 0000000..6b902e2
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0107]: wrong number of const arguments: expected 2, found 1
+  --> $DIR/incorrect-number-of-const-args.rs:12:5
+   |
+LL |     foo::<0>();
+   |     ^^^^^^^^ expected 2 const arguments
+
+error[E0107]: wrong number of const arguments: expected 2, found 3
+  --> $DIR/incorrect-number-of-const-args.rs:13:17
+   |
+LL |     foo::<0, 0, 0>();
+   |                 ^ unexpected const argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
index cea64654e11a022603445065be276bb7dfc42b3b..f7bdf761f7d1289882195317d995103aa437e415 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn foo<const X: usize, const Y: usize>() -> usize {
     0
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr
deleted file mode 100644 (file)
index 51064d7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/incorrect-number-of-const-args.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0107]: wrong number of const arguments: expected 2, found 1
-  --> $DIR/incorrect-number-of-const-args.rs:9:5
-   |
-LL |     foo::<0>();
-   |     ^^^^^^^^ expected 2 const arguments
-
-error[E0107]: wrong number of const arguments: expected 2, found 3
-  --> $DIR/incorrect-number-of-const-args.rs:10:17
-   |
-LL |     foo::<0, 0, 0>();
-   |                 ^ unexpected const argument
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0107`.
index 7e8152dacc46ce10621d5f6855b0e91507607152..609fdb35cf18d0b9b2e1338fe823768373a917d1 100644 (file)
@@ -1,8 +1,11 @@
 // run-pass
 //
 // see issue #70529
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct A<const N: usize> {
     arr: [u8; N],
diff --git a/src/test/ui/const-generics/infer_arg_from_pat.stderr b/src/test/ui/const-generics/infer_arg_from_pat.stderr
deleted file mode 100644 (file)
index f52e5e4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/infer_arg_from_pat.rs:4:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index cede9ea045d4434339b2272a974f9554a9e1604a..cbf48e3d24997aab5cb1964b8a27b03dd87e4bb6 100644 (file)
@@ -1,8 +1,11 @@
 // check-pass
 //
 // see issue #70529
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn as_chunks<const N: usize>() -> [u8; N] {
     loop {}
diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.stderr b/src/test/ui/const-generics/infer_arr_len_from_pat.stderr
deleted file mode 100644 (file)
index dfadfbb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/infer_arr_len_from_pat.rs:4:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 952e05bac30f4bc96242040801a1d95f295ba28e..bdbf338295cccaa94e58d27004b37c41c1ceb94a 100644 (file)
@@ -1,7 +1,9 @@
 // check-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) {
     f([1, 2, 3]);
@@ -15,4 +17,7 @@
     |_| {}
 }
 
-fn main() {}
+fn main() {
+    takes_closure_of_array_3(returns_closure_of_array_3());
+    takes_closure_of_array_3_apit(returns_closure_of_array_3());
+}
diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr
deleted file mode 100644 (file)
index aadd10e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.full.stderr
new file mode 100644 (file)
index 0000000..8855f18
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:7:40
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                        ^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-61522-array-len-succ.rs:12:24
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                        ^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.min.stderr
new file mode 100644 (file)
index 0000000..a1b1a09
--- /dev/null
@@ -0,0 +1,18 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-61522-array-len-succ.rs:7:45
+   |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+   |                                             ^^^^^ non-trivial anonymous constants must not depend on the parameter `COUNT`
+   |
+   = help: it is currently only allowed to use either `COUNT` or `{ COUNT }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-61522-array-len-succ.rs:12:30
+   |
+LL |     fn inner(&self) -> &[u8; COUNT + 1] {
+   |                              ^^^^^ non-trivial anonymous constants must not depend on the parameter `COUNT`
+   |
+   = help: it is currently only allowed to use either `COUNT` or `{ COUNT }` as generic constants
+
+error: aborting due to 2 previous errors
+
index 7c8cdeece871892abe59b859f91b85c7e15eff4d..81443b90d6156648725e22b693b25473cac642b3 100644 (file)
@@ -1,12 +1,17 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-//~^ ERROR constant expression depends on a generic parameter
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters must not be used
 
 impl<const COUNT: usize> MyArray<COUNT> {
     fn inner(&self) -> &[u8; COUNT + 1] {
-        //~^ ERROR constant expression depends on a generic parameter
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        //[min]~^^ ERROR generic parameters must not be used
         &self.0
     }
 }
diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.stderr
deleted file mode 100644 (file)
index a1fbd5f..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61522-array-len-succ.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:4:40
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                        ^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:8:24
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                        ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
new file mode 100644 (file)
index 0000000..3ff17dd
--- /dev/null
@@ -0,0 +1,11 @@
+error: using `&'static str` as const generic parameters is forbidden
+  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:9:25
+   |
+LL | trait Trait<const NAME: &'static str> {
+   |                         ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
index 74f036e6d89b57d3c06b59d1bf2a91f83fcc0c66..d458a366fb3737fcf80c43ab88766324cc1b2db6 100644 (file)
@@ -1,9 +1,13 @@
-// check-pass
+//[full] check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
 
 trait Trait<const NAME: &'static str> {
+//[min]~^ ERROR using `&'static str` as const generic parameters is forbidden
     type Assoc;
 }
 
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr
deleted file mode 100644 (file)
index 720420d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index bda9ce8767d085dc69b7f7d859475deacd0da0d9..eab63d3a6e6ab0563b3d513c5e256966c51bdef8 100644 (file)
@@ -1,8 +1,10 @@
 // aux-build:impl-const.rs
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 extern crate impl_const;
 
index ff2a5250263d5585a73120f8834b2062b7d16e2b..9cfa57006d5c670adb6f2751caa1e25a0c78b85c 100644 (file)
@@ -1,6 +1,9 @@
 // build-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub fn works() {
     let array/*: [_; _]*/ = default_array();
index 83338668f4ffde204681938230d23def9e833184..bbde404966ccf04361a3c338e0a2cbfdffd120c1 100644 (file)
@@ -1,6 +1,9 @@
 // build-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn works() {
     let array/*: [u8; _]*/ = default_byte_array();
index 048ed18c927bfa25e9a03b76cef939ac5c80f99d..d4c962452d182dae3164eb2a43b85ff954ab34ab 100644 (file)
@@ -1,6 +1,9 @@
 // check-pass
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub trait Foo<const B: bool> {}
 pub fn bar<T: Foo<{ true }>>() {}
index 9ca1f4552f596c5dfb415883f2e557df097837ff..cf24cbe7e82bae335920d968727f3f53fcbcf15a 100644 (file)
@@ -1,7 +1,10 @@
 // run-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
 
 use std::ops::AddAssign;
 
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.stderr b/src/test/ui/const-generics/mut-ref-const-param-array.stderr
deleted file mode 100644 (file)
index acbc2df..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/mut-ref-const-param-array.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/nested-type.full.stderr b/src/test/ui/const-generics/nested-type.full.stderr
new file mode 100644 (file)
index 0000000..012b8fe
--- /dev/null
@@ -0,0 +1,159 @@
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:7:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:7:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:11:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:3:1
+   |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:7:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:7:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:11:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:3:1
+   |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/const-generics/nested-type.min.stderr b/src/test/ui/const-generics/nested-type.min.stderr
new file mode 100644 (file)
index 0000000..ebe8187
--- /dev/null
@@ -0,0 +1,175 @@
+error: using `[u8; _]` as const generic parameters is forbidden
+  --> $DIR/nested-type.rs:7:21
+   |
+LL |   struct Foo<const N: [u8; {
+   |  _____________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |__^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:7:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:7:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:11:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:3:1
+   |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo`
+  --> $DIR/nested-type.rs:7:1
+   |
+LL | struct Foo<const N: [u8; {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires computing type of `Foo::N`...
+  --> $DIR/nested-type.rs:7:18
+   |
+LL | struct Foo<const N: [u8; {
+   |                  ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+  --> $DIR/nested-type.rs:7:26
+   |
+LL |   struct Foo<const N: [u8; {
+   |  __________________________^
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     Foo::<17>::value()
+LL | | }]>;
+   | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+  --> $DIR/nested-type.rs:11:5
+   |
+LL |     struct Foo<const N: usize>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which requires computing the variances for items in this crate...
+   = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/nested-type.rs:3:1
+   |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
index 12ea850c8f686f79a3c39950df8f10e19874f9b6..98a5a0dd3d8fdf3b8e6ecb3c1428f244a7115ea8 100644 (file)
@@ -1,9 +1,13 @@
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Foo<const N: [u8; {
 //~^ ERROR cycle detected
 //~| ERROR cycle detected
+//[min]~| ERROR using `[u8; _]` as const generic
     struct Foo<const N: usize>;
 
     impl<const N: usize> Foo<N> {
diff --git a/src/test/ui/const-generics/nested-type.stderr b/src/test/ui/const-generics/nested-type.stderr
deleted file mode 100644 (file)
index da0e803..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-error[E0391]: cycle detected when computing type of `Foo`
-  --> $DIR/nested-type.rs:4:1
-   |
-LL | struct Foo<const N: [u8; {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires computing type of `Foo::N`...
-  --> $DIR/nested-type.rs:4:18
-   |
-LL | struct Foo<const N: [u8; {
-   |                  ^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires const-evaluating `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires type-checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
-  --> $DIR/nested-type.rs:7:5
-   |
-LL |     struct Foo<const N: usize>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing the variances for items in this crate...
-   = note: ...which again requires computing type of `Foo`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/nested-type.rs:1:1
-   |
-LL | / #![feature(const_generics)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | struct Foo<const N: [u8; {
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-
-error[E0391]: cycle detected when computing type of `Foo`
-  --> $DIR/nested-type.rs:4:1
-   |
-LL | struct Foo<const N: [u8; {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires computing type of `Foo::N`...
-  --> $DIR/nested-type.rs:4:18
-   |
-LL | struct Foo<const N: [u8; {
-   |                  ^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires const-evaluating `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires type-checking `Foo::{{constant}}#0`...
-  --> $DIR/nested-type.rs:4:26
-   |
-LL |   struct Foo<const N: [u8; {
-   |  __________________________^
-LL | |
-LL | |
-LL | |     struct Foo<const N: usize>;
-...  |
-LL | |     Foo::<17>::value()
-LL | | }]>;
-   | |_^
-note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
-  --> $DIR/nested-type.rs:7:5
-   |
-LL |     struct Foo<const N: usize>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing the variances for items in this crate...
-   = note: ...which again requires computing type of `Foo`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/nested-type.rs:1:1
-   |
-LL | / #![feature(const_generics)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | struct Foo<const N: [u8; {
-...  |
-LL | |
-LL | | fn main() {}
-   | |____________^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
new file mode 100644 (file)
index 0000000..3dccfd7
--- /dev/null
@@ -0,0 +1,22 @@
+error: type parameters with a default must be trailing
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12
+   |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+   |            ^
+   |
+   = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44
+   |
+LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
+   |                                            ^ the anonymous constant must not depend on the parameter `T`
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
+   |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+   |                     ^ the anonymous constant must not depend on the parameter `N`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
new file mode 100644 (file)
index 0000000..461822a
--- /dev/null
@@ -0,0 +1,24 @@
+error: type parameters with a default must be trailing
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12
+   |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+   |            ^
+   |
+   = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44
+   |
+LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
+   |                                            ^ non-trivial anonymous constants must not depend on the parameter `T`
+   |
+   = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
+   |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+   |                     ^ the anonymous constant must not depend on the parameter `N`
+
+error: aborting due to 3 previous errors
+
index 84bbea5b880573c72f919de7642164b0006dadfb..e52773c78dbd3b4a66bb879dde364c4a054772c3 100644 (file)
@@ -1,7 +1,12 @@
-#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-//~^ ERROR constant values inside of type parameter defaults
+//[full]~^ ERROR constant values inside of type parameter defaults
+//[min]~^^ ERROR generic parameters must not be used inside of non trivial
 
 // FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
 struct Bar<T = [u8; N], const N: usize>(T);
diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.stderr
deleted file mode 100644 (file)
index 571be91..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-error: type parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:12
-   |
-LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |            ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:3:44
-   |
-LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-   |                                            ^ the anonymous constant must not depend on the parameter `T`
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:21
-   |
-LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.full.stderr
new file mode 100644 (file)
index 0000000..ffaab51
--- /dev/null
@@ -0,0 +1,14 @@
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:10:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:12:15
+   |
+LL | impl<const P: *const u32> Const<P> {
+   |               ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.min.stderr
new file mode 100644 (file)
index 0000000..dc4bb8b
--- /dev/null
@@ -0,0 +1,20 @@
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:10:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param-deref.rs:12:15
+   |
+LL | impl<const P: *const u32> Const<P> {
+   |               ^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
index 97ca9d6a44c9e8f38d0527697ad0d3b0a63ea97d..20cc62ebc17cd408a4c48430cccbf1ed4ff047b0 100644 (file)
@@ -1,5 +1,9 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Checks that pointers must not be used as the type of const params.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 const A: u32 = 3;
 
diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr
deleted file mode 100644 (file)
index 1ce8bb9..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/raw-ptr-const-param-deref.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:6:23
-   |
-LL | struct Const<const P: *const u32>;
-   |                       ^^^^^^^^^^
-
-error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param-deref.rs:8:15
-   |
-LL | impl<const P: *const u32> Const<P> {
-   |               ^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.full.stderr b/src/test/ui/const-generics/raw-ptr-const-param.full.stderr
new file mode 100644 (file)
index 0000000..d317aa0
--- /dev/null
@@ -0,0 +1,8 @@
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param.rs:7:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.min.stderr b/src/test/ui/const-generics/raw-ptr-const-param.min.stderr
new file mode 100644 (file)
index 0000000..f387974
--- /dev/null
@@ -0,0 +1,11 @@
+error: using raw pointers as const generic parameters is forbidden
+  --> $DIR/raw-ptr-const-param.rs:7:23
+   |
+LL | struct Const<const P: *const u32>;
+   |                       ^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
index 237b410e073d6f886b617bfc40f30434b16c7cd7..36e593aa210223d8a85eb1a9f35298c5f5ee117e 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
 
diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr
deleted file mode 100644 (file)
index 6e64f8a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/raw-ptr-const-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/raw-ptr-const-param.rs:4:23
-   |
-LL | struct Const<const P: *const u32>;
-   |                       ^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.full.stderr
new file mode 100644 (file)
index 0000000..d06da2e
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:15:35
+   |
+LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
+   |            --------------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstString<"Hello">`
+              found struct `ConstString<"World">`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:17:33
+   |
+LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
+   |            -------------------   ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstString<"ℇ㇈↦">`
+              found struct `ConstString<"ℇ㇈↥">`
+
+error[E0308]: mismatched types
+  --> $DIR/slice-const-param-mismatch.rs:19:33
+   |
+LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
+   |            ------------------   ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `ConstBytes<b"AAA">`
+              found struct `ConstBytes<b"BBB">`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
new file mode 100644 (file)
index 0000000..e86f885
--- /dev/null
@@ -0,0 +1,20 @@
+error: using `&'static str` as const generic parameters is forbidden
+  --> $DIR/slice-const-param-mismatch.rs:8:29
+   |
+LL | struct ConstString<const T: &'static str>;
+   |                             ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static [u8]` as const generic parameters is forbidden
+  --> $DIR/slice-const-param-mismatch.rs:10:28
+   |
+LL | struct ConstBytes<const T: &'static [u8]>;
+   |                            ^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
index 4f321b02b82770bc3723a462d4269012585416c7..0f8ae9bac4a3ce24898c8f761c26f4fa2e865080 100644 (file)
@@ -1,14 +1,20 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
 
 struct ConstString<const T: &'static str>;
+//[min]~^ ERROR
 struct ConstBytes<const T: &'static [u8]>;
+//[min]~^ ERROR
 
 pub fn main() {
     let _: ConstString<"Hello"> = ConstString::<"Hello">;
-    let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
+    let _: ConstString<"Hello"> = ConstString::<"World">; //[full]~ ERROR mismatched types
     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
-    let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
+    let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //[full]~ ERROR mismatched types
     let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
-    let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
+    let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //[full]~ ERROR mismatched types
 }
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr
deleted file mode 100644 (file)
index cc21f19..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/slice-const-param-mismatch.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:9:35
-   |
-LL |     let _: ConstString<"Hello"> = ConstString::<"World">;
-   |            --------------------   ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `ConstString<"Hello">`
-              found struct `ConstString<"World">`
-
-error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:11:33
-   |
-LL |     let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
-   |            -------------------   ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `ConstString<"ℇ㇈↦">`
-              found struct `ConstString<"ℇ㇈↥">`
-
-error[E0308]: mismatched types
-  --> $DIR/slice-const-param-mismatch.rs:13:33
-   |
-LL |     let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
-   |            ------------------   ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `ConstBytes<b"AAA">`
-              found struct `ConstBytes<b"BBB">`
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr
new file mode 100644 (file)
index 0000000..e2ffc67
--- /dev/null
@@ -0,0 +1,20 @@
+error: using `&'static str` as const generic parameters is forbidden
+  --> $DIR/slice-const-param.rs:8:40
+   |
+LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
+   |                                        ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static [u8]` as const generic parameters is forbidden
+  --> $DIR/slice-const-param.rs:13:41
+   |
+LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
+   |                                         ^^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
index 9668f7ddabb38a81568a21c875cdd292105b50fc..1b6d2f6216c44d27afdfa498eade3cea06c5bb43 100644 (file)
@@ -1,13 +1,17 @@
-// run-pass
+//[full] run-pass
+// revisions: min full
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub fn function_with_str<const STRING: &'static str>() -> &'static str {
+    //[min]~^ ERROR using `&'static str` as const
     STRING
 }
 
 pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
+    //[min]~^ ERROR using `&'static [u8]` as const
     BYTES
 }
 
diff --git a/src/test/ui/const-generics/slice-const-param.stderr b/src/test/ui/const-generics/slice-const-param.stderr
deleted file mode 100644 (file)
index 524bd41..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/slice-const-param.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr
new file mode 100644 (file)
index 0000000..e73a297
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0573]: expected type, found const parameter `C`
+  --> $DIR/struct-with-invalid-const-param.rs:8:23
+   |
+LL | struct S<const C: u8>(C);
+   |                       ^ not a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr
new file mode 100644 (file)
index 0000000..e73a297
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0573]: expected type, found const parameter `C`
+  --> $DIR/struct-with-invalid-const-param.rs:8:23
+   |
+LL | struct S<const C: u8>(C);
+   |                       ^ not a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
index 0b00481d903e02962c221a0982f35f8551f0c5f9..f0122ace3aec3a5c97e71a69d918c5a79b299746 100644 (file)
@@ -1,5 +1,9 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Checks that a const param cannot be stored in a struct.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
 
index b60d7e89651425bf14d471b4947d4eea577b7da9..b66d79845f971581f821b702ea1e88a8790c1bcf 100644 (file)
@@ -1,6 +1,9 @@
 // check-pass
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Const<const N: usize>;
 trait Foo<const N: usize> {}
index 1aed9cfe927301f5b030faefa4c66104236ce8ad..e041e9709d0ec56204caad2ebd7505736f22b63a 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 use std::mem::MaybeUninit;
 
diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr
deleted file mode 100644 (file)
index 6077fe5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 588c7b9523aad37a9fe6cbd9f8e9bece1cf920e4..f424fd03341fec6945058f72f9aa72c277ab21ce 100644 (file)
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 trait T<const A: usize> {
     fn l<const N: bool>() -> usize;
diff --git a/src/test/ui/const-generics/type_of_anon_const.stderr b/src/test/ui/const-generics/type_of_anon_const.stderr
deleted file mode 100644 (file)
index 8afed0d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/type_of_anon_const.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/uninferred-consts.full.stderr b/src/test/ui/const-generics/uninferred-consts.full.stderr
new file mode 100644 (file)
index 0000000..2c5af9e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:14:5
+   |
+LL |     Foo.foo();
+   |     ^^^^^^^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/uninferred-consts.min.stderr b/src/test/ui/const-generics/uninferred-consts.min.stderr
new file mode 100644 (file)
index 0000000..2c5af9e
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:14:5
+   |
+LL |     Foo.foo();
+   |     ^^^^^^^^^
+   |
+   = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
index 3b2bb49197d01ec9e30d030e18bc5bf6f0536e59..ec5b3ffe5440bca973d7657e38d86ceed9562c71 100644 (file)
@@ -1,5 +1,9 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Test that we emit an error if we cannot properly infer a constant.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 // taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
 struct Foo;
diff --git a/src/test/ui/const-generics/uninferred-consts.stderr b/src/test/ui/const-generics/uninferred-consts.stderr
deleted file mode 100644 (file)
index a362008..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/uninferred-consts.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:10:5
-   |
-LL |     Foo.foo();
-   |     ^^^^^^^^^
-   |
-   = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/unknown_adt.full.stderr b/src/test/ui/const-generics/unknown_adt.full.stderr
new file mode 100644 (file)
index 0000000..94f3165
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `UnknownStruct` in this scope
+  --> $DIR/unknown_adt.rs:8:12
+   |
+LL |     let _: UnknownStruct<7>;
+   |            ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/const-generics/unknown_adt.min.stderr b/src/test/ui/const-generics/unknown_adt.min.stderr
new file mode 100644 (file)
index 0000000..94f3165
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `UnknownStruct` in this scope
+  --> $DIR/unknown_adt.rs:8:12
+   |
+LL |     let _: UnknownStruct<7>;
+   |            ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
index 0ba9945b399ae62fba70ceca9d55a445209a90e6..c6131402aeb6cb60dc73c775db65f644d6573f4a 100644 (file)
@@ -1,5 +1,8 @@
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn main() {
     let _: UnknownStruct<7>;
diff --git a/src/test/ui/const-generics/unknown_adt.stderr b/src/test/ui/const-generics/unknown_adt.stderr
deleted file mode 100644 (file)
index b2e287b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0412]: cannot find type `UnknownStruct` in this scope
-  --> $DIR/unknown_adt.rs:5:12
-   |
-LL |     let _: UnknownStruct<7>;
-   |            ^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0412`.
index d9292efc21b749b8dc82ada5f9b7f06e202779ef..3c305167b4b64d12bbc5525b2cab68b7eeaf1f6c 100644 (file)
@@ -1,7 +1,9 @@
 // check-pass
+// revisions: full min
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct A<const N: usize>; // ok
 
diff --git a/src/test/ui/const-generics/unused-const-param.stderr b/src/test/ui/const-generics/unused-const-param.stderr
deleted file mode 100644 (file)
index be015a6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unused-const-param.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/unused_braces.full.fixed b/src/test/ui/const-generics/unused_braces.full.fixed
new file mode 100644 (file)
index 0000000..1b075ad
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+// run-rustfix
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+#![warn(unused_braces)]
+
+
+struct A<const N: usize>;
+
+fn main() {
+    let _: A<7>; // ok
+    let _: A<7>; //~ WARN unnecessary braces
+    let _: A<{ 3 + 5 }>; // ok
+}
diff --git a/src/test/ui/const-generics/unused_braces.full.stderr b/src/test/ui/const-generics/unused_braces.full.stderr
new file mode 100644 (file)
index 0000000..1752779
--- /dev/null
@@ -0,0 +1,14 @@
+warning: unnecessary braces around const expression
+  --> $DIR/unused_braces.rs:15:14
+   |
+LL |     let _: A<{ 7 }>;
+   |              ^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:8:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/const-generics/unused_braces.min.fixed b/src/test/ui/const-generics/unused_braces.min.fixed
new file mode 100644 (file)
index 0000000..1b075ad
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+// run-rustfix
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+#![warn(unused_braces)]
+
+
+struct A<const N: usize>;
+
+fn main() {
+    let _: A<7>; // ok
+    let _: A<7>; //~ WARN unnecessary braces
+    let _: A<{ 3 + 5 }>; // ok
+}
diff --git a/src/test/ui/const-generics/unused_braces.min.stderr b/src/test/ui/const-generics/unused_braces.min.stderr
new file mode 100644 (file)
index 0000000..1752779
--- /dev/null
@@ -0,0 +1,14 @@
+warning: unnecessary braces around const expression
+  --> $DIR/unused_braces.rs:15:14
+   |
+LL |     let _: A<{ 7 }>;
+   |              ^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:8:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
index c3e02b45ed5a26ecf4097df28fd9b925f86c53aa..31c4caf7ab8509037adfcc07f7e6fbb8f6413b54 100644 (file)
@@ -1,10 +1,12 @@
 // check-pass
 // run-rustfix
+// revisions: full min
 
-#![allow(incomplete_features)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 #![warn(unused_braces)]
 
-#![feature(const_generics)]
 
 struct A<const N: usize>;
 
diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr
deleted file mode 100644 (file)
index 618698a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: unnecessary braces around const expression
-  --> $DIR/unused_braces.rs:13:14
-   |
-LL |     let _: A<{ 7 }>;
-   |              ^^^^^ help: remove these braces
-   |
-note: the lint level is defined here
-  --> $DIR/unused_braces.rs:5:9
-   |
-LL | #![warn(unused_braces)]
-   |         ^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/wf-misc.full.stderr b/src/test/ui/const-generics/wf-misc.full.stderr
new file mode 100644 (file)
index 0000000..4af48fa
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/wf-misc.rs:9:12
+   |
+LL |     let _: [u8; N + 1];
+   |            ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/wf-misc.rs:17:12
+   |
+LL |     let _: Const::<{N + 1}>;
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/wf-misc.min.stderr b/src/test/ui/const-generics/wf-misc.min.stderr
new file mode 100644 (file)
index 0000000..f2acb8f
--- /dev/null
@@ -0,0 +1,18 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/wf-misc.rs:9:17
+   |
+LL |     let _: [u8; N + 1];
+   |                 ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/wf-misc.rs:17:21
+   |
+LL |     let _: Const::<{N + 1}>;
+   |                     ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
+
index 4ff1b9e2da5b24a5a4327884538260d1633e032a..e6f7a9963e8f11735cf5cc69e59af15f340de7bc 100644 (file)
@@ -1,16 +1,22 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Tests miscellaneous well-formedness examples.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
 
 pub fn arr_len<const N: usize>() {
     let _: [u8; N + 1];
-    //~^ ERROR constant expression depends on a generic parameter
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial
 }
 
 struct Const<const N: usize>;
 
 pub fn func_call<const N: usize>() {
     let _: Const::<{N + 1}>;
-    //~^ ERROR constant expression depends on a generic parameter
+    //[full]~^ ERROR constant expression depends on a generic parameter
+    //[min]~^^ ERROR generic parameters must not be used inside of non trivial
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/wf-misc.stderr b/src/test/ui/const-generics/wf-misc.stderr
deleted file mode 100644 (file)
index 03f2bf3..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/wf-misc.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
-  --> $DIR/wf-misc.rs:5:12
-   |
-LL |     let _: [u8; N + 1];
-   |            ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/wf-misc.rs:12:12
-   |
-LL |     let _: Const::<{N + 1}>;
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
index c7a66c327f1c177807e0322f8c372c5f080187a1..435a2c9396273093694b4d7dcfa857fd9ccfb9ba 100644 (file)
@@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/E0225.rs:6:36
    |
 LL |     let _: Box<dyn std::io::Read + std::io::Write>;
-   |                    -------------   ^^^^^^^^^^^^^^
-   |                    |               |
-   |                    |               additional non-auto trait
-   |                    |               trait alias used in trait object type (additional use)
+   |                    -------------   ^^^^^^^^^^^^^^ additional non-auto trait
+   |                    |
    |                    first non-auto trait
-   |                    trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/E0225.rs:8:20
@@ -22,6 +22,9 @@ LL |     let _: Box<dyn Foo>;
    |                    |
    |                    trait alias used in trait object type (additional use)
    |                    trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error: aborting due to 2 previous errors
 
index 3c6a1d4f88f1153b60c1dd5bba8962b163393d06..fa0c86ecf489423b8e1b67d765fb1ff8e2e87a99 100644 (file)
@@ -6,6 +6,10 @@ fn bar(self) {}
     fn foo() {
         self.bar(); //~ ERROR E0424
     }
+
+    fn baz(_: i32) {
+        self.bar(); //~ ERROR E0424
+    }
 }
 
 fn main () {
index 690a101496d7325eee1265c9b532fa6c37ec0e1e..9b8a29e8272492e64d8f513ec95b46b85d0d6d9b 100644 (file)
@@ -1,21 +1,37 @@
 error[E0424]: expected value, found module `self`
   --> $DIR/E0424.rs:7:9
    |
-LL | /     fn foo() {
-LL | |         self.bar();
-   | |         ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | |     }
-   | |_____- this function doesn't have a `self` parameter
+LL |     fn foo() {
+   |        --- this function doesn't have a `self` parameter
+LL |         self.bar();
+   |         ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+   |
+help: add a `self` receiver parameter to make the associated `fn` a method
+   |
+LL |     fn foo(&self) {
+   |            ^^^^^
+
+error[E0424]: expected value, found module `self`
+  --> $DIR/E0424.rs:11:9
+   |
+LL |     fn baz(_: i32) {
+   |        --- this function doesn't have a `self` parameter
+LL |         self.bar();
+   |         ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+   |
+help: add a `self` receiver parameter to make the associated `fn` a method
+   |
+LL |     fn baz(&self, _: i32) {
+   |            ^^^^^^
 
 error[E0424]: expected unit struct, unit variant or constant, found module `self`
-  --> $DIR/E0424.rs:12:9
+  --> $DIR/E0424.rs:16:9
    |
-LL | / fn main () {
-LL | |     let self = "self";
-   | |         ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
-LL | | }
-   | |_- this function doesn't have a `self` parameter
+LL | fn main () {
+   |    ---- this function can't have a `self` parameter
+LL |     let self = "self";
+   |         ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0424`.
diff --git a/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.rs
new file mode 100644 (file)
index 0000000..a84065e
--- /dev/null
@@ -0,0 +1,11 @@
+// Previously this ICE'd because `fn g()` would be lowered, but the block associated with `fn f()`
+// wasn't.
+
+// compile-flags: --crate-type=lib
+
+extern "C" {
+    fn f() {
+    //~^ incorrect function inside `extern` block
+        fn g() {}
+    }
+}
diff --git a/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr b/src/test/ui/foreign/issue-74120-lowering-of-ffi-block-bodies.stderr
new file mode 100644 (file)
index 0000000..d4a9ca3
--- /dev/null
@@ -0,0 +1,19 @@
+error: incorrect function inside `extern` block
+  --> $DIR/issue-74120-lowering-of-ffi-block-bodies.rs:7:8
+   |
+LL |   extern "C" {
+   |   ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL |       fn f() {
+   |  ________^___-
+   | |        |
+   | |        cannot have a body
+LL | |
+LL | |         fn g() {}
+LL | |     }
+   | |_____- help: remove the invalid body: `;`
+   |
+   = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+   = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to previous error
+
index e5e50ddd1554ce459b8c1970ebbe31229b474be7..9dda99109fa2b875416a57ccfa4967adcd842faa 100644 (file)
@@ -28,12 +28,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/issue-22560.rs:9:23
    |
 LL | type Test = dyn Add + Sub;
-   |                 ---   ^^^
-   |                 |     |
-   |                 |     additional non-auto trait
-   |                 |     trait alias used in trait object type (additional use)
+   |                 ---   ^^^ additional non-auto trait
+   |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add<[type error]> + Sub<[type error]> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified
   --> $DIR/issue-22560.rs:9:17
index 34d5c894e36f21e6df75fef38df52465a2673271..f9628f2c2eca3da5a5b9e78c44427dd330017c56 100644 (file)
@@ -2,23 +2,23 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/issue-32963.rs:8:31
    |
 LL |     size_of_copy::<dyn Misc + Copy>();
-   |                        ----   ^^^^
-   |                        |      |
-   |                        |      additional non-auto trait
-   |                        |      trait alias used in trait object type (additional use)
+   |                        ----   ^^^^ additional non-auto trait
+   |                        |
    |                        first non-auto trait
-   |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/issue-32963.rs:8:31
    |
 LL |     size_of_copy::<dyn Misc + Copy>();
-   |                        ----   ^^^^
-   |                        |      |
-   |                        |      additional non-auto trait
-   |                        |      trait alias used in trait object type (additional use)
+   |                        ----   ^^^^ additional non-auto trait
+   |                        |
    |                        first non-auto trait
-   |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
   --> $DIR/issue-32963.rs:8:5
index d00fff32809206b285a178d948abe48eec69342f..ee134835c37ed14eae101b077ee613c0dc68ee13 100644 (file)
@@ -1,3 +1,10 @@
-trait B < A > { fn a() -> A { this.a } } //~ ERROR cannot find value `this` in this scope
+trait B <A> {
+    fn a() -> A {
+        this.a //~ ERROR cannot find value `this` in this scope
+    }
+    fn b(x: i32) {
+        this.b(x); //~ ERROR cannot find value `this` in this scope
+    }
+}
 
 fn main() {}
index cc11db9c5eca62dab03f485c58572d80ec9ab679..b52fd28b2b575a9490700fbce875b36175f6f9ef 100644 (file)
@@ -1,9 +1,33 @@
 error[E0425]: cannot find value `this` in this scope
-  --> $DIR/issue-5099.rs:1:31
+  --> $DIR/issue-5099.rs:3:9
    |
-LL | trait B < A > { fn a() -> A { this.a } }
-   |                               ^^^^ not found in this scope
+LL |         this.a
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.a
+   |         ^^^^
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn a(&self) -> A {
+   |          ^^^^^
+
+error[E0425]: cannot find value `this` in this scope
+  --> $DIR/issue-5099.rs:6:9
+   |
+LL |         this.b(x);
+   |         ^^^^ not found in this scope
+   |
+help: you might have meant to use `self` here instead
+   |
+LL |         self.b(x);
+   |         ^^^^
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+   |
+LL |     fn b(&self, x: i32) {
+   |          ^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-66768.rs b/src/test/ui/issues/issue-66768.rs
new file mode 100644 (file)
index 0000000..ce42c8b
--- /dev/null
@@ -0,0 +1,205 @@
+// Regression test for #66768.
+// check-pass
+#![allow(dead_code)]
+//-^ "dead code" is needed to reproduce the issue.
+
+use std::marker::PhantomData;
+use std::ops::{Add, Mul};
+
+fn problematic_function<Space>(material_surface_element: Edge2dElement)
+where
+    DefaultAllocator: FiniteElementAllocator<DimU1, Space>,
+{
+    let _: Point2<f64> = material_surface_element.map_reference_coords().into();
+}
+
+impl<T> ArrayLength<T> for UTerm {
+    type ArrayType = ();
+}
+impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
+    type ArrayType = GenericArrayImplEven<T, N>;
+}
+impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
+    type ArrayType = GenericArrayImplOdd<T, N>;
+}
+impl<U> Add<U> for UTerm {
+    type Output = U;
+    fn add(self, _: U) -> Self::Output {
+        unimplemented!()
+    }
+}
+impl<Ul, Ur> Add<UInt<Ur, B1>> for UInt<Ul, B0>
+where
+    Ul: Add<Ur>,
+{
+    type Output = UInt<Sum<Ul, Ur>, B1>;
+    fn add(self, _: UInt<Ur, B1>) -> Self::Output {
+        unimplemented!()
+    }
+}
+impl<U> Mul<U> for UTerm {
+    type Output = UTerm;
+    fn mul(self, _: U) -> Self {
+        unimplemented!()
+    }
+}
+impl<Ul, B, Ur> Mul<UInt<Ur, B>> for UInt<Ul, B0>
+where
+    Ul: Mul<UInt<Ur, B>>,
+{
+    type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
+    fn mul(self, _: UInt<Ur, B>) -> Self::Output {
+        unimplemented!()
+    }
+}
+impl<Ul, B, Ur> Mul<UInt<Ur, B>> for UInt<Ul, B1>
+where
+    Ul: Mul<UInt<Ur, B>>,
+    UInt<Prod<Ul, UInt<Ur, B>>, B0>: Add<UInt<Ur, B>>,
+{
+    type Output = Sum<UInt<Prod<Ul, UInt<Ur, B>>, B0>, UInt<Ur, B>>;
+    fn mul(self, _: UInt<Ur, B>) -> Self::Output {
+        unimplemented!()
+    }
+}
+impl<N, R, C> Allocator<N, R, C> for DefaultAllocator
+where
+    R: DimName,
+    C: DimName,
+    R::Value: Mul<C::Value>,
+    Prod<R::Value, C::Value>: ArrayLength<N>,
+{
+    type Buffer = ArrayStorage<N, R, C>;
+    fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
+        unimplemented!()
+    }
+    fn allocate_from_iterator<I>(_: R, _: C, _: I) -> Self::Buffer {
+        unimplemented!()
+    }
+}
+impl<N, C> Allocator<N, Dynamic, C> for DefaultAllocator {
+    type Buffer = VecStorage<N, Dynamic, C>;
+    fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer {
+        unimplemented!()
+    }
+    fn allocate_from_iterator<I>(_: Dynamic, _: C, _: I) -> Self::Buffer {
+        unimplemented!()
+    }
+}
+impl DimName for DimU1 {
+    type Value = U1;
+    fn name() -> Self {
+        unimplemented!()
+    }
+}
+impl DimName for DimU2 {
+    type Value = U2;
+    fn name() -> Self {
+        unimplemented!()
+    }
+}
+impl<N, D> From<VectorN<N, D>> for Point<N, D>
+where
+    DefaultAllocator: Allocator<N, D>,
+{
+    fn from(_: VectorN<N, D>) -> Self {
+        unimplemented!()
+    }
+}
+impl<GeometryDim, NodalDim> FiniteElementAllocator<GeometryDim, NodalDim> for DefaultAllocator where
+    DefaultAllocator: Allocator<f64, GeometryDim> + Allocator<f64, NodalDim>
+{
+}
+impl ReferenceFiniteElement for Edge2dElement {
+    type NodalDim = DimU1;
+}
+impl FiniteElement<DimU2> for Edge2dElement {
+    fn map_reference_coords(&self) -> Vector2<f64> {
+        unimplemented!()
+    }
+}
+
+type Owned<N, R, C> = <DefaultAllocator as Allocator<N, R, C>>::Buffer;
+type MatrixMN<N, R, C> = Matrix<N, R, C, Owned<N, R, C>>;
+type VectorN<N, D> = MatrixMN<N, D, DimU1>;
+type Vector2<N> = VectorN<N, DimU2>;
+type Point2<N> = Point<N, DimU2>;
+type U1 = UInt<UTerm, B1>;
+type U2 = UInt<UInt<UTerm, B1>, B0>;
+type Sum<A, B> = <A as Add<B>>::Output;
+type Prod<A, B> = <A as Mul<B>>::Output;
+
+struct GenericArray<T, U: ArrayLength<T>> {
+    _data: U::ArrayType,
+}
+struct GenericArrayImplEven<T, U> {
+    _parent2: U,
+    _marker: T,
+}
+struct GenericArrayImplOdd<T, U> {
+    _parent2: U,
+    _data: T,
+}
+struct B0;
+struct B1;
+struct UTerm;
+struct UInt<U, B> {
+    _marker: PhantomData<(U, B)>,
+}
+struct DefaultAllocator;
+struct Dynamic;
+struct DimU1;
+struct DimU2;
+struct Matrix<N, R, C, S> {
+    _data: S,
+    _phantoms: PhantomData<(N, R, C)>,
+}
+struct ArrayStorage<N, R, C>
+where
+    R: DimName,
+    C: DimName,
+    R::Value: Mul<C::Value>,
+    Prod<R::Value, C::Value>: ArrayLength<N>,
+{
+    _data: GenericArray<N, Prod<R::Value, C::Value>>,
+}
+struct VecStorage<N, R, C> {
+    _data: N,
+    _nrows: R,
+    _ncols: C,
+}
+struct Point<N, D>
+where
+    DefaultAllocator: Allocator<N, D>,
+{
+    _coords: VectorN<N, D>,
+}
+struct Edge2dElement;
+
+trait ArrayLength<T> {
+    type ArrayType;
+}
+trait Allocator<Scalar, R, C = DimU1> {
+    type Buffer;
+    fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer;
+    fn allocate_from_iterator<I>(nrows: R, ncols: C, iter: I) -> Self::Buffer;
+}
+trait DimName {
+    type Value;
+    fn name() -> Self;
+}
+trait FiniteElementAllocator<GeometryDim, NodalDim>:
+    Allocator<f64, GeometryDim> + Allocator<f64, NodalDim>
+{
+}
+trait ReferenceFiniteElement {
+    type NodalDim;
+}
+trait FiniteElement<GeometryDim>: ReferenceFiniteElement
+where
+    DefaultAllocator: FiniteElementAllocator<GeometryDim, Self::NodalDim>,
+{
+    fn map_reference_coords(&self) -> VectorN<f64, GeometryDim>;
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-75307.rs b/src/test/ui/issues/issue-75307.rs
new file mode 100644 (file)
index 0000000..2fe112a
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
+}
diff --git a/src/test/ui/issues/issue-75307.stderr b/src/test/ui/issues/issue-75307.stderr
new file mode 100644 (file)
index 0000000..4a5d997
--- /dev/null
@@ -0,0 +1,10 @@
+error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+  --> $DIR/issue-75307.rs:2:13
+   |
+LL |     format!(r"{}{}{}", named_arg=1);
+   |             ^^^^^^^^^
+   |
+   = note: positional arguments are zero-based
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/mir/issue-75419-validation-impl-trait.rs b/src/test/ui/mir/issue-75419-validation-impl-trait.rs
new file mode 100644 (file)
index 0000000..a8741be
--- /dev/null
@@ -0,0 +1,13 @@
+// build-pass
+
+// This used to fail MIR validation due to the types on both sides of
+// an assignment not being equal.
+// The failure doesn't occur with a check-only build.
+
+fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator<Item = &'a T> {
+    xs.iter()
+}
+
+fn main() {
+    iter_slice::<()> as fn(_) -> _;
+}
diff --git a/src/test/ui/parser/expr-as-stmt-2.rs b/src/test/ui/parser/expr-as-stmt-2.rs
new file mode 100644 (file)
index 0000000..3a18bdc
--- /dev/null
@@ -0,0 +1,10 @@
+// This is not autofixable because we give extra suggestions to end the first expression with `;`.
+fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+    if let Some(x) = a { true } else { false }
+    //~^ ERROR mismatched types
+    //~| ERROR mismatched types
+    && //~ ERROR mismatched types
+    if let Some(y) = a { true } else { false }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt-2.stderr b/src/test/ui/parser/expr-as-stmt-2.stderr
new file mode 100644 (file)
index 0000000..ee07c36
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt-2.rs:3:26
+   |
+LL |     if let Some(x) = a { true } else { false }
+   |     ---------------------^^^^------------------ help: consider using a semicolon here
+   |     |                    |
+   |     |                    expected `()`, found `bool`
+   |     expected this to be `()`
+
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt-2.rs:3:40
+   |
+LL |     if let Some(x) = a { true } else { false }
+   |     -----------------------------------^^^^^--- help: consider using a semicolon here
+   |     |                                  |
+   |     |                                  expected `()`, found `bool`
+   |     expected this to be `()`
+
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt-2.rs:6:5
+   |
+LL |   fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+   |                                             ---- expected `bool` because of return type
+LL |       if let Some(x) = a { true } else { false }
+   |       ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
+...
+LL | /     &&
+LL | |     if let Some(y) = a { true } else { false }
+   | |______________________________________________^ expected `bool`, found `&&bool`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 1ce6f9c25034f811a881b80033d0156aba8cc0fa..02816ef2791b0dcaa5b83ec0a694795e5083e730 100644 (file)
@@ -25,12 +25,6 @@ fn baz() -> i32 {
     //~^ ERROR mismatched types
 }
 
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
-    (if let Some(x) = a { true } else { false })
-    && //~ ERROR expected expression
-    if let Some(y) = a { true } else { false }
-}
-
 fn moo(x: u32) -> bool {
     (match x {
         _ => 1,
index b526c17488eaf72ee218a67bbda59cf5e50d9303..93baa8278f890b7bd431c0d86bf63c1d001d5721 100644 (file)
@@ -25,12 +25,6 @@ fn baz() -> i32 {
     //~^ ERROR mismatched types
 }
 
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
-    if let Some(x) = a { true } else { false }
-    && //~ ERROR expected expression
-    if let Some(y) = a { true } else { false }
-}
-
 fn moo(x: u32) -> bool {
     match x {
         _ => 1,
index 4d93e130901e7be4cea4b9e36b32850ee2c330cb..324aed0ad7cf6df71e5ecb701edbe007e6fad0a6 100644 (file)
@@ -22,16 +22,8 @@ LL |     { 42 } + foo;
    |     |
    |     help: parentheses are required to parse this as an expression: `({ 42 })`
 
-error: expected expression, found `&&`
-  --> $DIR/expr-as-stmt.rs:30:5
-   |
-LL |     if let Some(x) = a { true } else { false }
-   |     ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
-LL |     &&
-   |     ^^ expected expression
-
 error: expected expression, found `>`
-  --> $DIR/expr-as-stmt.rs:37:7
+  --> $DIR/expr-as-stmt.rs:31:7
    |
 LL |     } > 0
    |       ^ expected expression
@@ -75,7 +67,7 @@ LL |     { 3 } * 3
    |     |
    |     help: parentheses are required to parse this as an expression: `({ 3 })`
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0308, E0614.
 For more information about an error, try `rustc --explain E0308`.
index 0d53315839cebbd7b0d61383aba31c58163a8a39..090a17b413dda582e9ea71ff3d427f3fc66088ae 100644 (file)
@@ -2,7 +2,6 @@ pub(crate) struct Bar<T> {
   foo: T,
 
 trait T { //~ ERROR expected identifier, found keyword `trait`
-//~^ ERROR expected `:`, found `T`
     fn foo(&self);
 }
 
index ac8dd48a588791f6f50019366a3bda2556c389c3..a47d5506ef0b83718091e55dcd14fb26afd2c27a 100644 (file)
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/missing-close-brace-in-struct.rs:14:65
+  --> $DIR/missing-close-brace-in-struct.rs:13:65
    |
 LL | pub(crate) struct Bar<T> {
    |                          - unclosed delimiter
@@ -13,11 +13,5 @@ error: expected identifier, found keyword `trait`
 LL | trait T {
    | ^^^^^ expected identifier, found keyword
 
-error: expected `:`, found `T`
-  --> $DIR/missing-close-brace-in-struct.rs:4:7
-   |
-LL | trait T {
-   |       ^ expected `:`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
index 9fe4a148a56aa0adb1001a32c45ac9b3d4467b06..6d64de296f15001130b56ccd8fe76f868325108a 100644 (file)
@@ -1,7 +1,6 @@
 struct S {
     let foo: (),
     //~^  ERROR expected identifier, found keyword `let`
-    //~^^ ERROR expected `:`, found `foo`
 }
 
 fn main() {}
index 7de2c730a70696ee86fd1aca3c3d9803bb0fda22..10be2e045b2b883f9626bd18e247442b4d060a7b 100644 (file)
@@ -4,11 +4,5 @@ error: expected identifier, found keyword `let`
 LL |     let foo: (),
    |     ^^^ expected identifier, found keyword
 
-error: expected `:`, found `foo`
-  --> $DIR/removed-syntax-field-let.rs:2:9
-   |
-LL |     let foo: (),
-   |         ^^^ expected `:`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 62da99bc47d2653f83a6075d70cd7da18a98de24..6efbfad8f38657881ca2653692c5520c536636ce 100644 (file)
@@ -40,34 +40,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/trait-object-trait-parens.rs:8:35
    |
 LL |     let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
-   |                -----              ^^^^^^^^^^^^^^^^^^^
-   |                |                  |
-   |                |                  additional non-auto trait
-   |                |                  trait alias used in trait object type (additional use)
+   |                -----              ^^^^^^^^^^^^^^^^^^^ additional non-auto trait
+   |                |
    |                first non-auto trait
-   |                trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-object-trait-parens.rs:12:49
    |
 LL |     let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
-   |                           -------------------   ^^^^^
-   |                           |                     |
-   |                           |                     additional non-auto trait
-   |                           |                     trait alias used in trait object type (additional use)
+   |                           -------------------   ^^^^^ additional non-auto trait
+   |                           |
    |                           first non-auto trait
-   |                           trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-object-trait-parens.rs:16:38
    |
 LL |     let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
-   |                 -----------------    ^^^^^
-   |                 |                    |
-   |                 |                    additional non-auto trait
-   |                 |                    trait alias used in trait object type (additional use)
+   |                 -----------------    ^^^^^ additional non-auto trait
+   |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error: aborting due to 6 previous errors; 3 warnings emitted
 
index 82a94933b470eba3ef53e7dcd1ffd0198f9cf945..60555dc12dcacc8e57a3a1a3cb2cf9f73f429add 100644 (file)
@@ -18,7 +18,55 @@ fn foo<I, T>(_: I)
     bar::<I>()
 }
 
+#[rustc_polymorphize_error]
+fn baz<I, T>(_: I)
+where
+    std::iter::Repeat<I>: Iterator<Item = T>,
+{
+    bar::<I>()
+}
+
+// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and
+// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates.
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+    I: Iterator<Item = &'a (T, E)>,
+{
+    type Item = T;
+
+    #[rustc_polymorphize_error]
+    fn next(&mut self) -> Option<Self::Item> {
+        self.find(|_| true)
+    }
+}
+
+// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered
+// used because `B` is now used.
+
+trait Baz<Z> {}
+
+impl Baz<u16> for u8 {}
+impl Baz<u32> for u16 {}
+
+#[rustc_polymorphize_error]
+fn quux<A, B, C: Default>() -> usize
+where
+    A: Baz<B>,
+    B: Baz<C>,
+{
+    std::mem::size_of::<C>()
+}
+
 fn main() {
     let x = &[2u32];
     foo(x.iter());
+    baz(x.iter());
+
+    let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+    let _ = a.next();
+
+    let _ = quux::<u8, u16, u32>();
 }
diff --git a/src/test/ui/polymorphization/symbol-ambiguity.rs b/src/test/ui/polymorphization/symbol-ambiguity.rs
new file mode 100644 (file)
index 0000000..d97bae1
--- /dev/null
@@ -0,0 +1,22 @@
+// build-pass
+// compile-flags: -Zpolymorphize=on -Zsymbol-mangling-version=v0
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+    I: Iterator<Item = &'a (T, E)>,
+{
+    type Item = T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.find(|_| true)
+    }
+}
+
+fn main() {
+    let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+    let mut b = Foo([(1u16, 1u32)].iter(), &1u32);
+    let _ = a.next();
+    let _ = b.next();
+}
index b687f0b0af0ad90f60c98d9d0a6f44e182055bbf..0339daa0d6a18c0018937304bf45bf51dd9629be 100644 (file)
@@ -70,14 +70,15 @@ LL |         purr();
 error[E0424]: expected value, found module `self`
   --> $DIR/issue-2356.rs:65:8
    |
-LL | /   fn meow() {
-LL | |     if self.whiskers > 3 {
-   | |        ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | |
-LL | |         println!("MEOW");
-LL | |     }
-LL | |   }
-   | |___- this function doesn't have a `self` parameter
+LL |   fn meow() {
+   |      ---- this function doesn't have a `self` parameter
+LL |     if self.whiskers > 3 {
+   |        ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+   |
+help: add a `self` receiver parameter to make the associated `fn` a method
+   |
+LL |   fn meow(&self) {
+   |           ^^^^^
 
 error[E0425]: cannot find function `grow_older` in this scope
   --> $DIR/issue-2356.rs:72:5
@@ -112,12 +113,10 @@ LL |     purr_louder();
 error[E0424]: expected value, found module `self`
   --> $DIR/issue-2356.rs:92:5
    |
-LL | / fn main() {
-LL | |     self += 1;
-   | |     ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | |
-LL | | }
-   | |_- this function doesn't have a `self` parameter
+LL | fn main() {
+   |    ---- this function can't have a `self` parameter
+LL |     self += 1;
+   |     ^^^^ `self` value is a keyword only available in methods with a `self` parameter
 
 error: aborting due to 17 previous errors
 
index b09c1879d701599092a3fa1e5e1d96817a317f85..fe88d105c78bf19f697db21bb7c47be77cb1a4df 100644 (file)
@@ -25,8 +25,6 @@ trait Tar<'t, 'k, I> {}
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
-    //~| ERROR the lifetime bound for this object type cannot be deduced from context
-    //~| ERROR the lifetime bound for this object type cannot be deduced from context
 }
 thread_local! {
     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
@@ -39,8 +37,6 @@ trait Tar<'t, 'k, I> {}
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
     //~| ERROR missing lifetime specifier
-    //~| ERROR the lifetime bound for this object type cannot be deduced from context
-    //~| ERROR the lifetime bound for this object type cannot be deduced from context
 }
 
 thread_local! {
@@ -52,9 +48,7 @@ trait Tar<'t, 'k, I> {}
 }
 thread_local! {
     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-    //~^ ERROR the lifetime bound for this object type cannot be deduced from context
-    //~| ERROR the lifetime bound for this object type cannot be deduced from context
-    //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+    //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
     //~| ERROR wrong number of lifetime arguments: expected 2, found 1
     //~| ERROR wrong number of lifetime arguments: expected 2, found 1
     //~| ERROR wrong number of lifetime arguments: expected 2, found 1
index 2630cf1affae6be7531a36b9d6aa44f8048b9766..9838ac72ad7675f9b3906f4bf736a138c45fca32 100644 (file)
@@ -71,7 +71,7 @@ LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar<'static, 'static>>>>> = Ref
    |                                             ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:32:48
+  --> $DIR/missing-lifetime-specifier.rs:30:48
    |
 LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
    |                                                ^ expected 2 lifetime parameters
@@ -83,7 +83,7 @@ LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> =
    |                                                ^^^^^^^^^^^^^^^^^
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:32:48
+  --> $DIR/missing-lifetime-specifier.rs:30:48
    |
 LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
    |                                                ^ expected 2 lifetime parameters
@@ -95,7 +95,7 @@ LL |     static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> =
    |                                                ^^^^^^^^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:37:44
+  --> $DIR/missing-lifetime-specifier.rs:35:44
    |
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -107,7 +107,7 @@ LL |     static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<i32>>>>> = RefCell:
    |                                            ^^^^^^^^
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:37:49
+  --> $DIR/missing-lifetime-specifier.rs:35:49
    |
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
    |                                                 ^ expected 2 lifetime parameters
@@ -119,7 +119,7 @@ LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>>
    |                                                 ^^^^^^^^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:37:44
+  --> $DIR/missing-lifetime-specifier.rs:35:44
    |
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -131,7 +131,7 @@ LL |     static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<i32>>>>> = RefCell:
    |                                            ^^^^^^^^
 
 error[E0106]: missing lifetime specifiers
-  --> $DIR/missing-lifetime-specifier.rs:37:49
+  --> $DIR/missing-lifetime-specifier.rs:35:49
    |
 LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
    |                                                 ^ expected 2 lifetime parameters
@@ -143,7 +143,7 @@ LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>>
    |                                                 ^^^^^^^^^^^^^^^^^
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:54:44
+  --> $DIR/missing-lifetime-specifier.rs:50:44
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -155,7 +155,7 @@ LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> =
    |                                            ^^^^^^^^
 
 error[E0106]: missing lifetime specifier
-  --> $DIR/missing-lifetime-specifier.rs:54:44
+  --> $DIR/missing-lifetime-specifier.rs:50:44
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^ expected named lifetime parameter
@@ -166,91 +166,55 @@ help: consider using the `'static` lifetime
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^
 
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:23:45
-   |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:23:45
-   |
-LL |     static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:37:45
-   |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:37:45
-   |
-LL |     static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^
-
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:47:44
+  --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:47:44
+  --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:47:44
+  --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:47:44
+  --> $DIR/missing-lifetime-specifier.rs:43:44
    |
 LL |     static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                            ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:54:45
+  --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:54:45
+  --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:54:45
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^
-
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:54:45
+  --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
-  --> $DIR/missing-lifetime-specifier.rs:54:45
-   |
-LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
-   |                                             ^^^^^^^^^^^^^^^^^
-
 error[E0107]: wrong number of lifetime arguments: expected 2, found 1
-  --> $DIR/missing-lifetime-specifier.rs:54:45
+  --> $DIR/missing-lifetime-specifier.rs:50:45
    |
 LL |     static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
    |                                             ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
 
-error: aborting due to 28 previous errors
+error: aborting due to 22 previous errors
 
-Some errors have detailed explanations: E0106, E0107, E0228.
+Some errors have detailed explanations: E0106, E0107.
 For more information about an error, try `rustc --explain E0106`.
index 6df1df86508ee48f65de6c57062331458fdd089b..b297d54375c79783f82cd67fb70c2582536a157b 100644 (file)
@@ -11,6 +11,9 @@ LL | type _T00 = dyn _0 + _0;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:19:22
@@ -27,6 +30,9 @@ LL | type _T01 = dyn _1 + _0;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:22:22
@@ -46,6 +52,9 @@ LL | type _T02 = dyn _1 + _1;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:25:23
@@ -59,7 +68,9 @@ LL | type _T03 = dyn Obj + _1;
    |                 ---   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:28:22
@@ -70,11 +81,12 @@ LL | trait _1 = _0;
    |            -- referenced here (first use)
 ...
 LL | type _T04 = dyn _1 + Obj;
-   |                 --   ^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:37:17
@@ -97,6 +109,9 @@ LL | type _T10 = dyn _2 + _3;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:40:22
@@ -113,6 +128,9 @@ LL | type _T11 = dyn _3 + _2;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:43:23
@@ -127,7 +145,9 @@ LL | type _T12 = dyn Obj + _2;
    |                 ---   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:46:17
@@ -150,6 +170,9 @@ LL | type _T13 = dyn _2 + Obj;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:49:22
@@ -166,6 +189,9 @@ LL | type _T14 = dyn _1 + _3;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:52:22
@@ -182,6 +208,9 @@ LL | type _T15 = dyn _3 + _1;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:55:22
@@ -200,6 +229,9 @@ LL | type _T16 = dyn _1 + _4;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:58:22
@@ -218,6 +250,9 @@ LL | type _T17 = dyn _4 + _1;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:65:22
@@ -232,6 +267,9 @@ LL | type _T20 = dyn _5 + _5;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:68:23
@@ -243,7 +281,9 @@ LL | type _T21 = dyn Obj + _5;
    |                 ---   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:71:22
@@ -252,11 +292,12 @@ LL | trait _5 = Obj + Send;
    |            --- first non-auto trait
 ...
 LL | type _T22 = dyn _5 + Obj;
-   |                 --   ^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:74:36
@@ -265,11 +306,12 @@ LL | trait _5 = Obj + Send;
    |            --- first non-auto trait
 ...
 LL | type _T23 = dyn _5 + Send + Sync + Obj;
-   |                 --                 ^^^
-   |                 |                  |
-   |                 |                  additional non-auto trait
-   |                 |                  trait alias used in trait object type (additional use)
+   |                 --                 ^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:81:17
@@ -290,6 +332,9 @@ LL | type _T30 = dyn _6;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:84:17
@@ -310,6 +355,9 @@ LL | type _T31 = dyn _6 + Send;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:87:24
@@ -330,6 +378,9 @@ LL | type _T32 = dyn Send + _6;
    |                        |
    |                        trait alias used in trait object type (additional use)
    |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:95:22
@@ -343,11 +394,12 @@ LL | trait _8 = Unpin + _7;
    |                    -- referenced here (first use)
 LL | 
 LL | type _T40 = dyn _8 + Obj;
-   |                 --   ^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:98:23
@@ -364,7 +416,9 @@ LL | type _T41 = dyn Obj + _8;
    |                 ---   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:101:22
@@ -386,6 +440,9 @@ LL | type _T42 = dyn _8 + _4;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:104:22
@@ -407,6 +464,9 @@ LL | type _T43 = dyn _4 + _8;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:107:36
@@ -428,6 +488,9 @@ LL | type _T44 = dyn _4 + Send + Sync + _8;
    |                 --                 ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:117:22
@@ -440,6 +503,9 @@ LL | type _T50 = dyn _9 + _10;
    |                 --   ^^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-duplicates.rs:123:23
@@ -452,6 +518,9 @@ LL | type _T60 = dyn _11 + _12;
    |                 ---   ^^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error: aborting due to 27 previous errors
 
index 15685a228833d69184a4e27e11748e519f244765..1d7b3fa112b007a7a290aa23943eaccf2e5f6a08 100644 (file)
@@ -5,11 +5,12 @@ LL | trait _0 = ObjA;
    |            ---- first non-auto trait
 ...
 LL | type _T00 = dyn _0 + ObjB;
-   |                 --   ^^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:19:24
@@ -21,7 +22,9 @@ LL | type _T01 = dyn ObjB + _0;
    |                 ----   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:22:24
@@ -35,7 +38,9 @@ LL | type _T02 = dyn ObjB + _1;
    |                 ----   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:25:22
@@ -46,11 +51,12 @@ LL | trait _1 = _0;
    |            -- referenced here (first use)
 ...
 LL | type _T03 = dyn _1 + ObjB;
-   |                 --   ^^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:34:22
@@ -67,6 +73,9 @@ LL | type _T10 = dyn _2 + _3;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:37:22
@@ -83,6 +92,9 @@ LL | type _T11 = dyn _3 + _2;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:40:22
@@ -101,6 +113,9 @@ LL | type _T12 = dyn _2 + _4;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:43:22
@@ -119,6 +134,9 @@ LL | type _T13 = dyn _4 + _2;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:50:22
@@ -135,6 +153,9 @@ LL | type _T20 = dyn _5 + _1;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:53:22
@@ -151,6 +172,9 @@ LL | type _T21 = dyn _1 + _5;
    |                 --   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:56:22
@@ -159,11 +183,12 @@ LL | trait _5 = Sync + ObjB + Send;
    |                   ---- first non-auto trait
 ...
 LL | type _T22 = dyn _5 + ObjA;
-   |                 --   ^^^^
-   |                 |    |
-   |                 |    additional non-auto trait
-   |                 |    trait alias used in trait object type (additional use)
+   |                 --   ^^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:59:24
@@ -175,7 +200,9 @@ LL | type _T23 = dyn ObjA + _5;
    |                 ----   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:62:29
@@ -192,6 +219,9 @@ LL | type _T24 = dyn Send + _5 + _1 + Sync;
    |                        --   ^^ trait alias used in trait object type (additional use)
    |                        |
    |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:65:29
@@ -208,6 +238,9 @@ LL | type _T25 = dyn _1 + Sync + _5 + Send;
    |                 --          ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:68:36
@@ -216,11 +249,12 @@ LL | trait _5 = Sync + ObjB + Send;
    |                   ---- first non-auto trait
 ...
 LL | type _T26 = dyn Sync + Send + _5 + ObjA;
-   |                               --   ^^^^
-   |                               |    |
-   |                               |    additional non-auto trait
-   |                               |    trait alias used in trait object type (additional use)
+   |                               --   ^^^^ additional non-auto trait
+   |                               |
    |                               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:71:38
@@ -232,7 +266,9 @@ LL | type _T27 = dyn Send + Sync + ObjA + _5;
    |                               ----   ^^ trait alias used in trait object type (additional use)
    |                               |
    |                               first non-auto trait
-   |                               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:80:17
@@ -255,6 +291,9 @@ LL | type _T30 = dyn _6;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:83:17
@@ -277,6 +316,9 @@ LL | type _T31 = dyn _6 + Send;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:86:24
@@ -299,6 +341,9 @@ LL | type _T32 = dyn Send + _6;
    |                        |
    |                        trait alias used in trait object type (additional use)
    |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:89:17
@@ -331,6 +376,9 @@ LL | type _T33 = dyn _8;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:92:17
@@ -363,6 +411,9 @@ LL | type _T34 = dyn _8 + Send;
    |                 |
    |                 trait alias used in trait object type (additional use)
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:95:24
@@ -395,6 +446,9 @@ LL | type _T35 = dyn Send + _8;
    |                        |
    |                        trait alias used in trait object type (additional use)
    |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:103:23
@@ -408,11 +462,12 @@ LL | trait _10 = Unpin + _9;
    |                     -- referenced here (first use)
 LL | 
 LL | type _T40 = dyn _10 + ObjA;
-   |                 ---   ^^^^
-   |                 |     |
-   |                 |     additional non-auto trait
-   |                 |     trait alias used in trait object type (additional use)
+   |                 ---   ^^^^ additional non-auto trait
+   |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:106:24
@@ -429,7 +484,9 @@ LL | type _T41 = dyn ObjA + _10;
    |                 ----   ^^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:109:23
@@ -451,6 +508,9 @@ LL | type _T42 = dyn _10 + _1;
    |                 ---   ^^ trait alias used in trait object type (additional use)
    |                 |
    |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:112:37
@@ -464,11 +524,12 @@ LL | trait _10 = Unpin + _9;
    |                     -- referenced here (first use)
 ...
 LL | type _T43 = dyn Send + _10 + Sync + ObjA;
-   |                        ---          ^^^^
-   |                        |            |
-   |                        |            additional non-auto trait
-   |                        |            trait alias used in trait object type (additional use)
+   |                        ---          ^^^^ additional non-auto trait
+   |                        |
    |                        trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:115:24
@@ -485,7 +546,9 @@ LL | type _T44 = dyn ObjA + _10 + Send + Sync;
    |                 ----   ^^^ trait alias used in trait object type (additional use)
    |                 |
    |                 first non-auto trait
-   |                 trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/trait-alias-no-extra-traits.rs:118:37
@@ -507,6 +570,9 @@ LL | type _T45 = dyn Sync + Send + _10 + _1;
    |                               ---   ^^ trait alias used in trait object type (additional use)
    |                               |
    |                               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error: aborting due to 28 previous errors
 
index 269d92fe43db80aff783a3bcdfc476efc389233f..ed5409d01596ace0b9fd238b611c51af61c30596 100644 (file)
@@ -2,56 +2,56 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
   --> $DIR/wf-trait-object-no-duplicates.rs:8:21
    |
 LL | type _0 = dyn Obj + Obj;
-   |               ---   ^^^
-   |               |     |
-   |               |     additional non-auto trait
-   |               |     trait alias used in trait object type (additional use)
+   |               ---   ^^^ additional non-auto trait
+   |               |
    |               first non-auto trait
-   |               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/wf-trait-object-no-duplicates.rs:13:28
    |
 LL | type _1 = dyn Send + Obj + Obj;
-   |                      ---   ^^^
-   |                      |     |
-   |                      |     additional non-auto trait
-   |                      |     trait alias used in trait object type (additional use)
+   |                      ---   ^^^ additional non-auto trait
+   |                      |
    |                      first non-auto trait
-   |                      trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/wf-trait-object-no-duplicates.rs:16:28
    |
 LL | type _2 = dyn Obj + Send + Obj;
-   |               ---          ^^^
-   |               |            |
-   |               |            additional non-auto trait
-   |               |            trait alias used in trait object type (additional use)
+   |               ---          ^^^ additional non-auto trait
+   |               |
    |               first non-auto trait
-   |               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/wf-trait-object-no-duplicates.rs:26:34
    |
 LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>;
-   |               ----------------   ^^^^^^^^^^^^^^^^
-   |               |                  |
-   |               |                  additional non-auto trait
-   |               |                  trait alias used in trait object type (additional use)
+   |               ----------------   ^^^^^^^^^^^^^^^^ additional non-auto trait
+   |               |
    |               first non-auto trait
-   |               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error[E0225]: only auto traits can be used as additional traits in a trait object
   --> $DIR/wf-trait-object-no-duplicates.rs:30:42
    |
 LL | type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>;
-   |               ------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^
-   |               |                          |
-   |               |                          additional non-auto trait
-   |               |                          trait alias used in trait object type (additional use)
+   |               ------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait
+   |               |
    |               first non-auto trait
-   |               trait alias used in trait object type (first use)
+   |
+   = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+   = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/unknown-llvm-arg.rs b/src/test/ui/unknown-llvm-arg.rs
new file mode 100644 (file)
index 0000000..289bae2
--- /dev/null
@@ -0,0 +1,22 @@
+// compile-flags: -Cllvm-args=-not-a-real-llvm-arg
+// normalize-stderr-test "--help" -> "-help"
+// normalize-stderr-test "\n(\n|.)*" -> ""
+
+// I'm seeing "--help" locally, but "-help" in CI, so I'm normalizing it to just "-help".
+
+// Note that the rustc-supplied "program name", given when invoking LLVM, is used by LLVM to
+// generate user-facing error messages and a usage (--help) messages. If the program name is
+// `rustc`, the usage message in response to `--llvm-args="--help"` starts with:
+// ```
+//   USAGE: rustc [options]
+// ```
+// followed by the list of options not to `rustc` but to `llvm`.
+//
+// On the other hand, if the program name is set to `rustc -Cllvm-args="..." with`, the usage
+// message is more clear:
+// ```
+//   USAGE: rustc -Cllvm-args="..." with [options]
+// ```
+// This test captures the effect of the current program name setting on LLVM command line
+// error messages.
+fn main() {}
diff --git a/src/test/ui/unknown-llvm-arg.stderr b/src/test/ui/unknown-llvm-arg.stderr
new file mode 100644 (file)
index 0000000..e1d3cfe
--- /dev/null
@@ -0,0 +1 @@
+rustc -Cllvm-args="..." with: Unknown command line argument '-not-a-real-llvm-arg'.  Try: 'rustc -Cllvm-args="..." with -help'
\ No newline at end of file
index 5dede95a85823d63734eb9a4f28850b533ef02c0..58022484fa6cceee20fd42d053297c97e20f9cc1 100644 (file)
@@ -447,6 +447,7 @@ fn add_packages_to(&mut self, manifest: &mut Manifest) {
         let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets);
         package("rustc", HOSTS);
         package("rustc-dev", HOSTS);
+        package("rustc-docs", HOSTS);
         package("cargo", HOSTS);
         package("rust-mingw", MINGW);
         package("rust-std", TARGETS);
@@ -500,6 +501,7 @@ fn add_profiles_to(&mut self, manifest: &mut Manifest) {
         // for users to install the additional component manually, if needed.
         if self.rust_release == "nightly" {
             self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
+            self.extend_profile("complete", &mut manifest.profiles, &["rustc-docs"]);
         }
     }
 
@@ -575,6 +577,7 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option
                 .map(|target| Component::from_str("rust-std", target)),
         );
         extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target)));
+        extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target)));
         extensions.push(Component::from_str("rust-src", "*"));
 
         // If the components/extensions don't actually exist for this
index 80a0675898240633e73830d6dc6a649df326c7ef..58b0704294b566622dd6028c290066e5dd605f7b 100644 (file)
@@ -224,7 +224,7 @@ fn check_hash_peq<'tcx>(
                         mess,
                         |diag| {
                             if let Some(local_def_id) = impl_id.as_local() {
-                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
                                 diag.span_note(
                                     cx.tcx.hir().span(hir_id),
                                     "`PartialEq` implemented here"
@@ -278,7 +278,7 @@ fn check_ord_partial_ord<'tcx>(
                         mess,
                         |diag| {
                             if let Some(local_def_id) = impl_id.as_local() {
-                                let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+                                let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
                                 diag.span_note(
                                     cx.tcx.hir().span(hir_id),
                                     "`PartialOrd` implemented here"
@@ -341,7 +341,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
     ty: Ty<'tcx>,
 ) {
     fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
-        let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
+        let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
         cx.tcx.hir().expect_item(hir_id)
     }
 
@@ -355,7 +355,7 @@ fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
         if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE);
         if let ty::Adt(def, _) = ty.kind;
         if let Some(local_def_id) = def.did.as_local();
-        let adt_hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+        let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
         if !is_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
         if cx.tcx.inherent_impls(def.did)
             .iter()
index 621ebdef2f0b17462cbabee5e277f369899cf47a..28d1322e94626c604cced668546593bb2193e02e 100644 (file)
@@ -103,7 +103,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
                                         cx.tcx.for_each_impl(default_trait_id, |d| {
                                             if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
                                                 if let Some(local_def_id) = ty_def.did.as_local() {
-                                                    impls.insert(cx.tcx.hir().as_local_hir_id(local_def_id));
+                                                    impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
                                                 }
                                             }
                                         });
index bd4c5949800f698dbcbc282841b195fc0eb53ebc..c601084d11917acff620fb1230531e92fed0e4f8 100644 (file)
@@ -8,7 +8,7 @@ edition = "2018"
 diff = "0.1.10"
 env_logger = { version = "0.7", default-features = false }
 getopts = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
 regex = "1.0"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
index 8f685fb8559f5a7d834b5fbddc85f120e2431ed3..8edc9c9cd038e5c2694a613aa878988e8adac16a 100644 (file)
@@ -8,8 +8,8 @@
 use std::str::FromStr;
 
 use lazy_static::lazy_static;
-use log::*;
 use regex::Regex;
+use tracing::*;
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum ErrorKind {
index edbb83726333b91f42cceda57dcaeb8303cc1c21..90a0d8926ad94bfa88e0915422c125131baac92d 100644 (file)
@@ -5,7 +5,7 @@
 use std::io::BufReader;
 use std::path::{Path, PathBuf};
 
-use log::*;
+use tracing::*;
 
 use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode};
 use crate::extract_gdb_version;
index bf3510ea0894bfeb74b01b7de1a5fb731dbdc61d..46e16393a24c1c49e3be4fa63b98dfd621f63523 100644 (file)
@@ -9,7 +9,6 @@
 use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, Pretty, TestPaths};
 use crate::util::logv;
 use getopts::Options;
-use log::*;
 use std::env;
 use std::ffi::OsString;
 use std::fs;
@@ -18,6 +17,7 @@
 use std::process::Command;
 use std::time::SystemTime;
 use test::ColorConfig;
+use tracing::*;
 use walkdir::WalkDir;
 
 use self::header::EarlyProps;
index 7f49cb913b125244db5fbe4de6e1c479210e4cd5..03136921ad626b83f937a99c042062381043c2c5 100644 (file)
@@ -30,7 +30,7 @@
 
 use glob::glob;
 use lazy_static::lazy_static;
-use log::*;
+use tracing::*;
 
 use crate::extract_gdb_version;
 use crate::is_android_gdb_target;
index ddd7941b11469d973f70c7201c6f2d62a7659b41..cc4b21f9efb450667f33c59a62b99d5cce729aae 100644 (file)
@@ -3,7 +3,7 @@
 use std::ffi::OsStr;
 use std::path::PathBuf;
 
-use log::*;
+use tracing::*;
 
 #[cfg(test)]
 mod tests;
@@ -87,6 +87,7 @@
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
     "x86_64-fuchsia",
+    "x86_64-unknown-freebsd",
     "x86_64-unknown-linux-gnu",
 ];
 
     &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
 
 pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] =
-    &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
+    &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
 
-pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] =
-    &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
+    "aarch64-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-unknown-freebsd",
+    "x86_64-unknown-linux-gnu",
+];
 
 const BIG_ENDIAN: &'static [&'static str] = &[
     "armebv7r",
index 8fe89095ae99facec08e89f456619ec1caa44665..707e381b06e47b840cd15e6e90cbcfda5015f187 100644 (file)
@@ -99,94 +99,3 @@ message_on_add = """\
 - Needs `I-nominated`?
 """
 message_on_remove = "Issue #{number}'s prioritization request has been removed."
-
-[notify-zulip."I-nominated"]
-required_labels = ["T-compiler"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "I-nominated #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-i-nominated-issues)
-- Already discussed?
-- Worth the meeting time?
-- Add agenda entry:
-  - Why nominated?
-  - Assignee?
-  - Issue? PR? What's the status?
-  - Summary and important details?
-"""
-message_on_remove = "#{number}'s nomination has been removed."
-
-[notify-zulip."beta-nominated"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "Backport #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} has been requested for beta backport.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
-Prepare agenda entry:
-- Why nominated?
-- Author, assignee?
-- Important details?
-"""
-message_on_remove = "PR #{number}'s beta backport request has been removed."
-
-[notify-zulip."stable-nominated"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "Backport #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} has been requested for stable backport.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
-Prepare agenda entry:
-- Why nominated?
-- Author, assignee?
-- Important details?
-"""
-message_on_remove = "PR #{number}'s stable backport request has been removed."
-
-[notify-zulip."S-waiting-on-team"]
-required_labels = ["T-compiler"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "S-waiting-on-team #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} is waiting on `T-compiler`.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-prs-waiting-on-team)
-- Prepare agenda entry:
-  - What is it waiting for?
-  - Important details?
-- Could be resolved quickly? Tag `I-nominated`.
-"""
-message_on_remove = "PR #{number}'s is no longer waiting on `T-compiler`."
-
-[notify-zulip."P-critical"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "P-critical #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* issue #{number} has been assigned `P-critical`.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
-- Notify people/groups?
-- Assign if possible?
-- Add to agenda:
-  - Assignee?
-  - Summary and important details?
-- Other actions to move forward?
-"""
-
-[notify-zulip."P-high"]
-required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "P-high regression #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* issue #{number} has been assigned `P-high` and is a regression.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
-Is issue assigned? If not:
-- Try to find an assignee?
-- Otherwise add to agenda:
-  - Mark as unassigned.
-  - Summary and important details?
-"""