]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #74784 - anp:track-vtables, r=eddyb
authorbors <bors@rust-lang.org>
Mon, 27 Jul 2020 03:47:17 +0000 (03:47 +0000)
committerbors <bors@rust-lang.org>
Mon, 27 Jul 2020 03:47:17 +0000 (03:47 +0000)
Fix #[track_caller] shims for trait objects.

We were missing an Instance::resolve_for_fn_ptr in resolve_for_vtable.

Closes #74764.

589 files changed:
.github/workflows/ci.yml
.gitmodules
Cargo.lock
Cargo.toml
rustfmt.toml
src/backtrace [deleted submodule]
src/bootstrap/builder.rs
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/install.rs
src/build_helper/lib.rs
src/ci/azure-pipelines/auto.yml
src/ci/azure-pipelines/master.yml [deleted file]
src/ci/azure-pipelines/pr.yml [deleted file]
src/ci/azure-pipelines/try.yml
src/ci/docker/README.md
src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/002-newer-gcc.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch [deleted file]
src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/002-newer-gcc.patch [deleted file]
src/ci/docker/host-x86_64/dist-powerpc-linux/powerpc-linux-gnu.config
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/002-Prevent-inlining-in-PPC64-initfini.s.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/003-newer-gcc.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch [deleted file]
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch [deleted file]
src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/003-newer-gcc.patch [deleted file]
src/ci/docker/host-x86_64/dist-powerpc64-linux/powerpc64-linux-gnu.config
src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/002-newer-gcc.patch [new file with mode: 0644]
src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch [deleted file]
src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/002-newer-gcc.patch [deleted file]
src/ci/docker/host-x86_64/dist-s390x-linux/s390x-linux-gnu.config
src/ci/github-actions/ci.yml
src/doc/book
src/doc/edition-guide
src/doc/reference
src/doc/rustc/src/codegen-options/index.md
src/doc/unstable-book/src/compiler-flags/sanitizer.md
src/liballoc/boxed.rs
src/liballoc/collections/binary_heap.rs
src/liballoc/collections/btree/map.rs
src/liballoc/collections/linked_list.rs
src/liballoc/collections/vec_deque.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/liballoc/string.rs
src/liballoc/sync.rs
src/liballoc/tests/btree/map.rs
src/liballoc/vec.rs
src/libcore/alloc/layout.rs
src/libcore/array/iter.rs
src/libcore/array/mod.rs
src/libcore/convert/mod.rs
src/libcore/fmt/rt/v1.rs
src/libcore/hash/sip.rs
src/libcore/intrinsics.rs
src/libcore/iter/range.rs
src/libcore/iter/traits/iterator.rs
src/libcore/macros/mod.rs
src/libcore/mem/mod.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/mod.rs
src/libcore/ops/function.rs
src/libcore/ops/range.rs
src/libcore/pin.rs
src/libcore/ptr/const_ptr.rs
src/libcore/ptr/mut_ptr.rs
src/libcore/ptr/non_null.rs
src/libcore/slice/mod.rs
src/libcore/slice/sort.rs
src/libcore/tests/num/int_macros.rs
src/libcore/tests/num/uint_macros.rs
src/libcore/tests/slice.rs
src/libpanic_unwind/miri.rs
src/libprofiler_builtins/Cargo.toml
src/libprofiler_builtins/build.rs
src/librustc_ast/build.rs [deleted file]
src/librustc_ast_lowering/expr.rs
src/librustc_ast_lowering/lib.rs
src/librustc_ast_passes/ast_validation.rs
src/librustc_attr/Cargo.toml
src/librustc_attr/build.rs [deleted file]
src/librustc_attr/builtin.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/build.rs [deleted file]
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/callee.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/mono_item.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_llvm/va_arg.rs
src/librustc_codegen_ssa/back/link.rs
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/build.rs [deleted file]
src/librustc_codegen_ssa/debuginfo/type_names.rs
src/librustc_codegen_ssa/meth.rs
src/librustc_codegen_ssa/mir/analyze.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/mir/rvalue.rs
src/librustc_codegen_ssa/traits/type_.rs
src/librustc_data_structures/sorted_map/index_map.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_driver/build.rs [deleted file]
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes/E0719.md
src/librustc_error_codes/error_codes/E0724.md
src/librustc_error_codes/error_codes/E0727.md
src/librustc_error_codes/error_codes/E0771.md [new file with mode: 0644]
src/librustc_expand/base.rs
src/librustc_expand/expand.rs
src/librustc_feature/accepted.rs
src/librustc_feature/builtin_attrs.rs
src/librustc_hir/hir.rs
src/librustc_incremental/build.rs [deleted file]
src/librustc_index/bit_set.rs
src/librustc_index/lib.rs
src/librustc_infer/infer/combine.rs
src/librustc_infer/infer/error_reporting/mod.rs
src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
src/librustc_infer/infer/error_reporting/nice_region_error/util.rs
src/librustc_infer/infer/mod.rs
src/librustc_infer/lib.rs
src/librustc_interface/build.rs [deleted file]
src/librustc_interface/tests.rs
src/librustc_llvm/Cargo.toml
src/librustc_llvm/build.rs
src/librustc_metadata/build.rs [deleted file]
src/librustc_metadata/creader.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/rmeta/decoder.rs
src/librustc_metadata/rmeta/decoder/cstore_impl.rs
src/librustc_metadata/rmeta/encoder.rs
src/librustc_metadata/rmeta/mod.rs
src/librustc_metadata/rmeta/table.rs
src/librustc_middle/build.rs [deleted file]
src/librustc_middle/ich/hcx.rs
src/librustc_middle/ich/impls_hir.rs
src/librustc_middle/lib.rs
src/librustc_middle/lint.rs
src/librustc_middle/middle/stability.rs
src/librustc_middle/mir/interpret/allocation.rs
src/librustc_middle/mir/interpret/value.rs
src/librustc_middle/mir/mono.rs
src/librustc_middle/query/mod.rs
src/librustc_middle/traits/mod.rs
src/librustc_middle/traits/specialization_graph.rs
src/librustc_middle/traits/structural_impls.rs
src/librustc_middle/ty/flags.rs
src/librustc_middle/ty/instance.rs
src/librustc_middle/ty/layout.rs
src/librustc_middle/ty/mod.rs
src/librustc_middle/ty/normalize_erasing_regions.rs
src/librustc_middle/ty/print/obsolete.rs
src/librustc_middle/ty/query/mod.rs
src/librustc_middle/ty/query/on_disk_cache.rs
src/librustc_middle/ty/sty.rs
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
src/librustc_mir/borrow_check/diagnostics/region_name.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/const_eval/eval_queries.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/monomorphize/polymorphize.rs [new file with mode: 0644]
src/librustc_mir/shim.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir_build/build/expr/into.rs
src/librustc_mir_build/build/mod.rs
src/librustc_mir_build/hair/pattern/_match.rs
src/librustc_mir_build/hair/pattern/mod.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/expr.rs
src/librustc_parse/parser/path.rs
src/librustc_passes/stability.rs
src/librustc_resolve/build_reduced_graph.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_resolve/macros.rs
src/librustc_save_analysis/lib.rs
src/librustc_session/config.rs
src/librustc_session/options.rs
src/librustc_session/session.rs
src/librustc_span/def_id.rs
src/librustc_span/hygiene.rs
src/librustc_span/lib.rs
src/librustc_span/symbol.rs
src/librustc_symbol_mangling/legacy.rs
src/librustc_target/abi/mod.rs
src/librustc_target/build.rs [deleted file]
src/librustc_target/spec/aarch64_apple_darwin.rs [new file with mode: 0644]
src/librustc_target/spec/apple_base.rs
src/librustc_target/spec/freestanding_base.rs
src/librustc_target/spec/illumos_base.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/msp430_none_elf.rs
src/librustc_target/spec/riscv32i_unknown_none_elf.rs
src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
src/librustc_target/spec/riscv32imc_unknown_none_elf.rs
src/librustc_target/spec/riscv64gc_unknown_none_elf.rs
src/librustc_target/spec/riscv64imac_unknown_none_elf.rs
src/librustc_target/spec/solaris_base.rs
src/librustc_target/spec/windows_gnu_base.rs
src/librustc_target/spec/x86_64_apple_darwin.rs
src/librustc_trait_selection/traits/codegen/mod.rs
src/librustc_trait_selection/traits/coherence.rs
src/librustc_trait_selection/traits/error_reporting/suggestions.rs
src/librustc_trait_selection/traits/mod.rs
src/librustc_trait_selection/traits/wf.rs
src/librustc_ty/instance.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/ayu.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/passes/collect_intra_doc_links.rs
src/libstd/Cargo.toml
src/libstd/backtrace.rs
src/libstd/build.rs
src/libstd/collections/mod.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/io/mod.rs
src/libstd/keyword_docs.rs
src/libstd/lib.rs
src/libstd/os/linux/fs.rs
src/libstd/os/redox/fs.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/primitive_docs.rs
src/libstd/sys/hermit/condvar.rs
src/libstd/sys/hermit/rwlock.rs
src/libstd/sys/sgx/fd.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/fd.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/weak.rs
src/libstd/sys/vxworks/fd.rs
src/libstd/sys/vxworks/time.rs
src/libstd/sys/wasi/ext/mod.rs
src/libstd/sys/wasi/fs.rs
src/libstd/sys/windows/thread_local_key.rs
src/libstd/sys_common/backtrace.rs
src/libunwind/Cargo.toml
src/test/codegen-units/item-collection/static-init.rs
src/test/codegen-units/item-collection/trait-method-default-impl.rs
src/test/codegen-units/polymorphization/unused_type_parameters.rs [new file with mode: 0644]
src/test/codegen/abi-efiapi.rs
src/test/codegen/avr/avr-func-addrspace.rs [new file with mode: 0644]
src/test/codegen/cfguard-checks.rs
src/test/codegen/cfguard-disabled.rs
src/test/codegen/cfguard-nochecks.rs
src/test/codegen/cfguard-non-msvc.rs
src/test/codegen/force-unwind-tables.rs
src/test/codegen/issue-69101-bounds-check.rs
src/test/codegen/unchecked-float-casts.rs
src/test/codegen/wasm_casts_trapping.rs
src/test/debuginfo/function-call.rs
src/test/debuginfo/pretty-huge-vec.rs
src/test/debuginfo/pretty-std-collections.rs
src/test/debuginfo/pretty-std.rs
src/test/debuginfo/pretty-uninitialized-vec.rs
src/test/incremental/hygiene/auxiliary/cached_hygiene.rs [new file with mode: 0644]
src/test/incremental/hygiene/load_cached_hygiene.rs [new file with mode: 0644]
src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/boolean_identities.rs [new file with mode: 0644]
src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff [new file with mode: 0644]
src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/mult_by_zero.rs [new file with mode: 0644]
src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff [new file with mode: 0644]
src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff
src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff
src/test/mir-opt/match-arm-scopes.rs
src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir [deleted file]
src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff [new file with mode: 0644]
src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir [deleted file]
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/checkrust.rs
src/test/run-make-fulldeps/c-link-to-rust-va-list-fn/test.c
src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
src/test/rustdoc-ui/intra-doc-alias-ice.stderr
src/test/rustdoc-ui/intra-link-span-ice-55723.rs
src/test/rustdoc-ui/intra-link-span-ice-55723.stderr
src/test/rustdoc-ui/intra-links-anchors.rs
src/test/rustdoc-ui/intra-links-anchors.stderr
src/test/rustdoc-ui/intra-links-private.private.stderr [new file with mode: 0644]
src/test/rustdoc-ui/intra-links-private.public.stderr
src/test/rustdoc-ui/intra-links-private.rs
src/test/rustdoc-ui/intra-links-warning-crlf.rs
src/test/rustdoc-ui/intra-links-warning-crlf.stderr
src/test/rustdoc-ui/intra-links-warning.rs
src/test/rustdoc-ui/intra-links-warning.stderr
src/test/rustdoc-ui/issue-74134.private.stderr [new file with mode: 0644]
src/test/rustdoc-ui/issue-74134.public.stderr
src/test/rustdoc-ui/issue-74134.rs
src/test/rustdoc-ui/lint-group.rs
src/test/rustdoc-ui/lint-group.stderr
src/test/rustdoc/auxiliary/unstable-trait.rs [new file with mode: 0644]
src/test/rustdoc/hide-unstable-trait.rs [new file with mode: 0644]
src/test/ui/associated-type-bounds/issue-73818.rs [new file with mode: 0644]
src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs
src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr
src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
src/test/ui/associated-types/issue-62200.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-62200.stderr [new file with mode: 0644]
src/test/ui/async-await/issues/issue-62097.rs
src/test/ui/async-await/issues/issue-62097.stderr
src/test/ui/cfguard-run.rs
src/test/ui/closure-expected.stderr
src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
src/test/ui/const-generics/argument_order.rs
src/test/ui/const-generics/argument_order.stderr
src/test/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs [deleted file]
src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr [deleted file]
src/test/ui/const-generics/array-impls/alloc-types-impls-length-33.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs [deleted file]
src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr [deleted file]
src/test/ui/const-generics/array-impls/core-traits-impls-length-33.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs [deleted file]
src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr [deleted file]
src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs [new file with mode: 0644]
src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs [deleted file]
src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr [deleted file]
src/test/ui/const-generics/broken-mir-2.rs
src/test/ui/const-generics/broken-mir-2.stderr
src/test/ui/const-generics/const-argument-non-static-lifetime.rs [new file with mode: 0644]
src/test/ui/const-generics/const-argument-non-static-lifetime.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/wrong-order.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/wrong-order.stderr [new file with mode: 0644]
src/test/ui/const-generics/derive-debug-array-wrapper.rs
src/test/ui/const-generics/derive-debug-array-wrapper.stderr
src/test/ui/const-generics/issues/issue-56445.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-56445.stderr [new file with mode: 0644]
src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
src/test/ui/consts/issue-73976-monomorphic.rs [new file with mode: 0644]
src/test/ui/consts/issue-73976-polymorphic.rs [new file with mode: 0644]
src/test/ui/consts/issue-73976-polymorphic.stderr [new file with mode: 0644]
src/test/ui/consts/too_generic_eval_ice.rs
src/test/ui/consts/too_generic_eval_ice.stderr
src/test/ui/error-codes/E0308-2.rs [new file with mode: 0644]
src/test/ui/error-codes/E0308-2.stderr [new file with mode: 0644]
src/test/ui/error-codes/E0771.rs [new file with mode: 0644]
src/test/ui/error-codes/E0771.stderr [new file with mode: 0644]
src/test/ui/extern/extern-wrong-value-type.stderr
src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
src/test/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr
src/test/ui/generic-associated-types/issue-68643-broken-mir.stderr
src/test/ui/generic-associated-types/issue-68644-codegen-selection.stderr
src/test/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr
src/test/ui/hygiene/auxiliary/needs_hygiene.rs [new file with mode: 0644]
src/test/ui/hygiene/auxiliary/nested-dollar-crate.rs [new file with mode: 0644]
src/test/ui/hygiene/cross_crate_hygiene.rs [new file with mode: 0644]
src/test/ui/hygiene/nested-dollar-crate.rs [new file with mode: 0644]
src/test/ui/hygiene/panic-location.rs [new file with mode: 0644]
src/test/ui/hygiene/panic-location.run.stderr [new file with mode: 0644]
src/test/ui/impl-header-lifetime-elision/dyn-trait.rs
src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
src/test/ui/impl-trait/issue-72911.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-72911.stderr [new file with mode: 0644]
src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr
src/test/ui/impl-trait/static-return-lifetime-infered.rs
src/test/ui/impl-trait/static-return-lifetime-infered.stderr
src/test/ui/issue-74047.rs [new file with mode: 0644]
src/test/ui/issue-74047.stderr [new file with mode: 0644]
src/test/ui/issues/issue-16922.rs
src/test/ui/issues/issue-16922.stderr
src/test/ui/issues/issue-21837.stderr
src/test/ui/issues/issue-22034.stderr
src/test/ui/issues/issue-74539.rs [new file with mode: 0644]
src/test/ui/issues/issue-74539.stderr [new file with mode: 0644]
src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs [new file with mode: 0644]
src/test/ui/issues/issue-74614.rs [new file with mode: 0644]
src/test/ui/iterators/into-iter-on-arrays-lint.fixed
src/test/ui/iterators/into-iter-on-arrays-lint.rs
src/test/ui/iterators/into-iter-on-arrays-lint.stderr
src/test/ui/lint/lint-ctypes.rs
src/test/ui/lint/lint-ctypes.stderr
src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
src/test/ui/polymorphization/const_parameters/closures.rs [new file with mode: 0644]
src/test/ui/polymorphization/const_parameters/closures.stderr [new file with mode: 0644]
src/test/ui/polymorphization/const_parameters/functions.rs [new file with mode: 0644]
src/test/ui/polymorphization/const_parameters/functions.stderr [new file with mode: 0644]
src/test/ui/polymorphization/drop_shims/simple.rs [new file with mode: 0644]
src/test/ui/polymorphization/drop_shims/transitive.rs [new file with mode: 0644]
src/test/ui/polymorphization/generators.rs [new file with mode: 0644]
src/test/ui/polymorphization/generators.stderr [new file with mode: 0644]
src/test/ui/polymorphization/lifetimes.rs [new file with mode: 0644]
src/test/ui/polymorphization/lifetimes.stderr [new file with mode: 0644]
src/test/ui/polymorphization/normalized_sig_types.rs [new file with mode: 0644]
src/test/ui/polymorphization/predicates.rs [new file with mode: 0644]
src/test/ui/polymorphization/predicates.stderr [new file with mode: 0644]
src/test/ui/polymorphization/promoted-function.rs [new file with mode: 0644]
src/test/ui/polymorphization/too-many-generic-params.rs [new file with mode: 0644]
src/test/ui/polymorphization/type_parameters/closures.rs [new file with mode: 0644]
src/test/ui/polymorphization/type_parameters/closures.stderr [new file with mode: 0644]
src/test/ui/polymorphization/type_parameters/functions.rs [new file with mode: 0644]
src/test/ui/polymorphization/type_parameters/functions.stderr [new file with mode: 0644]
src/test/ui/polymorphization/unsized_cast.rs [new file with mode: 0644]
src/test/ui/polymorphization/unsized_cast.stderr [new file with mode: 0644]
src/test/ui/print_type_sizes/niche-filling.stdout
src/test/ui/proc-macro/auxiliary/make-macro.rs
src/test/ui/proc-macro/auxiliary/meta-macro.rs
src/test/ui/proc-macro/dollar-crate-issue-57089.rs
src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
src/test/ui/proc-macro/dollar-crate-issue-62325.rs
src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
src/test/ui/proc-macro/dollar-crate.rs
src/test/ui/proc-macro/dollar-crate.stdout
src/test/ui/proc-macro/input-interpolated.rs
src/test/ui/proc-macro/input-interpolated.stdout
src/test/ui/proc-macro/meta-macro-hygiene.rs
src/test/ui/proc-macro/meta-macro-hygiene.stdout
src/test/ui/proc-macro/meta-macro.rs
src/test/ui/proc-macro/meta-macro.stdout
src/test/ui/proc-macro/nested-macro-rules.rs
src/test/ui/proc-macro/nested-macro-rules.stdout
src/test/ui/proc-macro/nodelim-groups.rs
src/test/ui/proc-macro/nodelim-groups.stdout
src/test/ui/regions/region-object-lifetime-in-coercion.rs
src/test/ui/regions/region-object-lifetime-in-coercion.stderr
src/test/ui/regions/regions-addr-of-self.rs
src/test/ui/regions/regions-addr-of-self.stderr
src/test/ui/regions/regions-close-object-into-object-2.rs
src/test/ui/regions/regions-close-object-into-object-2.stderr
src/test/ui/regions/regions-close-object-into-object-4.rs
src/test/ui/regions/regions-close-object-into-object-4.stderr
src/test/ui/regions/regions-proc-bound-capture.rs
src/test/ui/regions/regions-proc-bound-capture.stderr
src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs [new file with mode: 0644]
src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.rs
src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs [new file with mode: 0644]
src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/stability-attribute-sanity.rs
src/test/ui/stability-attribute/stability-attribute-sanity.stderr
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs [new file with mode: 0644]
src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr [new file with mode: 0644]
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.rs
src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs [new file with mode: 0644]
src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr [new file with mode: 0644]
src/test/ui/traits/issue-72410.rs [new file with mode: 0644]
src/test/ui/traits/issue-72410.stderr [new file with mode: 0644]
src/test/ui/type-sizes.rs
src/test/ui/typeck/typeck_type_placeholder_item.rs
src/test/ui/typeck/typeck_type_placeholder_item.stderr
src/test/ui/underscore-lifetime/dyn-trait-underscore.rs
src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
src/test/ui/unsized/unsized-trait-impl-self-type.stderr
src/test/ui/wf/wf-foreign-fn-decl-ret.rs [new file with mode: 0644]
src/test/ui/wf/wf-foreign-fn-decl-ret.stderr [new file with mode: 0644]
src/test/ui/wf/wf-impl-self-type.rs [new file with mode: 0644]
src/test/ui/wf/wf-impl-self-type.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/clippy/.github/deploy.sh
src/tools/clippy/CHANGELOG.md
src/tools/clippy/README.md
src/tools/clippy/clippy_lints/src/deprecated_lints.rs
src/tools/clippy/clippy_lints/src/dereference.rs
src/tools/clippy/clippy_lints/src/inherent_impl.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/misc_early.rs
src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/option_if_let_else.rs
src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
src/tools/clippy/clippy_lints/src/redundant_clone.rs
src/tools/clippy/clippy_lints/src/redundant_closure_call.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/shadow.rs
src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/useless_conversion.rs
src/tools/clippy/clippy_lints/src/utils/mod.rs
src/tools/clippy/clippy_lints/src/utils/numeric_literal.rs
src/tools/clippy/clippy_lints/src/utils/paths.rs
src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
src/tools/clippy/src/lintlist/mod.rs
src/tools/clippy/tests/ui/iter_nth_zero.stderr
src/tools/clippy/tests/ui/manual_async_fn.fixed
src/tools/clippy/tests/ui/manual_async_fn.rs
src/tools/clippy/tests/ui/manual_async_fn.stderr
src/tools/clippy/tests/ui/needless_range_loop2.rs
src/tools/clippy/tests/ui/never_loop.rs
src/tools/clippy/tests/ui/panicking_macros.rs
src/tools/clippy/tests/ui/panicking_macros.stderr
src/tools/clippy/tests/ui/precedence.fixed
src/tools/clippy/tests/ui/precedence.rs
src/tools/clippy/tests/ui/redundant_clone.fixed
src/tools/clippy/tests/ui/redundant_clone.rs
src/tools/clippy/tests/ui/redundant_clone.stderr
src/tools/clippy/tests/ui/redundant_closure_call.rs [deleted file]
src/tools/clippy/tests/ui/redundant_closure_call.stderr [deleted file]
src/tools/clippy/tests/ui/redundant_closure_call_early.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_closure_call_early.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr
src/tools/clippy/tests/ui/redundant_closure_call_late.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_closure_call_late.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching.fixed
src/tools/clippy/tests/ui/redundant_pattern_matching.rs
src/tools/clippy/tests/ui/redundant_pattern_matching.stderr
src/tools/clippy/tests/ui/shadow.stderr
src/tools/clippy/tests/ui/unit_return_expecting_ord.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/useless_conversion.fixed
src/tools/clippy/tests/ui/useless_conversion.rs
src/tools/clippy/tests/ui/useless_conversion.stderr
src/tools/clippy/tests/ui/vec_resize_to_zero.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/header/tests.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/tests.rs
src/tools/error_index_generator/Cargo.toml
src/tools/publish_toolstate.py
src/tools/rls
src/tools/rust-analyzer
src/tools/rustfmt
src/tools/tidy/src/deps.rs
src/tools/tidy/src/lib.rs
triagebot.toml

index 86de37820003ae425f59eee735e23666f7099015..d83971b70bedc45bfecb79c29608d884c0d5ef79 100644 (file)
@@ -20,6 +20,7 @@ name: CI
     branches:
       - auto
       - try
+      - try-perf
       - master
   pull_request:
     branches:
@@ -32,9 +33,9 @@ jobs:
     name: PR
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
-      SCCACHE_BUCKET: rust-lang-gha-caches
-      TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
-      CACHE_DOMAIN: ci-caches-gha.rust-lang.org
+      SCCACHE_BUCKET: rust-lang-ci-sccache2
+      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
+      CACHE_DOMAIN: ci-caches.rust-lang.org
     if: "github.event_name == 'pull_request'"
     strategy:
       matrix:
@@ -63,6 +64,11 @@ jobs:
         with:
           github_token: "${{ secrets.github_token }}"
         if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+      - name: configure the PR in which the error message will be posted
+        run: "echo \"[CI_PR_NUMBER=$num]\""
+        env:
+          num: "${{ github.event.number }}"
+        if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
         env:
@@ -133,15 +139,15 @@ jobs:
     name: try
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
-      SCCACHE_BUCKET: rust-lang-gha-caches
-      DEPLOY_BUCKET: rust-lang-gha
-      TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
-      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues"
+      SCCACHE_BUCKET: rust-lang-ci-sccache2
+      DEPLOY_BUCKET: rust-lang-ci2
+      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
+      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
       TOOLSTATE_PUBLISH: 1
-      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
-      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
-      CACHE_DOMAIN: ci-caches-gha.rust-lang.org
-    if: "github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'"
+      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+      CACHE_DOMAIN: ci-caches.rust-lang.org
+    if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     strategy:
       matrix:
         include:
@@ -162,6 +168,11 @@ jobs:
         with:
           github_token: "${{ secrets.github_token }}"
         if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+      - name: configure the PR in which the error message will be posted
+        run: "echo \"[CI_PR_NUMBER=$num]\""
+        env:
+          num: "${{ github.event.number }}"
+        if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
         env:
@@ -232,14 +243,14 @@ jobs:
     name: auto
     env:
       CI_JOB_NAME: "${{ matrix.name }}"
-      SCCACHE_BUCKET: rust-lang-gha-caches
-      DEPLOY_BUCKET: rust-lang-gha
-      TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
-      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues"
+      SCCACHE_BUCKET: rust-lang-ci-sccache2
+      DEPLOY_BUCKET: rust-lang-ci2
+      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
+      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
       TOOLSTATE_PUBLISH: 1
-      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
-      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
-      CACHE_DOMAIN: ci-caches-gha.rust-lang.org
+      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+      CACHE_DOMAIN: ci-caches.rust-lang.org
     if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'"
     strategy:
       matrix:
@@ -479,6 +490,11 @@ jobs:
         with:
           github_token: "${{ secrets.github_token }}"
         if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+      - name: configure the PR in which the error message will be posted
+        run: "echo \"[CI_PR_NUMBER=$num]\""
+        env:
+          num: "${{ github.event.number }}"
+        if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
         env:
@@ -604,6 +620,11 @@ jobs:
         with:
           github_token: "${{ secrets.github_token }}"
         if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
+      - name: configure the PR in which the error message will be posted
+        run: "echo \"[CI_PR_NUMBER=$num]\""
+        env:
+          num: "${{ github.event.number }}"
+        if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
         env:
@@ -674,14 +695,14 @@ jobs:
     name: master
     runs-on: ubuntu-latest
     env:
-      SCCACHE_BUCKET: rust-lang-gha-caches
-      DEPLOY_BUCKET: rust-lang-gha
-      TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate"
-      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/pietroalbini/rust-toolstate/issues"
+      SCCACHE_BUCKET: rust-lang-ci-sccache2
+      DEPLOY_BUCKET: rust-lang-ci2
+      TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
+      TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
       TOOLSTATE_PUBLISH: 1
-      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5
-      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF
-      CACHE_DOMAIN: ci-caches-gha.rust-lang.org
+      CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+      ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+      CACHE_DOMAIN: ci-caches.rust-lang.org
     if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: checkout the source code
@@ -697,7 +718,7 @@ jobs:
   try-success:
     needs:
       - try
-    if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'"
+    if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a success
         run: exit 0
@@ -707,7 +728,7 @@ jobs:
   try-failure:
     needs:
       - try
-    if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'"
+    if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     steps:
       - name: mark the job as a failure
         run: exit 1
index b914b7d6fa12961cb20f627f0a2133715e86c481..5c0ab737f63dbd7da7c41695f382a9a2a275f1b6 100644 (file)
@@ -44,6 +44,3 @@
 [submodule "src/tools/rust-analyzer"]
        path = src/tools/rust-analyzer
        url = https://github.com/rust-analyzer/rust-analyzer.git
-[submodule "src/backtrace"]
-       path = src/backtrace
-       url = https://github.com/rust-lang/backtrace-rs.git
index 34a33eca3f40b7c635b79dfbf7b1bc0f416c8497..d0ce581343f0b473871b99a208b8c28e0f115eb2 100644 (file)
@@ -1,26 +1,10 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
 [[package]]
-name = "addr2line"
-version = "0.13.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
-dependencies = [
- "compiler_builtins",
- "gimli",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
-[[package]]
-name = "adler"
-version = "0.2.2"
+name = "adler32"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-core",
-]
+checksum = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
 
 [[package]]
 name = "aho-corasick"
@@ -141,14 +125,28 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
 
 [[package]]
 name = "backtrace"
-version = "0.3.50"
+version = "0.3.46"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e"
 dependencies = [
- "addr2line",
+ "backtrace-sys",
  "cfg-if",
+ "compiler_builtins",
  "libc",
- "miniz_oxide",
- "object",
  "rustc-demangle",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399"
+dependencies = [
+ "cc",
+ "compiler_builtins",
+ "libc",
+ "rustc-std-workspace-core",
 ]
 
 [[package]]
@@ -280,7 +278,7 @@ checksum = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
 
 [[package]]
 name = "cargo"
-version = "0.47.0"
+version = "0.48.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -412,9 +410,9 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.57"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fde55d2a2bfaa4c9668bbc63f531fbdeee3ffe188f4662511ce2c22b3eedebe"
+checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
 dependencies = [
  "jobserver",
 ]
@@ -690,9 +688,9 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.2.0"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
+checksum = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192"
 dependencies = [
  "cfg-if",
 ]
@@ -1025,9 +1023,9 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
 
 [[package]]
 name = "flate2"
-version = "1.0.16"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e"
+checksum = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3"
 dependencies = [
  "cfg-if",
  "crc32fast",
@@ -1161,17 +1159,6 @@ dependencies = [
  "wasi",
 ]
 
-[[package]]
-name = "gimli"
-version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
 [[package]]
 name = "git2"
 version = "0.13.5"
@@ -1255,9 +1242,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.14"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
+checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -1576,9 +1563,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
 
 [[package]]
 name = "libc"
-version = "0.2.71"
+version = "0.2.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
+checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -1832,14 +1819,11 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.4.0"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
+checksum = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625"
 dependencies = [
- "adler",
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
+ "adler32",
 ]
 
 [[package]]
@@ -1971,17 +1955,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "object"
-version = "0.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
-dependencies = [
- "compiler_builtins",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
-]
-
 [[package]]
 name = "once_cell"
 version = "1.1.0"
@@ -2442,9 +2415,9 @@ dependencies = [
 
 [[package]]
 name = "racer"
-version = "2.1.35"
+version = "2.1.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "421174f19211ba9e5fda34aa0cbc292188aae8e0cfbff4aebbae23f1a416bfb3"
+checksum = "09ba6cca9fcd8ae086b842b1bd9e3f19f104a4c30e0e8927b2befc06d375e7e0"
 dependencies = [
  "bitflags",
  "clap",
@@ -2838,9 +2811,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_arena"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c6683b49209f8b132bec33dc6b6c8f9958c8c94eb3586d4cb495e092b61c1da"
+checksum = "c9cdd301e9dcb15ead384fc07196c850fd22829fae81d296b2ed6b4b10bf3278"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "smallvec 1.4.0",
@@ -2848,9 +2821,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b21784d92fb2d584800f528866f00fe814f73abda794f406bfd1fbb2f1ca7f7"
+checksum = "3f7c0d0537ca69dfe4a49212035295dfb37a235b5df01aa877d50b247f4775b8"
 dependencies = [
  "bitflags",
  "log",
@@ -2866,9 +2839,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast_passes"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "820c46fde7ef1df0432073090d775f097b7279ca75ea34ba954081ce4b884d4c"
+checksum = "d4cf4dca95f55f70eeb193fb08554026d79d0628de771fd726bb609e36887b82"
 dependencies = [
  "itertools 0.8.0",
  "log",
@@ -2885,9 +2858,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast_pretty"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "013db7dd198fe95962d2cefa5bd0b350cf2028af77c169b17b4baa9c3bbf77d1"
+checksum = "202bd2886d0cfa48baa3711042c14843f1b4852555b7ee7e5376bf66b276cb8d"
 dependencies = [
  "log",
  "rustc-ap-rustc_ast",
@@ -2897,9 +2870,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_attr"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35b5a85c90eb341eec543600ffdd9e262da5ea72a73a23ae4ca2f4ab8cd1a188"
+checksum = "b11ee1d92b3214e8a8c7829eff84cc1b03925da0ea5c6900cefe05b99edb4682"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_ast_pretty",
@@ -2915,9 +2888,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b92e4c6cb6c43ee9031a71709dc12853b358253c2b41d12a26379994fab625e0"
+checksum = "7a45d43b974d4cb9e32e5a15119c5eb7672c306ef09b064f2125b6a0399f6656"
 dependencies = [
  "bitflags",
  "cfg-if",
@@ -2945,9 +2918,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b0aa79423260c1b9e2f856e144e040f606b0f5d43644408375becf9d7bcdf86"
+checksum = "8cd895d440820aaa04e6dc5486105494920a1e9779b9b051e8dba4ca5c182f94"
 dependencies = [
  "annotate-snippets 0.8.0",
  "atty",
@@ -2963,9 +2936,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_expand"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c07d76ba2a1b7d4325a2ed21d6345ccebd89ddc6666a1535a6edd489fb4cbc11"
+checksum = "71a0cc7820860d6691bf0aa7a95cdbc60f6587b495c18e0fa15a888fdabbf171"
 dependencies = [
  "log",
  "rustc-ap-rustc_ast",
@@ -2985,9 +2958,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_feature"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bbd625705c1db42a0c7503736292813d7b76ada5da20578fb55c63228c80ab5"
+checksum = "5473d5106401aa46f881eb91772f0a41fd5f28ae6134cf4b450eb1370ea6af22"
 dependencies = [
  "lazy_static",
  "rustc-ap-rustc_data_structures",
@@ -2996,21 +2969,21 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_fs_util"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cca6e2942fa0b059c582437ead666d5bcf20fa7c242599e2bbea9b609f29ae"
+checksum = "8da1d57ee7a7ef55f31a97d99c7f919f02fc9a60ab96faa8cf45a7ae3ab1ccbf"
 
 [[package]]
 name = "rustc-ap-rustc_graphviz"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13d6a029b81f5e02da85763f82c135507f278a4a0c776432c728520563059529"
+checksum = "e3af62b20460908378cd1d354917acd9553376c5363bbb4e465f949bd82bdef9"
 
 [[package]]
 name = "rustc-ap-rustc_index"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bae50852d303e230b2781c994513788136dc6c2fe4ebe032959f0b990a425767"
+checksum = "3af7d4c456fe7647453d3fcd58335c9d512d1ff9a239a370b7ebdd353d69f66f"
 dependencies = [
  "rustc-ap-rustc_serialize",
  "smallvec 1.4.0",
@@ -3018,18 +2991,18 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7186e74aa2d31bf0e2454325fefcdf0a3da77d9344134592144b9e40d45b15d"
+checksum = "456af5f09c006cf6c22c1a433ee0232c4bb74bdc6c647a010166a47c94ed2a63"
 dependencies = [
  "unicode-xid 0.2.0",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fc1add04e9d2301164118660ee0bc3266e9a7b1973fc2303fdbe002a12e5401"
+checksum = "64f6acd192f313047759a346b892998b626466b93fe04f415da5f38906bb3b4c"
 dependencies = [
  "proc-macro2 1.0.3",
  "quote 1.0.2",
@@ -3039,9 +3012,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_parse"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cd7fc4968bd60084f2fa4f280fa450b0cf98660a7983d6b93a7ae41b6d1d322"
+checksum = "c006e8117c1c55e42bb56386c86ce6f7e4b47349e0bec7888c1d24784272e61b"
 dependencies = [
  "bitflags",
  "log",
@@ -3058,9 +3031,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_serialize"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00bf4c110271d9a2b7dfd2c6eb82e56fd80606a8bad6c102e158c54e44044046"
+checksum = "306ced69beaeebe4de9552ee751eb54ea25b5f34a73fe80f5f9cbbe15ccebc48"
 dependencies = [
  "indexmap",
  "smallvec 1.4.0",
@@ -3068,10 +3041,11 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_session"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "431cf962de71d4c03fb877d54f331ec36eca77350b0539017abc40a4410d6501"
+checksum = "dbff48435f5a476365e3ab5f49e07f98715cecb2d8c5bbcafeaf3aec638407be"
 dependencies = [
+ "bitflags",
  "getopts",
  "log",
  "num_cpus",
@@ -3087,9 +3061,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_span"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b912039640597624f4bcb75f1e1fcfa5710267d715a7f73a6336baef341b23d1"
+checksum = "ec4273af0abbe78fc4585316ab193445c848c555e9203ddc28af02330918bf30"
 dependencies = [
  "cfg-if",
  "log",
@@ -3106,9 +3080,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "664.0.0"
+version = "669.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51347a9dadc5ad0b5916cc12d42624b31955285ad13745dbe72f0140038b84e9"
+checksum = "6f9a2d6004ce6ad492a8eeacc2569b1c008169434b8828996d8dade4e5c6b6ee"
 dependencies = [
  "bitflags",
  "log",
@@ -4112,7 +4086,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.18"
+version = "1.4.19"
 dependencies = [
  "annotate-snippets 0.6.1",
  "anyhow",
@@ -4373,8 +4347,8 @@ dependencies = [
 name = "std"
 version = "0.0.0"
 dependencies = [
- "addr2line",
  "alloc",
+ "backtrace",
  "cfg-if",
  "compiler_builtins",
  "core",
@@ -4383,13 +4357,10 @@ dependencies = [
  "hashbrown",
  "hermit-abi",
  "libc",
- "miniz_oxide",
- "object",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
  "rand 0.7.3",
- "rustc-demangle",
  "unwind",
  "wasi",
 ]
index 9429e063b51106e35e9d19aa6eb89a91e242eba4..efc6f4a0291ca6791b9088ad6f7a02bb4473106b 100644 (file)
@@ -80,11 +80,5 @@ rustc-std-workspace-core = { path = 'src/tools/rustc-std-workspace-core' }
 rustc-std-workspace-alloc = { path = 'src/tools/rustc-std-workspace-alloc' }
 rustc-std-workspace-std = { path = 'src/tools/rustc-std-workspace-std' }
 
-# This crate's integration with libstd is a bit wonky, so we use a submodule
-# instead of a crates.io dependency. Make sure everything else in the repo is
-# also using the submodule, however, so we can avoid duplicate copies of the
-# source code for this crate.
-backtrace = { path = "src/backtrace" }
-
 [patch."https://github.com/rust-lang/rust-clippy"]
 clippy_lints = { path = "src/tools/clippy/clippy_lints" }
index b16aecc463c9191c591d0c135ab50e975afc1000..c76a75fa07bb0361eee0acda48734f8c58c797a2 100644 (file)
@@ -30,7 +30,6 @@ ignore = [
     "src/tools/rust-analyzer",
     "src/tools/rust-installer",
     "src/tools/rustfmt",
-    "src/backtrace",
 
     # We do not format this file as it is externally sourced and auto-generated.
     "src/libstd/sys/cloudabi/abi/cloudabi.rs",
diff --git a/src/backtrace b/src/backtrace
deleted file mode 160000 (submodule)
index 8f89434..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 8f89434446f72f27f8145d8bbc1a302c6ef29d1e
index 70e5f6ac26fc13c8b0479192cff2f9df709e3639..c1e56347ab1e0111ed0ff5d0bd71f1c88aead816 100644 (file)
@@ -1239,7 +1239,7 @@ pub fn cargo(
             && self.config.control_flow_guard
             && compiler.stage >= 1
         {
-            rustflags.arg("-Zcontrol-flow-guard");
+            rustflags.arg("-Ccontrol-flow-guard");
         }
 
         // For `cargo doc` invocations, make rustdoc print the Rust version into the docs
@@ -1444,6 +1444,10 @@ pub struct Cargo {
 }
 
 impl Cargo {
+    pub fn rustdocflag(&mut self, arg: &str) -> &mut Cargo {
+        self.rustdocflags.arg(arg);
+        self
+    }
     pub fn rustflag(&mut self, arg: &str) -> &mut Cargo {
         self.rustflags.arg(arg);
         self
@@ -1466,6 +1470,9 @@ pub fn args<I, S>(&mut self, args: I) -> &mut Cargo
     }
 
     pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Cargo {
+        // These are managed through rustflag/rustdocflag interfaces.
+        assert_ne!(key.as_ref(), "RUSTFLAGS");
+        assert_ne!(key.as_ref(), "RUSTDOCFLAGS");
         self.command.env(key.as_ref(), value.as_ref());
         self
     }
index af30747a9592e6dcaf4eccaa226ba34f0c1d06cb..c64934cd6c9ded20f166b32e7988f80eb94eb68c 100644 (file)
@@ -91,7 +91,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let name = pkgname(builder, "rust-docs");
 
         if !builder.config.docs {
-            return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
         }
 
         builder.default_doc(None);
@@ -99,7 +99,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         builder.info(&format!("Dist docs ({})", host));
         let _time = timeit(builder);
 
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("share/doc/rust/html");
@@ -119,14 +119,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, host))
+            .arg(format!("--package-name={}-{}", name, host.triple))
             .arg("--component-name=rust-docs")
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--bulk-dirs=share/doc/rust/html");
         builder.run(&mut cmd);
         builder.remove_dir(&image);
 
-        distdir(builder).join(format!("{}-{}.tar.gz", name, host))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))
     }
 }
 
@@ -154,12 +154,12 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let name = pkgname(builder, "rustc-docs");
 
         if !builder.config.compiler_docs {
-            return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
         }
 
         builder.default_doc(None);
 
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
         let _ = fs::remove_dir_all(&image);
 
         let dst = image.join("share/doc/rust/html");
@@ -178,7 +178,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, host))
+            .arg(format!("--package-name={}-{}", name, host.triple))
             .arg("--component-name=rustc-docs")
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--bulk-dirs=share/doc/rust/html");
@@ -188,7 +188,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         builder.run(&mut cmd);
         builder.remove_dir(&image);
 
-        distdir(builder).join(format!("{}-{}.tar.gz", name, host))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple))
     }
 }
 
@@ -372,7 +372,7 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
         builder.info(&format!("Dist mingw ({})", host));
         let _time = timeit(builder);
         let name = pkgname(builder, "rust-mingw");
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
         let _ = fs::remove_dir_all(&image);
         t!(fs::create_dir_all(&image));
 
@@ -393,12 +393,12 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, host))
+            .arg(format!("--package-name={}-{}", name, host.triple))
             .arg("--component-name=rust-mingw")
             .arg("--legacy-manifest-dirs=rustlib,cargo");
         builder.run(&mut cmd);
         t!(fs::remove_dir_all(&image));
-        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple)))
     }
 }
 
@@ -427,9 +427,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let host = self.compiler.host;
 
         let name = pkgname(builder, "rustc");
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, host));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
         let _ = fs::remove_dir_all(&image);
-        let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host));
+        let overlay = tmpdir(builder).join(format!("{}-{}-overlay", name, host.triple));
         let _ = fs::remove_dir_all(&overlay);
 
         // Prepare the rustc "image", what will actually end up getting installed
@@ -483,17 +483,17 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, host))
+            .arg(format!("--package-name={}-{}", name, host.triple))
             .arg("--component-name=rustc")
             .arg("--legacy-manifest-dirs=rustlib,cargo");
 
-        builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host));
+        builder.info(&format!("Dist rustc stage{} ({})", compiler.stage, host.triple));
         let _time = timeit(builder);
         builder.run(&mut cmd);
         builder.remove_dir(&image);
         builder.remove_dir(&overlay);
 
-        return distdir(builder).join(format!("{}-{}.tar.gz", name, host));
+        return distdir(builder).join(format!("{}-{}.tar.gz", name, host.triple));
 
         fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
             let host = compiler.host;
@@ -707,14 +707,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let target = self.target;
 
         let name = pkgname(builder, "rust-std");
-        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
         if skip_host_target_lib(builder, compiler) {
             return archive;
         }
 
         builder.ensure(compile::Std { compiler, target });
 
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
         let _ = fs::remove_dir_all(&image);
 
         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
@@ -732,8 +732,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, target))
-            .arg(format!("--component-name=rust-std-{}", target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
+            .arg(format!("--component-name=rust-std-{}", target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo");
 
         builder
@@ -776,14 +776,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let target = self.target;
 
         let name = pkgname(builder, "rustc-dev");
-        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+        let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
         if skip_host_target_lib(builder, compiler) {
             return archive;
         }
 
         builder.ensure(compile::Rustc { compiler, target });
 
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
         let _ = fs::remove_dir_all(&image);
 
         let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
@@ -801,8 +801,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, target))
-            .arg(format!("--component-name=rustc-dev-{}", target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
+            .arg(format!("--component-name=rustc-dev-{}", target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo");
 
         builder.info(&format!(
@@ -853,12 +853,12 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
         let name = pkgname(builder, "rust-analysis");
 
         if compiler.host != builder.config.build {
-            return distdir(builder).join(format!("{}-{}.tar.gz", name, target));
+            return distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple));
         }
 
         builder.ensure(compile::Std { compiler, target });
 
-        let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
+        let image = tmpdir(builder).join(format!("{}-{}-image", name, target.triple));
 
         let src = builder
             .stage_out(compiler, Mode::Std)
@@ -883,15 +883,15 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&tmpdir(builder))
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", name, target))
-            .arg(format!("--component-name=rust-analysis-{}", target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
+            .arg(format!("--component-name=rust-analysis-{}", target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo");
 
         builder.info("Dist analysis");
         let _time = timeit(builder);
         builder.run(&mut cmd);
         builder.remove_dir(&image);
-        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
     }
 }
 
@@ -1242,14 +1242,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--component-name=cargo")
             .arg("--legacy-manifest-dirs=rustlib,cargo");
 
         builder.info(&format!("Dist cargo stage{} ({})", compiler.stage, target));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
     }
 }
 
@@ -1332,14 +1332,14 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=rls-preview");
 
-        builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target));
+        builder.info(&format!("Dist RLS stage{} ({})", compiler.stage, target.triple));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
     }
 }
 
@@ -1419,14 +1419,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=rust-analyzer-preview");
 
         builder.info(&format!("Dist rust-analyzer stage{} ({})", compiler.stage, target));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
     }
 }
 
@@ -1510,14 +1510,14 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=clippy-preview");
 
         builder.info(&format!("Dist clippy stage{} ({})", compiler.stage, target));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        distdir(builder).join(format!("{}-{}.tar.gz", name, target))
+        distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple))
     }
 }
 
@@ -1607,14 +1607,14 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=miri-preview");
 
         builder.info(&format!("Dist miri stage{} ({})", compiler.stage, target));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
     }
 }
 
@@ -1701,14 +1701,14 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=rustfmt-preview");
 
         builder.info(&format!("Dist Rustfmt stage{} ({})", compiler.stage, target));
         let _time = timeit(builder);
         builder.run(&mut cmd);
-        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
     }
 }
 
@@ -1813,7 +1813,7 @@ fn run(self, builder: &Builder<'_>) {
             .arg(&work)
             .arg("--output-dir")
             .arg(&distdir(builder))
-            .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target))
+            .arg(format!("--package-name={}-{}", pkgname(builder, "rust"), target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--input-tarballs")
             .arg(input_tarballs)
@@ -1893,7 +1893,7 @@ fn filter(contents: &str, marker: &str) -> String {
             let prepare = |name: &str| {
                 builder.create_dir(&pkg.join(name));
                 builder.cp_r(
-                    &work.join(&format!("{}-{}", pkgname(builder, name), target)),
+                    &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)),
                     &pkg.join(name),
                 );
                 builder.install(&etc.join("pkg/postinstall"), &pkg.join(name), 0o755);
@@ -1926,7 +1926,11 @@ fn filter(contents: &str, marker: &str) -> String {
                 .arg(xform(&etc.join("pkg/Distribution.xml")))
                 .arg("--resources")
                 .arg(pkg.join("res"))
-                .arg(distdir(builder).join(format!("{}-{}.pkg", pkgname(builder, "rust"), target)))
+                .arg(distdir(builder).join(format!(
+                    "{}-{}.pkg",
+                    pkgname(builder, "rust"),
+                    target.triple
+                )))
                 .arg("--package-path")
                 .arg(&pkg);
             let _time = timeit(builder);
@@ -1940,7 +1944,7 @@ fn filter(contents: &str, marker: &str) -> String {
             let prepare = |name: &str| {
                 builder.create_dir(&exe.join(name));
                 let dir = if name == "rust-std" || name == "rust-analysis" {
-                    format!("{}-{}", name, target)
+                    format!("{}-{}", name, target.triple)
                 } else if name == "rls" {
                     "rls-preview".to_string()
                 } else if name == "rust-analyzer" {
@@ -1953,7 +1957,7 @@ fn filter(contents: &str, marker: &str) -> String {
                     name.to_string()
                 };
                 builder.cp_r(
-                    &work.join(&format!("{}-{}", pkgname(builder, name), target)).join(dir),
+                    &work.join(&format!("{}-{}", pkgname(builder, name), target.triple)).join(dir),
                     &exe.join(name),
                 );
                 builder.remove(&exe.join(name).join("manifest.in"));
@@ -2212,7 +2216,7 @@ fn filter(contents: &str, marker: &str) -> String {
             builder.install(&etc.join("gfx/dialogbg.bmp"), &exe, 0o644);
 
             builder.info(&format!("building `msi` installer with {:?}", light));
-            let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target);
+            let filename = format!("{}-{}.msi", pkgname(builder, "rust"), target.triple);
             let mut cmd = Command::new(&light);
             cmd.arg("-nologo")
                 .arg("-ext")
@@ -2461,11 +2465,11 @@ fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
             .arg(&distdir(builder))
             .arg("--non-installed-overlay")
             .arg(&overlay)
-            .arg(format!("--package-name={}-{}", name, target))
+            .arg(format!("--package-name={}-{}", name, target.triple))
             .arg("--legacy-manifest-dirs=rustlib,cargo")
             .arg("--component-name=llvm-tools-preview");
 
         builder.run(&mut cmd);
-        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target.triple)))
     }
 }
index b051390fc2671f73b7fe1f134717b5e8a4bc4dec..f8a549afc88fb81da408d64ca8c9f7519fee8bf8 100644 (file)
@@ -527,11 +527,9 @@ fn run(self, builder: &Builder<'_>) {
 
         // Build cargo command.
         let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "doc");
-        cargo.env(
-            "RUSTDOCFLAGS",
-            "--document-private-items \
-            --enable-index-page -Zunstable-options",
-        );
+        cargo.rustdocflag("--document-private-items");
+        cargo.rustdocflag("--enable-index-page");
+        cargo.rustdocflag("-Zunstable-options");
         compile::rustc_cargo(builder, &mut cargo, target);
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
@@ -624,7 +622,7 @@ fn run(self, builder: &Builder<'_>) {
         cargo.arg("--no-deps");
         cargo.arg("-p").arg("rustdoc");
 
-        cargo.env("RUSTDOCFLAGS", "--document-private-items");
+        cargo.rustdocflag("--document-private-items");
         builder.run(&mut cargo.into());
     }
 }
index dcdc681e87dbb010e75ee5c34eee6951bd990da1..1316f95dd41770b7b1cd0217924de8a11ff52c46 100644 (file)
@@ -107,7 +107,7 @@ fn install_sh(
 
     t!(fs::create_dir_all(&empty_dir));
     let package_name = if let Some(host) = host {
-        format!("{}-{}", pkgname(builder, name), host)
+        format!("{}-{}", pkgname(builder, name), host.triple)
     } else {
         pkgname(builder, name)
     };
index 43c3c5773ce5b2d45cd32ee1157cf2d8ce0dc1b2..e30da8d56e10fca3ebb0fb3e289f07665e4e27e0 100644 (file)
@@ -1,3 +1,5 @@
+use std::ffi::{OsStr, OsString};
+use std::fmt::Display;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::time::{SystemTime, UNIX_EPOCH};
@@ -28,6 +30,14 @@ macro_rules! t {
     };
 }
 
+/// Reads an environment variable and adds it to dependencies.
+/// Supposed to be used for all variables except those set for build scripts by cargo
+/// https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
+pub fn tracked_env_var_os<K: AsRef<OsStr> + Display>(key: K) -> Option<OsString> {
+    println!("cargo:rerun-if-env-changed={}", key);
+    env::var_os(key)
+}
+
 // Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
 // break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
 // shared library, which means that when our freshly built llvm-config goes to load it's
@@ -37,10 +47,8 @@ macro_rules! t {
 // perfect -- we might actually want to see something from Cargo's added library paths -- but
 // for now it works.
 pub fn restore_library_path() {
-    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH_VAR");
-    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH");
-    let key = env::var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
-    if let Some(env) = env::var_os("REAL_LIBRARY_PATH") {
+    let key = tracked_env_var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
+    if let Some(env) = tracked_env_var_os("REAL_LIBRARY_PATH") {
         env::set_var(&key, &env);
     } else {
         env::remove_var(&key);
index 1786baa0278b9896df976494b3051a9eedfc972f..06e284c763c1509f7c34b38d3edc5e0198ff158c 100644 (file)
 #####################################
 
 #
-# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows.
+# Azure Pipelines "auto" branch build for Rust on macOS
 #
 
 pr: none
 trigger:
   - auto
 
-variables:
-- group: prod-credentials
-
 jobs:
-- job: Linux
-  timeoutInMinutes: 600
-  pool:
-    vmImage: ubuntu-16.04
-  steps:
-  - template: steps/run.yml
-  strategy:
-    matrix:
-      x86_64-gnu-llvm-8:
-        RUST_BACKTRACE: 1
-      dist-x86_64-linux: {}
-      dist-x86_64-linux-alt:
-        IMAGE: dist-x86_64-linux
-      arm-android: {}
-      armhf-gnu: {}
-      dist-various-1: {}
-      dist-various-2: {}
-      dist-aarch64-linux: {}
-      dist-android: {}
-      dist-arm-linux: {}
-      dist-armhf-linux: {}
-      dist-armv7-linux: {}
-      dist-i586-gnu-i586-i686-musl: {}
-      dist-i686-freebsd: {}
-      dist-i686-linux: {}
-      dist-mips-linux: {}
-      dist-mips64-linux: {}
-      dist-mips64el-linux: {}
-      dist-mipsel-linux: {}
-      dist-powerpc-linux: {}
-      dist-powerpc64-linux: {}
-      dist-powerpc64le-linux: {}
-      dist-riscv64-linux: {}
-      dist-s390x-linux: {}
-      dist-x86_64-freebsd: {}
-      dist-x86_64-illumos: {}
-      dist-x86_64-musl: {}
-      dist-x86_64-netbsd: {}
-      i686-gnu: {}
-      i686-gnu-nopt: {}
-      test-various: {}
-      wasm32: {}
-      x86_64-gnu: {}
-      x86_64-gnu-full-bootstrap: {}
-      x86_64-gnu-aux: {}
-      x86_64-gnu-tools:
-        DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
-      x86_64-gnu-debug: {}
-      x86_64-gnu-nopt: {}
-      x86_64-gnu-distcheck: {}
-      mingw-check: {}
-
 - job: macOS
   timeoutInMinutes: 600
   pool:
     vmImage: macos-10.15
   steps:
   - template: steps/run.yml
+  variables:
+    # We're still uploading macOS builds from Azure Pipelines.
+    - group: prod-credentials
   strategy:
     matrix:
       # OSX builders running tests, these run the full test suite.
@@ -112,115 +60,3 @@ jobs:
         MACOSX_DEPLOYMENT_TARGET: 10.7
         NO_LLVM_ASSERTIONS: 1
         NO_DEBUG_ASSERTIONS: 1
-
-
-- job: Windows
-  timeoutInMinutes: 600
-  pool:
-    vmImage: 'vs2017-win2016'
-  steps:
-  - template: steps/run.yml
-  strategy:
-    matrix:
-      # 32/64 bit MSVC tests
-      x86_64-msvc-1:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
-        SCRIPT: make ci-subset-1
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      x86_64-msvc-2:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
-        SCRIPT: make ci-subset-2
-      i686-msvc-1:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
-        SCRIPT: make ci-subset-1
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      i686-msvc-2:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
-        SCRIPT: make ci-subset-2
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      x86_64-msvc-cargo:
-        SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
-        VCVARS_BAT: vcvars64.bat
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      # MSVC tools tests
-      x86_64-msvc-tools:
-        SCRIPT: src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh x.py
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json
-
-      # 32/64-bit MinGW builds.
-      #
-      # We are using MinGW with posix threads since LLVM does not compile with
-      # the win32 threads version due to missing support for C++'s std::thread.
-      #
-      # Instead of relying on the MinGW version installed on appveryor we download
-      # and install one ourselves so we won't be surprised by changes to appveyor's
-      # build image.
-      #
-      # Finally, note that the downloads below are all in the `rust-lang-ci` S3
-      # bucket, but they cleraly didn't originate there! The downloads originally
-      # came from the mingw-w64 SourceForge download site. Unfortunately
-      # SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
-      i686-mingw-1:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
-        SCRIPT: make ci-mingw-subset-1
-        CUSTOM_MINGW: 1
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      i686-mingw-2:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
-        SCRIPT: make ci-mingw-subset-2
-        CUSTOM_MINGW: 1
-      x86_64-mingw-1:
-        SCRIPT: make ci-mingw-subset-1
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
-        CUSTOM_MINGW: 1
-        # FIXME(#59637)
-        NO_DEBUG_ASSERTIONS: 1
-        NO_LLVM_ASSERTIONS: 1
-      x86_64-mingw-2:
-        SCRIPT: make ci-mingw-subset-2
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu
-        CUSTOM_MINGW: 1
-
-      # 32/64 bit MSVC and GNU deployment
-      dist-x86_64-msvc:
-        INITIAL_RUST_CONFIGURE_ARGS: >-
-          --build=x86_64-pc-windows-msvc
-          --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
-          --enable-full-tools
-          --enable-profiler
-        SCRIPT: python x.py dist
-        DIST_REQUIRE_ALL_TOOLS: 1
-      dist-i686-msvc:
-        INITIAL_RUST_CONFIGURE_ARGS: >-
-          --build=i686-pc-windows-msvc
-          --target=i586-pc-windows-msvc
-          --enable-full-tools
-          --enable-profiler
-        SCRIPT: python x.py dist
-        DIST_REQUIRE_ALL_TOOLS: 1
-      dist-i686-mingw:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler
-        SCRIPT: python x.py dist
-        CUSTOM_MINGW: 1
-        DIST_REQUIRE_ALL_TOOLS: 1
-      dist-x86_64-mingw:
-        SCRIPT: python x.py dist
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler
-        CUSTOM_MINGW: 1
-        DIST_REQUIRE_ALL_TOOLS: 1
-
-      # "alternate" deployment, see .travis.yml for more info
-      dist-x86_64-msvc-alt:
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
-        SCRIPT: python x.py dist
diff --git a/src/ci/azure-pipelines/master.yml b/src/ci/azure-pipelines/master.yml
deleted file mode 100644 (file)
index 485b803..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#####################################
-##    READ BEFORE CHANGING THIS    ##
-#####################################
-
-# We're in the process of evaluating GitHub Actions as a possible replacement
-# for Azure Pipelines, and at the moment the configuration is duplicated
-# between the two CI providers. Be sure to also change the configuration in
-# src/ci/github-actions when changing this file.
-
-#####################################
-
-#
-# Azure Pipelines job to publish toolstate. Only triggers on pushes to master.
-#
-
-pr: none
-trigger:
-  - master
-
-variables:
-- group: prod-credentials
-
-pool:
-  vmImage: ubuntu-16.04
-
-steps:
-- checkout: self
-  fetchDepth: 2
-
-- script: src/ci/publish_toolstate.sh
-  displayName: Publish toolstate
-  env:
-    TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN)
diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml
deleted file mode 100644 (file)
index 1fc8d18..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#####################################
-##    READ BEFORE CHANGING THIS    ##
-#####################################
-
-# We're in the process of evaluating GitHub Actions as a possible replacement
-# for Azure Pipelines, and at the moment the configuration is duplicated
-# between the two CI providers. Be sure to also change the configuration in
-# src/ci/github-actions when changing this file.
-
-#####################################
-
-#
-# Azure Pipelines pull request build for Rust
-#
-
-trigger: none
-pr:
-- master
-
-variables:
-- group: public-credentials
-
-jobs:
-- job: Linux
-  timeoutInMinutes: 600
-  pool:
-    vmImage: ubuntu-16.04
-  steps:
-    - template: steps/run.yml
-  strategy:
-    matrix:
-      x86_64-gnu-llvm-8: {}
-      mingw-check: {}
-      x86_64-gnu-tools:
-        CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
index 818306a00922986ab4fe3c3f8ceb079b574a3acd..62bb6f47334123f79f34d6d77bd552ba99ea2900 100644 (file)
@@ -13,70 +13,10 @@ pr: none
 trigger:
 - try
 
-variables:
-- group: prod-credentials
-
 jobs:
-- job: Linux
+- job: Dummy
   timeoutInMinutes: 600
   pool:
     vmImage: ubuntu-16.04
   steps:
-  - template: steps/run.yml
-  strategy:
-    matrix:
-      dist-x86_64-linux: {}
-
-# The macOS and Windows builds here are currently disabled due to them not being
-# overly necessary on `try` builds. We also don't actually have anything that
-# consumes the artifacts currently. Perhaps one day we can re-enable, but for now
-# it helps free up capacity on Azure.
-# - job: macOS
-#   timeoutInMinutes: 600
-#   pool:
-#     vmImage: macos-10.15
-#   steps:
-#   - template: steps/run.yml
-#   strategy:
-#     matrix:
-#       dist-x86_64-apple:
-#         SCRIPT: ./x.py dist
-#         INITIAL_RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc
-#         DEPLOY: 1
-#         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-#         MACOSX_DEPLOYMENT_TARGET: 10.7
-#         NO_LLVM_ASSERTIONS: 1
-#         NO_DEBUG_ASSERTIONS: 1
-#         DIST_REQUIRE_ALL_TOOLS: 1
-#
-#       dist-x86_64-apple-alt:
-#         SCRIPT: ./x.py dist
-#         INITIAL_RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc
-#         DEPLOY_ALT: 1
-#         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-#         MACOSX_DEPLOYMENT_TARGET: 10.7
-#         NO_LLVM_ASSERTIONS: 1
-#         NO_DEBUG_ASSERTIONS: 1
-#
-# - job: Windows
-#   timeoutInMinutes: 600
-#   pool:
-#     vmImage: 'vs2017-win2016'
-#   steps:
-#   - template: steps/run.yml
-#   strategy:
-#     matrix:
-#       dist-x86_64-msvc:
-#         INITIAL_RUST_CONFIGURE_ARGS: >
-#           --build=x86_64-pc-windows-msvc
-#           --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc
-#           --enable-full-tools
-#           --enable-profiler
-#         SCRIPT: python x.py dist
-#         DIST_REQUIRE_ALL_TOOLS: 1
-#         DEPLOY: 1
-#
-#       dist-x86_64-msvc-alt:
-#         INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
-#         SCRIPT: python x.py dist
-#         DEPLOY_ALT: 1
+  - bash: echo "We're running this job since bors is still gating on Azure"
index ff28f4f603c9dcc97fe4bbdb0ba6378e3080b8db..1a1c1618da40de27ec2c09fac5a7252bdb128ec9 100644 (file)
@@ -238,7 +238,7 @@ For targets: `powerpc-unknown-linux-gnu`
 - Target options > Emit assembly for CPU = powerpc -- pure 32-bit PowerPC
 - Operating System > Target OS = linux
 - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
-- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
+- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc
 - C compiler > gcc version = 5.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
@@ -255,7 +255,7 @@ For targets: `powerpc64-unknown-linux-gnu`
 - Target options > Tune for CPU = power6 -- (+)
 - Operating System > Target OS = linux
 - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
-- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
+- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc
 - C compiler > gcc version = 5.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
@@ -272,7 +272,7 @@ For targets: `s390x-unknown-linux-gnu`
 - Target options > Bitness = 64-bit
 - Operating System > Target OS = linux
 - Operating System > Linux kernel version = 2.6.32.68 -- ~RHEL6 kernel
-- C-library > glibc version = 2.12.2 -- ~RHEL6 glibc
+- C-library > glibc version = 2.11.1 -- ~SLE11-SP4 glibc
 - C compiler > gcc version = 5.2.0
 - C compiler > gcc extra config = --with-arch=z10 -- LLVM's minimum support
 - C compiler > C++ = ENABLE -- to cross compile LLVM
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch
new file mode 100644 (file)
index 0000000..744eb18
--- /dev/null
@@ -0,0 +1,24 @@
+From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
+From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
+Date: Thu, 1 Nov 2012 18:00:06 -0500
+Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
+
+---
+ sysdeps/powerpc/Makefile | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
+index 79dd6fa976d5..7442b6709ad1 100644
+--- a/sysdeps/powerpc/Makefile
++++ b/sysdeps/powerpc/Makefile
+@@ -1,7 +1,3 @@
+-# We always want to use the new mnemonic syntax even if we are on a RS6000
+-# machine.
+-+cflags += -mnew-mnemonics
+-
+ ifeq ($(subdir),gmon)
+ sysdep_routines += ppc-mcount
+ endif
+-- 
+2.9.3
+
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.11.1/002-newer-gcc.patch
new file mode 100644 (file)
index 0000000..a96b488
--- /dev/null
@@ -0,0 +1,26 @@
+diff --git a/configure b/configure
+index b6752d147c6b..6089a3403410 100755
+--- a/configure
++++ b/configure
+@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
+   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
+   case $ac_prog_version in
+     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+-    3.4* | 4.[0-9]* )
++    3.4* | [4-9].* )
+        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+diff --git a/configure.in b/configure.in
+index 56849dfc489a..09677eb3d0c1 100644
+--- a/configure.in
++++ b/configure.in
+@@ -960,7 +960,7 @@ fi
+ # These programs are version sensitive.
+ AC_CHECK_TOOL_PREFIX
+ AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
+-  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
++  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
+   critic_missing="$critic_missing gcc")
+ AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
+   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch
deleted file mode 100644 (file)
index 744eb18..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
-From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
-Date: Thu, 1 Nov 2012 18:00:06 -0500
-Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
-
----
- sysdeps/powerpc/Makefile | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
-index 79dd6fa976d5..7442b6709ad1 100644
---- a/sysdeps/powerpc/Makefile
-+++ b/sysdeps/powerpc/Makefile
-@@ -1,7 +1,3 @@
--# We always want to use the new mnemonic syntax even if we are on a RS6000
--# machine.
--+cflags += -mnew-mnemonics
--
- ifeq ($(subdir),gmon)
- sysdep_routines += ppc-mcount
- endif
--- 
-2.9.3
-
diff --git a/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc-linux/patches/glibc/2.12.2/002-newer-gcc.patch
deleted file mode 100644 (file)
index a96b488..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/configure b/configure
-index b6752d147c6b..6089a3403410 100755
---- a/configure
-+++ b/configure
-@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
-   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
-   case $ac_prog_version in
-     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
--    3.4* | 4.[0-9]* )
-+    3.4* | [4-9].* )
-        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
-     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
-diff --git a/configure.in b/configure.in
-index 56849dfc489a..09677eb3d0c1 100644
---- a/configure.in
-+++ b/configure.in
-@@ -960,7 +960,7 @@ fi
- # These programs are version sensitive.
- AC_CHECK_TOOL_PREFIX
- AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
--  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
-+  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
-   critic_missing="$critic_missing gcc")
- AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
-   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
index 7df41da2bf76e87cc5f3fe670b252b6850318578..b358dce3cdfe855d41203fa02517c461df7d58af 100644 (file)
@@ -290,7 +290,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
 # C-library
 #
 CT_LIBC="glibc"
-CT_LIBC_VERSION="2.12.2"
+CT_LIBC_VERSION="2.11.1"
 CT_LIBC_glibc=y
 # CT_LIBC_musl is not set
 # CT_LIBC_uClibc is not set
@@ -309,9 +309,9 @@ CT_THREADS="nptl"
 # CT_LIBC_GLIBC_V_2_14_1 is not set
 # CT_LIBC_GLIBC_V_2_14 is not set
 # CT_LIBC_GLIBC_V_2_13 is not set
-CT_LIBC_GLIBC_V_2_12_2=y
+# CT_LIBC_GLIBC_V_2_12_2 is not set
 # CT_LIBC_GLIBC_V_2_12_1 is not set
-# CT_LIBC_GLIBC_V_2_11_1 is not set
+CT_LIBC_GLIBC_V_2_11_1=y
 # CT_LIBC_GLIBC_V_2_11 is not set
 # CT_LIBC_GLIBC_V_2_10_1 is not set
 # CT_LIBC_GLIBC_V_2_9 is not set
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch
new file mode 100644 (file)
index 0000000..744eb18
--- /dev/null
@@ -0,0 +1,24 @@
+From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
+From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
+Date: Thu, 1 Nov 2012 18:00:06 -0500
+Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
+
+---
+ sysdeps/powerpc/Makefile | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
+index 79dd6fa976d5..7442b6709ad1 100644
+--- a/sysdeps/powerpc/Makefile
++++ b/sysdeps/powerpc/Makefile
+@@ -1,7 +1,3 @@
+-# We always want to use the new mnemonic syntax even if we are on a RS6000
+-# machine.
+-+cflags += -mnew-mnemonics
+-
+ ifeq ($(subdir),gmon)
+ sysdep_routines += ppc-mcount
+ endif
+-- 
+2.9.3
+
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/002-Prevent-inlining-in-PPC64-initfini.s.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/002-Prevent-inlining-in-PPC64-initfini.s.patch
new file mode 100644 (file)
index 0000000..47cc8b2
--- /dev/null
@@ -0,0 +1,26 @@
+From a4f388e111ce05e2ab7912cff3c9070334bb74ae Mon Sep 17 00:00:00 2001
+From: Josh Stone <jistone@redhat.com>
+Date: Fri, 20 Jan 2017 15:41:56 -0800
+Subject: [PATCH] Prevent inlining in PPC64 initfini.s
+
+Ref: https://sourceware.org/ml/libc-alpha/2012-01/msg00195.html
+---
+ sysdeps/powerpc/powerpc64/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
+index 78d4f07e575f..fe96aae4d43e 100644
+--- a/sysdeps/powerpc/powerpc64/Makefile
++++ b/sysdeps/powerpc/powerpc64/Makefile
+@@ -28,7 +28,7 @@ elide-routines.os += hp-timing
+ ifneq ($(elf),no)
+ # The initfini generation code doesn't work in the presence of -fPIC, so
+ # we use -fpic instead which is much better.
+-CFLAGS-initfini.s += -fpic -O1
++CFLAGS-initfini.s += -fpic -O1 -fno-inline
+ endif
+ endif
+-- 
+2.9.3
+
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/003-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.11.1/003-newer-gcc.patch
new file mode 100644 (file)
index 0000000..a96b488
--- /dev/null
@@ -0,0 +1,26 @@
+diff --git a/configure b/configure
+index b6752d147c6b..6089a3403410 100755
+--- a/configure
++++ b/configure
+@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
+   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
+   case $ac_prog_version in
+     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+-    3.4* | 4.[0-9]* )
++    3.4* | [4-9].* )
+        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+diff --git a/configure.in b/configure.in
+index 56849dfc489a..09677eb3d0c1 100644
+--- a/configure.in
++++ b/configure.in
+@@ -960,7 +960,7 @@ fi
+ # These programs are version sensitive.
+ AC_CHECK_TOOL_PREFIX
+ AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
+-  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
++  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
+   critic_missing="$critic_missing gcc")
+ AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
+   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/001-PowerPC-Remove-unnecessary-mnew-mnemonics.patch
deleted file mode 100644 (file)
index 744eb18..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From b3563932f85d60bb0d38b0a5f3b8f4abc133f890 Mon Sep 17 00:00:00 2001
-From: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
-Date: Thu, 1 Nov 2012 18:00:06 -0500
-Subject: [PATCH] PowerPC: Remove unnecessary -mnew-mnemonics.
-
----
- sysdeps/powerpc/Makefile | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
-index 79dd6fa976d5..7442b6709ad1 100644
---- a/sysdeps/powerpc/Makefile
-+++ b/sysdeps/powerpc/Makefile
-@@ -1,7 +1,3 @@
--# We always want to use the new mnemonic syntax even if we are on a RS6000
--# machine.
--+cflags += -mnew-mnemonics
--
- ifeq ($(subdir),gmon)
- sysdep_routines += ppc-mcount
- endif
--- 
-2.9.3
-
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/002-Prevent-inlining-in-PPC64-initfini.s.patch
deleted file mode 100644 (file)
index 47cc8b2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From a4f388e111ce05e2ab7912cff3c9070334bb74ae Mon Sep 17 00:00:00 2001
-From: Josh Stone <jistone@redhat.com>
-Date: Fri, 20 Jan 2017 15:41:56 -0800
-Subject: [PATCH] Prevent inlining in PPC64 initfini.s
-
-Ref: https://sourceware.org/ml/libc-alpha/2012-01/msg00195.html
----
- sysdeps/powerpc/powerpc64/Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
-index 78d4f07e575f..fe96aae4d43e 100644
---- a/sysdeps/powerpc/powerpc64/Makefile
-+++ b/sysdeps/powerpc/powerpc64/Makefile
-@@ -28,7 +28,7 @@ elide-routines.os += hp-timing
- ifneq ($(elf),no)
- # The initfini generation code doesn't work in the presence of -fPIC, so
- # we use -fpic instead which is much better.
--CFLAGS-initfini.s += -fpic -O1
-+CFLAGS-initfini.s += -fpic -O1 -fno-inline
- endif
- endif
--- 
-2.9.3
-
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/003-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-powerpc64-linux/patches/glibc/2.12.2/003-newer-gcc.patch
deleted file mode 100644 (file)
index a96b488..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/configure b/configure
-index b6752d147c6b..6089a3403410 100755
---- a/configure
-+++ b/configure
-@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
-   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
-   case $ac_prog_version in
-     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
--    3.4* | 4.[0-9]* )
-+    3.4* | [4-9].* )
-        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
-     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
-diff --git a/configure.in b/configure.in
-index 56849dfc489a..09677eb3d0c1 100644
---- a/configure.in
-+++ b/configure.in
-@@ -960,7 +960,7 @@ fi
- # These programs are version sensitive.
- AC_CHECK_TOOL_PREFIX
- AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
--  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
-+  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
-   critic_missing="$critic_missing gcc")
- AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
-   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
index 4aab4f4fd44457eccf86ed90e8290bdd59f1e6e1..aa13119d50c19f346b521037f2f490a5e82de246 100644 (file)
@@ -290,7 +290,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
 # C-library
 #
 CT_LIBC="glibc"
-CT_LIBC_VERSION="2.12.2"
+CT_LIBC_VERSION="2.11.1"
 CT_LIBC_glibc=y
 # CT_LIBC_musl is not set
 # CT_LIBC_uClibc is not set
@@ -309,9 +309,9 @@ CT_THREADS="nptl"
 # CT_LIBC_GLIBC_V_2_14_1 is not set
 # CT_LIBC_GLIBC_V_2_14 is not set
 # CT_LIBC_GLIBC_V_2_13 is not set
-CT_LIBC_GLIBC_V_2_12_2=y
+# CT_LIBC_GLIBC_V_2_12_2 is not set
 # CT_LIBC_GLIBC_V_2_12_1 is not set
-# CT_LIBC_GLIBC_V_2_11_1 is not set
+CT_LIBC_GLIBC_V_2_11_1=y
 # CT_LIBC_GLIBC_V_2_11 is not set
 # CT_LIBC_GLIBC_V_2_10_1 is not set
 # CT_LIBC_GLIBC_V_2_9 is not set
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch
new file mode 100644 (file)
index 0000000..cba416e
--- /dev/null
@@ -0,0 +1,63 @@
+From 2739047682590b1df473401b4febf424f857fccf Mon Sep 17 00:00:00 2001
+From: Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+Date: Sun, 17 Apr 2011 20:43:59 -0400
+Subject: [PATCH] Use .machine to prevent AS from complaining about z9-109
+ instructions in iconv modules
+
+---
+ sysdeps/s390/s390-64/utf16-utf32-z9.c | 5 ++++-
+ sysdeps/s390/s390-64/utf8-utf16-z9.c  | 5 ++++-
+ sysdeps/s390/s390-64/utf8-utf32-z9.c  | 5 ++++-
+ 3 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/sysdeps/s390/s390-64/utf16-utf32-z9.c b/sysdeps/s390/s390-64/utf16-utf32-z9.c
+index 14daf2118fe5..5bcaaaedec9c 100644
+--- a/sysdeps/s390/s390-64/utf16-utf32-z9.c
++++ b/sysdeps/s390/s390-64/utf16-utf32-z9.c
+@@ -169,7 +169,10 @@ gconv_end (struct __gconv_step *data)
+     register unsigned long long outlen asm("11") = outend - outptr;   \
+     uint64_t cc = 0;                                                  \
+                                                                       \
+-    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
++    asm volatile (".machine push       \n\t"                          \
++                  ".machine \"z9-109\" \n\t"                          \
++                "0: " INSTRUCTION "  \n\t"                            \
++                  ".machine pop        \n\t"                          \
+                   "   jo     0b        \n\t"                          \
+                 "   ipm    %2        \n"                              \
+                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
+diff --git a/sysdeps/s390/s390-64/utf8-utf16-z9.c b/sysdeps/s390/s390-64/utf8-utf16-z9.c
+index 5f73f3c59e21..812a42fae44c 100644
+--- a/sysdeps/s390/s390-64/utf8-utf16-z9.c
++++ b/sysdeps/s390/s390-64/utf8-utf16-z9.c
+@@ -151,7 +151,10 @@ gconv_end (struct __gconv_step *data)
+     register unsigned long long outlen asm("11") = outend - outptr;   \
+     uint64_t cc = 0;                                                  \
+                                                                       \
+-    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
++    asm volatile (".machine push       \n\t"                          \
++                  ".machine \"z9-109\" \n\t"                          \
++                "0: " INSTRUCTION "  \n\t"                            \
++                  ".machine pop        \n\t"                          \
+                   "   jo     0b        \n\t"                          \
+                 "   ipm    %2        \n"                              \
+                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
+diff --git a/sysdeps/s390/s390-64/utf8-utf32-z9.c b/sysdeps/s390/s390-64/utf8-utf32-z9.c
+index 17ef8bc890c3..0ffd848c8124 100644
+--- a/sysdeps/s390/s390-64/utf8-utf32-z9.c
++++ b/sysdeps/s390/s390-64/utf8-utf32-z9.c
+@@ -155,7 +155,10 @@ gconv_end (struct __gconv_step *data)
+     register unsigned long long outlen asm("11") = outend - outptr;   \
+     uint64_t cc = 0;                                                  \
+                                                                       \
+-    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
++    asm volatile (".machine push       \n\t"                          \
++                  ".machine \"z9-109\" \n\t"                          \
++                "0: " INSTRUCTION "  \n\t"                            \
++                  ".machine pop        \n\t"                          \
+                   "   jo     0b        \n\t"                          \
+                 "   ipm    %2        \n"                              \
+                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
+-- 
+2.9.3
+
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.11.1/002-newer-gcc.patch
new file mode 100644 (file)
index 0000000..a96b488
--- /dev/null
@@ -0,0 +1,26 @@
+diff --git a/configure b/configure
+index b6752d147c6b..6089a3403410 100755
+--- a/configure
++++ b/configure
+@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
+   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
+   case $ac_prog_version in
+     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+-    3.4* | 4.[0-9]* )
++    3.4* | [4-9].* )
+        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+diff --git a/configure.in b/configure.in
+index 56849dfc489a..09677eb3d0c1 100644
+--- a/configure.in
++++ b/configure.in
+@@ -960,7 +960,7 @@ fi
+ # These programs are version sensitive.
+ AC_CHECK_TOOL_PREFIX
+ AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
+-  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
++  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
+   critic_missing="$critic_missing gcc")
+ AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
+   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/001-Use-.machine-to-prevent-AS-from-complaining-about-z9.patch
deleted file mode 100644 (file)
index cba416e..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-From 2739047682590b1df473401b4febf424f857fccf Mon Sep 17 00:00:00 2001
-From: Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
-Date: Sun, 17 Apr 2011 20:43:59 -0400
-Subject: [PATCH] Use .machine to prevent AS from complaining about z9-109
- instructions in iconv modules
-
----
- sysdeps/s390/s390-64/utf16-utf32-z9.c | 5 ++++-
- sysdeps/s390/s390-64/utf8-utf16-z9.c  | 5 ++++-
- sysdeps/s390/s390-64/utf8-utf32-z9.c  | 5 ++++-
- 3 files changed, 12 insertions(+), 3 deletions(-)
-
-diff --git a/sysdeps/s390/s390-64/utf16-utf32-z9.c b/sysdeps/s390/s390-64/utf16-utf32-z9.c
-index 14daf2118fe5..5bcaaaedec9c 100644
---- a/sysdeps/s390/s390-64/utf16-utf32-z9.c
-+++ b/sysdeps/s390/s390-64/utf16-utf32-z9.c
-@@ -169,7 +169,10 @@ gconv_end (struct __gconv_step *data)
-     register unsigned long long outlen asm("11") = outend - outptr;   \
-     uint64_t cc = 0;                                                  \
-                                                                       \
--    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
-+    asm volatile (".machine push       \n\t"                          \
-+                  ".machine \"z9-109\" \n\t"                          \
-+                "0: " INSTRUCTION "  \n\t"                            \
-+                  ".machine pop        \n\t"                          \
-                   "   jo     0b        \n\t"                          \
-                 "   ipm    %2        \n"                              \
-                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
-diff --git a/sysdeps/s390/s390-64/utf8-utf16-z9.c b/sysdeps/s390/s390-64/utf8-utf16-z9.c
-index 5f73f3c59e21..812a42fae44c 100644
---- a/sysdeps/s390/s390-64/utf8-utf16-z9.c
-+++ b/sysdeps/s390/s390-64/utf8-utf16-z9.c
-@@ -151,7 +151,10 @@ gconv_end (struct __gconv_step *data)
-     register unsigned long long outlen asm("11") = outend - outptr;   \
-     uint64_t cc = 0;                                                  \
-                                                                       \
--    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
-+    asm volatile (".machine push       \n\t"                          \
-+                  ".machine \"z9-109\" \n\t"                          \
-+                "0: " INSTRUCTION "  \n\t"                            \
-+                  ".machine pop        \n\t"                          \
-                   "   jo     0b        \n\t"                          \
-                 "   ipm    %2        \n"                              \
-                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
-diff --git a/sysdeps/s390/s390-64/utf8-utf32-z9.c b/sysdeps/s390/s390-64/utf8-utf32-z9.c
-index 17ef8bc890c3..0ffd848c8124 100644
---- a/sysdeps/s390/s390-64/utf8-utf32-z9.c
-+++ b/sysdeps/s390/s390-64/utf8-utf32-z9.c
-@@ -155,7 +155,10 @@ gconv_end (struct __gconv_step *data)
-     register unsigned long long outlen asm("11") = outend - outptr;   \
-     uint64_t cc = 0;                                                  \
-                                                                       \
--    asm volatile ("0: " INSTRUCTION "  \n\t"                          \
-+    asm volatile (".machine push       \n\t"                          \
-+                  ".machine \"z9-109\" \n\t"                          \
-+                "0: " INSTRUCTION "  \n\t"                            \
-+                  ".machine pop        \n\t"                          \
-                   "   jo     0b        \n\t"                          \
-                 "   ipm    %2        \n"                              \
-                 : "+a" (pOutput), "+a" (pInput), "+d" (cc),           \
--- 
-2.9.3
-
diff --git a/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/002-newer-gcc.patch b/src/ci/docker/host-x86_64/dist-s390x-linux/patches/glibc/2.12.2/002-newer-gcc.patch
deleted file mode 100644 (file)
index a96b488..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/configure b/configure
-index b6752d147c6b..6089a3403410 100755
---- a/configure
-+++ b/configure
-@@ -5079,7 +5079,7 @@ $as_echo_n "checking version of $CC... " >&6; }
-   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`
-   case $ac_prog_version in
-     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
--    3.4* | 4.[0-9]* )
-+    3.4* | [4-9].* )
-        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
-     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
-diff --git a/configure.in b/configure.in
-index 56849dfc489a..09677eb3d0c1 100644
---- a/configure.in
-+++ b/configure.in
-@@ -960,7 +960,7 @@ fi
- # These programs are version sensitive.
- AC_CHECK_TOOL_PREFIX
- AC_CHECK_PROG_VER(CC, ${ac_tool_prefix}gcc ${ac_tool_prefix}cc, -v,
--  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | 4.[0-9]* ],
-+  [version \([egcygnustpi-]*[0-9.]*\)], [3.4* | [4-9].* ],
-   critic_missing="$critic_missing gcc")
- AC_CHECK_PROG_VER(MAKE, gnumake gmake make, --version,
-   [GNU Make[^0-9]*\([0-9][0-9.]*\)],
index cd1c41b02e3122e53059ac6a9a5565cd8952cb62..c9c141afad131d1883466c44a7847e0108bf90a5 100644 (file)
@@ -270,7 +270,7 @@ CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
 # C-library
 #
 CT_LIBC="glibc"
-CT_LIBC_VERSION="2.12.2"
+CT_LIBC_VERSION="2.11.1"
 CT_LIBC_glibc=y
 # CT_LIBC_musl is not set
 # CT_LIBC_uClibc is not set
@@ -289,9 +289,9 @@ CT_THREADS="nptl"
 # CT_LIBC_GLIBC_V_2_14_1 is not set
 # CT_LIBC_GLIBC_V_2_14 is not set
 # CT_LIBC_GLIBC_V_2_13 is not set
-CT_LIBC_GLIBC_V_2_12_2=y
+# CT_LIBC_GLIBC_V_2_12_2 is not set
 # CT_LIBC_GLIBC_V_2_12_1 is not set
-# CT_LIBC_GLIBC_V_2_11_1 is not set
+CT_LIBC_GLIBC_V_2_11_1=y
 # CT_LIBC_GLIBC_V_2_11 is not set
 # CT_LIBC_GLIBC_V_2_10_1 is not set
 # CT_LIBC_GLIBC_V_2_9 is not set
index 5573d87aa2e55c278399a8f0e0c1b6a12bf11600..0aeb6a04e5f773ec8d12ef17351ba9ef77f5d88f 100644 (file)
@@ -35,11 +35,26 @@ x--expand-yaml-anchors--remove:
     CI_JOB_NAME: ${{ matrix.name }}
 
   - &public-variables
-    SCCACHE_BUCKET: rust-lang-gha-caches
-    TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate
-    CACHE_DOMAIN: ci-caches-gha.rust-lang.org
+    SCCACHE_BUCKET: rust-lang-ci-sccache2
+    TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate
+    CACHE_DOMAIN: ci-caches.rust-lang.org
 
   - &prod-variables
+    SCCACHE_BUCKET: rust-lang-ci-sccache2
+    DEPLOY_BUCKET: rust-lang-ci2
+    TOOLSTATE_REPO: https://github.com/rust-lang-nursery/rust-toolstate
+    TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues
+    TOOLSTATE_PUBLISH: 1
+    # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named
+    # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to
+    # rotate them in a single branch while keeping the old key in another
+    # branch, which wouldn't be possible if the key was named with the kind
+    # (caches, artifacts...).
+    CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+    ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+    CACHE_DOMAIN: ci-caches.rust-lang.org
+
+  - &dummy-variables
     SCCACHE_BUCKET: rust-lang-gha-caches
     DEPLOY_BUCKET: rust-lang-gha
     TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate
@@ -92,6 +107,15 @@ x--expand-yaml-anchors--remove:
         if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'
         <<: *step
 
+      # Rust Log Analyzer can't currently detect the PR number of a GitHub
+      # Actions build on its own, so a hint in the log message is needed to
+      # point it in the right direction.
+      - name: configure the PR in which the error message will be posted
+        run: echo "[CI_PR_NUMBER=$num]"
+        env:
+          num: ${{ github.event.number }}
+        if: success() && !env.SKIP_JOBS && github.event_name == 'pull_request'
+
       - name: add extra environment variables
         run: src/ci/scripts/setup-environment.sh
         env:
@@ -223,6 +247,7 @@ on:
     branches:
       - auto
       - try
+      - try-perf
       - master
   pull_request:
     branches:
@@ -261,7 +286,7 @@ jobs:
     name: try
     env:
       <<: [*shared-ci-variables, *prod-variables]
-    if: github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'
+    if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'
     strategy:
       matrix:
         include:
@@ -556,7 +581,7 @@ jobs:
     <<: *base-ci-job
     name: auto-fallible
     env:
-      <<: [*shared-ci-variables, *prod-variables]
+      <<: [*shared-ci-variables, *dummy-variables]
     if: github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'
     strategy:
       matrix:
@@ -621,11 +646,11 @@ jobs:
   # successful listening to webhooks only.
   try-success:
     needs: [try]
-    if: "success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'"
+    if: "success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     <<: *base-success-job
   try-failure:
     needs: [try]
-    if: "!success() && github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'"
+    if: "!success() && github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
     <<: *base-failure-job
   auto-success:
     needs: [auto]
index 84a31397b34f9d405df44f2899ff17a4828dba18..a914f2c7e5cdb771fa465de142381a51c53b580e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 84a31397b34f9d405df44f2899ff17a4828dba18
+Subproject commit a914f2c7e5cdb771fa465de142381a51c53b580e
index 82bec5877c77cfad530ca11095db4456d757f668..bd6e4a9f59c5c1545f572266af77f5c7a5bad6d1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 82bec5877c77cfad530ca11095db4456d757f668
+Subproject commit bd6e4a9f59c5c1545f572266af77f5c7a5bad6d1
index 0ea7bc494f1289234d8800bb9185021e0ad946f0..b329ce37424874ad4db94f829a55807c6e21d2cb 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0ea7bc494f1289234d8800bb9185021e0ad946f0
+Subproject commit b329ce37424874ad4db94f829a55807c6e21d2cb
index 0b4bb05c1db23e66ead131d085b9ced6d7bf9141..7b0280d5b78a74bc2b014782e1e113aebd11ae86 100644 (file)
@@ -12,7 +12,7 @@ This option is deprecated and does nothing.
 This option lets you choose which code model to use. \
 Code models put constraints on address ranges that the program and its symbols may use. \
 With smaller address ranges machine instructions
-may be able to use use more compact addressing modes.
+may be able to use more compact addressing modes.
 
 The specific ranges depend on target architectures and addressing modes available to them. \
 For x86 more detailed description of its code models can be found in
@@ -42,6 +42,18 @@ generated code, but may be slower to compile.
 The default value, if not specified, is 16 for non-incremental builds. For
 incremental builds the default is 256 which allows caching to be more granular.
 
+## control-flow-guard
+
+This flag controls whether LLVM enables the Windows [Control Flow 
+Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) 
+platform security feature. This flag is currently ignored for non-Windows targets. 
+It takes one of the following values:
+
+* `y`, `yes`, `on`, `checks`, or no value: enable Control Flow Guard.
+* `nochecks`: emit Control Flow Guard metadata without runtime enforcement checks (this 
+should only be used for testing purposes as it does not provide security enforcement).
+* `n`, `no`, `off`: do not enable Control Flow Guard (the default).
+
 ## debug-assertions
 
 This flag lets you turn `cfg(debug_assertions)` [conditional
index 5e2e04c063bc483abff4700462958c6791e9573a..93908e9190e6436af2fdc6290aec711543fe252e 100644 (file)
@@ -26,6 +26,9 @@ of bugs:
 * Double-free, invalid free
 * Memory leaks
 
+The memory leak detection is enabled by default on Linux, and can be enabled
+with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
+
 AddressSanitizer is supported on the following targets:
 
 * `x86_64-apple-darwin`
@@ -196,10 +199,6 @@ fn main() {
 
 ```shell
 $ export \
-  CC=clang \
-  CXX=clang++ \
-  CFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \
-  CXXFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \
   RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
   RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
 $ cargo clean
index 3320ebdf821d054e31217ba4b02591375d268db0..f225aa18853c7214bfb31263212f890265096141 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use core::any::Any;
-use core::array::LengthAtMost32;
 use core::borrow;
 use core::cmp::Ordering;
 use core::convert::{From, TryFrom};
@@ -871,10 +870,7 @@ fn from(s: Box<str>) -> Self {
 }
 
 #[stable(feature = "box_from_array", since = "1.45.0")]
-impl<T, const N: usize> From<[T; N]> for Box<[T]>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> From<[T; N]> for Box<[T]> {
     /// Converts a `[T; N]` into a `Box<[T]>`
     ///
     /// This conversion moves the array to newly heap-allocated memory.
@@ -890,10 +886,7 @@ fn from(s: Box<str>) -> Self {
 }
 
 #[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
-impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
     type Error = Box<[T]>;
 
     fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
index 15313e333ce732a876646d5fe533b77a58f4d0bf..8398cfa3bd34e2ea07fbca98e3ce7ec9a7d1f1ed 100644 (file)
@@ -1,9 +1,9 @@
 //! A priority queue implemented with a binary heap.
 //!
-//! Insertion and popping the largest element have `O(log(n))` time complexity.
-//! Checking the largest element is `O(1)`. Converting a vector to a binary heap
-//! can be done in-place, and has `O(n)` complexity. A binary heap can also be
-//! converted to a sorted vector in-place, allowing it to be used for an `O(n * log(n))`
+//! Insertion and popping the largest element have *O*(log(*n*)) time complexity.
+//! Checking the largest element is *O*(1). Converting a vector to a binary heap
+//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be
+//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*))
 //! in-place heapsort.
 //!
 //! # Examples
 ///
 /// | [push] | [pop]     | [peek]/[peek\_mut] |
 /// |--------|-----------|--------------------|
-/// | O(1)~  | O(log(n)) | O(1)               |
+/// | O(1)~  | *O*(log(*n*)) | *O*(1)               |
 ///
 /// The value for `push` is an expected cost; the method documentation gives a
 /// more detailed analysis.
@@ -398,7 +398,7 @@ pub fn with_capacity(capacity: usize) -> BinaryHeap<T> {
     ///
     /// # Time complexity
     ///
-    /// Cost is `O(1)` in the worst case.
+    /// Cost is *O*(1) in the worst case.
     #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
     pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
         if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: true }) }
@@ -422,7 +422,7 @@ pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
     ///
     /// # Time complexity
     ///
-    /// The worst case cost of `pop` on a heap containing *n* elements is `O(log(n))`.
+    /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)).
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<T> {
         self.data.pop().map(|mut item| {
@@ -455,15 +455,15 @@ pub fn pop(&mut self) -> Option<T> {
     ///
     /// The expected cost of `push`, averaged over every possible ordering of
     /// the elements being pushed, and over a sufficiently large number of
-    /// pushes, is `O(1)`. This is the most meaningful cost metric when pushing
+    /// pushes, is *O*(1). This is the most meaningful cost metric when pushing
     /// elements that are *not* already in any sorted pattern.
     ///
     /// The time complexity degrades if elements are pushed in predominantly
     /// ascending order. In the worst case, elements are pushed in ascending
-    /// sorted order and the amortized cost per push is `O(log(n))` against a heap
+    /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap
     /// containing *n* elements.
     ///
-    /// The worst case cost of a *single* call to `push` is `O(n)`. The worst case
+    /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case
     /// occurs when capacity is exhausted and needs a resize. The resize cost
     /// has been amortized in the previous figures.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -643,7 +643,7 @@ fn better_to_rebuild(len1: usize, len2: usize) -> bool {
     /// The remaining elements will be removed on drop in heap order.
     ///
     /// Note:
-    /// * `.drain_sorted()` is `O(n * log(n))`; much slower than `.drain()`.
+    /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`.
     ///   You should use the latter for most cases.
     ///
     /// # Examples
@@ -756,7 +756,7 @@ pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
     ///
     /// # Time complexity
     ///
-    /// Cost is `O(1)` in the worst case.
+    /// Cost is *O*(1) in the worst case.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn peek(&self) -> Option<&T> {
         self.data.get(0)
@@ -1312,7 +1312,7 @@ unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {}
 impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
     /// Converts a `Vec<T>` into a `BinaryHeap<T>`.
     ///
-    /// This conversion happens in-place, and has `O(n)` time complexity.
+    /// This conversion happens in-place, and has *O*(*n*) time complexity.
     fn from(vec: Vec<T>) -> BinaryHeap<T> {
         let mut heap = BinaryHeap { data: vec };
         heap.rebuild();
index d2f4278d0d0e0a817d51246c971265c4056c6103..24d1f61fa68c48dd773ec161e2d1f98356b4f4bd 100644 (file)
@@ -1672,19 +1672,12 @@ pub(super) fn peek(&self) -> Option<(&K, &V)> {
         edge.reborrow().next_kv().ok().map(|kv| kv.into_kv())
     }
 
-    unsafe fn next_kv(
-        &mut self,
-    ) -> Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>> {
-        let edge = self.cur_leaf_edge.as_ref()?;
-        unsafe { ptr::read(edge).next_kv().ok() }
-    }
-
     /// Implementation of a typical `DrainFilter::next` method, given the predicate.
     pub(super) fn next<F>(&mut self, pred: &mut F) -> Option<(K, V)>
     where
         F: FnMut(&K, &mut V) -> bool,
     {
-        while let Some(mut kv) = unsafe { self.next_kv() } {
+        while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() {
             let (k, v) = kv.kv_mut();
             if pred(k, v) {
                 *self.length -= 1;
index 36b5785fdf6c5ed930340eb4b38d772d7dd21f4a..1f875f6c5217f4897cb67711b05670b9dfae509a 100644 (file)
@@ -404,7 +404,7 @@ pub const fn new() -> Self {
     /// This reuses all the nodes from `other` and moves them into `self`. After
     /// this operation, `other` becomes empty.
     ///
-    /// This operation should compute in `O(1)` time and `O(1)` memory.
+    /// This operation should compute in *O*(1) time and *O*(1) memory.
     ///
     /// # Examples
     ///
@@ -561,7 +561,7 @@ pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
 
     /// Returns `true` if the `LinkedList` is empty.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -582,7 +582,7 @@ pub fn is_empty(&self) -> bool {
 
     /// Returns the length of the `LinkedList`.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -608,7 +608,7 @@ pub fn len(&self) -> usize {
 
     /// Removes all elements from the `LinkedList`.
     ///
-    /// This operation should compute in `O(n)` time.
+    /// This operation should compute in *O*(*n*) time.
     ///
     /// # Examples
     ///
@@ -751,7 +751,7 @@ pub fn back_mut(&mut self) -> Option<&mut T> {
 
     /// Adds an element first in the list.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -774,7 +774,7 @@ pub fn push_front(&mut self, elt: T) {
     /// Removes the first element and returns it, or `None` if the list is
     /// empty.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -797,7 +797,7 @@ pub fn pop_front(&mut self) -> Option<T> {
 
     /// Appends an element to the back of a list.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -817,7 +817,7 @@ pub fn push_back(&mut self, elt: T) {
     /// Removes the last element from a list and returns it, or `None` if
     /// it is empty.
     ///
-    /// This operation should compute in `O(1)` time.
+    /// This operation should compute in *O*(1) time.
     ///
     /// # Examples
     ///
@@ -838,7 +838,7 @@ pub fn pop_back(&mut self) -> Option<T> {
     /// Splits the list into two at the given index. Returns everything after the given index,
     /// including the index.
     ///
-    /// This operation should compute in `O(n)` time.
+    /// This operation should compute in *O*(*n*) time.
     ///
     /// # Panics
     ///
@@ -894,7 +894,7 @@ pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
 
     /// Removes the element at the given index and returns it.
     ///
-    /// This operation should compute in `O(n)` time.
+    /// This operation should compute in *O*(*n*) time.
     ///
     /// # Panics
     /// Panics if at >= len
index 2efb94e8afe57731485f7bca4665a93e235abf1e..d3c6d493d6d8d87faf4e3da5c026b7a112a0d5ae 100644 (file)
@@ -1,7 +1,7 @@
 //! A double-ended queue implemented with a growable ring buffer.
 //!
-//! This queue has `O(1)` amortized inserts and removals from both ends of the
-//! container. It also has `O(1)` indexing like a vector. The contained elements
+//! This queue has *O*(1) amortized inserts and removals from both ends of the
+//! container. It also has *O*(1) indexing like a vector. The contained elements
 //! are not required to be copyable, and the queue will be sendable if the
 //! contained type is sendable.
 
@@ -9,7 +9,6 @@
 
 // ignore-tidy-filelength
 
-use core::array::LengthAtMost32;
 use core::cmp::{self, Ordering};
 use core::fmt;
 use core::hash::{Hash, Hasher};
@@ -1512,7 +1511,7 @@ fn is_contiguous(&self) -> bool {
     /// Removes an element from anywhere in the `VecDeque` and returns it,
     /// replacing it with the first element.
     ///
-    /// This does not preserve ordering, but is `O(1)`.
+    /// This does not preserve ordering, but is *O*(1).
     ///
     /// Returns `None` if `index` is out of bounds.
     ///
@@ -1547,7 +1546,7 @@ pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
     /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the
     /// last element.
     ///
-    /// This does not preserve ordering, but is `O(1)`.
+    /// This does not preserve ordering, but is *O*(1).
     ///
     /// Returns `None` if `index` is out of bounds.
     ///
@@ -2331,7 +2330,7 @@ pub fn make_contiguous(&mut self) -> &mut [T] {
     ///
     /// # Complexity
     ///
-    /// Takes `O(min(mid, len() - mid))` time and no extra space.
+    /// Takes `*O*(min(mid, len() - mid))` time and no extra space.
     ///
     /// # Examples
     ///
@@ -2374,7 +2373,7 @@ pub fn rotate_left(&mut self, mid: usize) {
     ///
     /// # Complexity
     ///
-    /// Takes `O(min(k, len() - k))` time and no extra space.
+    /// Takes `*O*(min(k, len() - k))` time and no extra space.
     ///
     /// # Examples
     ///
@@ -2889,9 +2888,9 @@ fn eq(&self, other: &$rhs) -> bool {
 __impl_slice_eq1! { [] VecDeque<A>, Vec<B>, }
 __impl_slice_eq1! { [] VecDeque<A>, &[B], }
 __impl_slice_eq1! { [] VecDeque<A>, &mut [B], }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, [B; N], [B; N]: LengthAtMost32 }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, &[B; N], [B; N]: LengthAtMost32 }
-__impl_slice_eq1! { [const N: usize] VecDeque<A>, &mut [B; N], [B; N]: LengthAtMost32 }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, [B; N], }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, &[B; N], }
+__impl_slice_eq1! { [const N: usize] VecDeque<A>, &mut [B; N], }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: PartialOrd> PartialOrd for VecDeque<A> {
@@ -3076,7 +3075,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
     /// [`Vec<T>`]: crate::vec::Vec
     /// [`VecDeque<T>`]: crate::collections::VecDeque
     ///
-    /// This never needs to re-allocate, but does need to do `O(n)` data movement if
+    /// This never needs to re-allocate, but does need to do *O*(*n*) data movement if
     /// the circular buffer doesn't happen to be at the beginning of the allocation.
     ///
     /// # Examples
@@ -3084,7 +3083,7 @@ impl<T> From<VecDeque<T>> for Vec<T> {
     /// ```
     /// use std::collections::VecDeque;
     ///
-    /// // This one is O(1).
+    /// // This one is *O*(1).
     /// let deque: VecDeque<_> = (1..5).collect();
     /// let ptr = deque.as_slices().0.as_ptr();
     /// let vec = Vec::from(deque);
index 87aee950082e9cac6e217db63c3f4a0e901e2147..90e2d2531c552e25a2857b6fd1deeb060b8bd30d 100644 (file)
@@ -84,7 +84,6 @@
 #![feature(cfg_target_has_atomic)]
 #![feature(coerce_unsized)]
 #![feature(const_btree_new)]
-#![feature(const_generic_impls_guard)]
 #![feature(const_generics)]
 #![feature(const_in_array_repeat_expressions)]
 #![feature(cow_is_borrowed)]
index 77ff567aa7af172c074b3c744f180900e77c326c..96dfc2f42519b3b0f5ae34ccce38c99d36104db1 100644 (file)
 use std::boxed::Box;
 
 use core::any::Any;
-use core::array::LengthAtMost32;
 use core::borrow;
 use core::cell::Cell;
 use core::cmp::Ordering;
@@ -1516,10 +1515,7 @@ fn from(cow: Cow<'a, B>) -> Rc<B> {
 }
 
 #[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
-impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> TryFrom<Rc<[T]>> for Rc<[T; N]> {
     type Error = Rc<[T]>;
 
     fn try_from(boxed_slice: Rc<[T]>) -> Result<Self, Self::Error> {
index 1c3879c40c2f94c384009967e4c5e5a73bdb5bde..05398ca68c8ba753549b99a293cadf9d73f51b26 100644 (file)
@@ -65,7 +65,7 @@
 ///
 /// # Examples
 ///
-/// You can create a `String` from [a literal string][str] with [`String::from`]:
+/// You can create a `String` from [a literal string][`str`] with [`String::from`]:
 ///
 /// [`String::from`]: From::from
 ///
 ///
 /// Here, there's no need to allocate more memory inside the loop.
 ///
-/// [`&str`]: str
+/// [`str`]: type@str
+/// [`&str`]: type@str
 /// [`Deref`]: core::ops::Deref
 /// [`as_str()`]: String::as_str
 #[derive(PartialOrd, Eq, Ord)]
@@ -666,15 +667,16 @@ pub fn into_raw_parts(self) -> (*mut u8, usize, usize) {
     /// This is highly unsafe, due to the number of invariants that aren't
     /// checked:
     ///
-    /// * The memory at `ptr` needs to have been previously allocated by the
+    /// * The memory at `buf` needs to have been previously allocated by the
     ///   same allocator the standard library uses, with a required alignment of exactly 1.
     /// * `length` needs to be less than or equal to `capacity`.
     /// * `capacity` needs to be the correct value.
+    /// * The first `length` bytes at `buf` need to be valid UTF-8.
     ///
     /// Violating these may cause problems like corrupting the allocator's
     /// internal data structures.
     ///
-    /// The ownership of `ptr` is effectively transferred to the
+    /// The ownership of `buf` is effectively transferred to the
     /// `String` which may then deallocate, reallocate or change the
     /// contents of memory pointed to by the pointer at will. Ensure
     /// that nothing else uses the pointer after calling this
@@ -1162,7 +1164,7 @@ pub fn pop(&mut self) -> Option<char> {
 
     /// Removes a [`char`] from this `String` at a byte position and returns it.
     ///
-    /// This is an `O(n)` operation, as it requires copying every element in the
+    /// This is an *O*(*n*) operation, as it requires copying every element in the
     /// buffer.
     ///
     /// # Panics
@@ -1262,7 +1264,7 @@ pub fn retain<F>(&mut self, mut f: F)
 
     /// Inserts a character into this `String` at a byte position.
     ///
-    /// This is an `O(n)` operation as it requires copying every element in the
+    /// This is an *O*(*n*) operation as it requires copying every element in the
     /// buffer.
     ///
     /// # Panics
@@ -1309,7 +1311,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
 
     /// Inserts a string slice into this `String` at a byte position.
     ///
-    /// This is an `O(n)` operation as it requires copying every element in the
+    /// This is an *O*(*n*) operation as it requires copying every element in the
     /// buffer.
     ///
     /// # Panics
@@ -1971,7 +1973,7 @@ fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
 ///
 /// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if
 /// necessary). This is done to avoid allocating a new `String` and copying the entire contents on
-/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by
+/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by
 /// repeated concatenation.
 ///
 /// The string on the right-hand side is only borrowed; its contents are copied into the returned
index 0cf250576f176b402408a96585da795e04edeefc..8a5f1ee5076b97d4f67d9aacd2496865e4099fd7 100644 (file)
@@ -7,7 +7,6 @@
 //! [arc]: struct.Arc.html
 
 use core::any::Any;
-use core::array::LengthAtMost32;
 use core::borrow;
 use core::cmp::Ordering;
 use core::convert::{From, TryFrom};
@@ -2162,10 +2161,7 @@ fn from(cow: Cow<'a, B>) -> Arc<B> {
 }
 
 #[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
-impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> TryFrom<Arc<[T]>> for Arc<[T; N]> {
     type Error = Arc<[T]>;
 
     fn try_from(boxed_slice: Arc<[T]>) -> Result<Self, Self::Error> {
index f66b5814ca0d43aa5cae4d0d651403d0b7b59a26..f9f81716e357c243b3c7ec9add10b11f6dabff5e 100644 (file)
@@ -3,6 +3,7 @@
 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};
 // 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();
@@ -268,7 +283,14 @@ fn test_iter_mut_mutation() {
 }
 
 #[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"));
@@ -281,6 +303,36 @@ fn test_values_mut() {
     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
@@ -835,10 +887,8 @@ fn drop(&mut self) {
             }
         }
 
-        let mut map = BTreeMap::new();
-        map.insert(0, D);
-        map.insert(4, D);
-        map.insert(8, D);
+        // 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, _| {
@@ -846,7 +896,7 @@ fn drop(&mut self) {
                 true
             }))
         })
-        .ok();
+        .unwrap_err();
 
         assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
         assert_eq!(DROPS.load(Ordering::SeqCst), 3);
@@ -864,10 +914,8 @@ fn drop(&mut self) {
             }
         }
 
-        let mut map = BTreeMap::new();
-        map.insert(0, D);
-        map.insert(4, D);
-        map.insert(8, D);
+        // 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, _| {
@@ -878,7 +926,45 @@ fn drop(&mut self) {
                 }
             }))
         }))
-        .ok();
+        .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);
@@ -1283,6 +1369,34 @@ fn test_split_off_empty_left() {
     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
@@ -1319,7 +1433,7 @@ fn drop(&mut self) {
     map.insert("d", D);
     map.insert("e", D);
 
-    catch_unwind(move || drop(map.into_iter())).ok();
+    catch_unwind(move || drop(map.into_iter())).unwrap_err();
 
     assert_eq!(DROPS.load(Ordering::SeqCst), 5);
 }
@@ -1343,7 +1457,7 @@ fn drop(&mut self) {
         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())).ok();
+        catch_unwind(move || drop(map.into_iter())).unwrap_err();
         assert_eq!(DROPS.load(Ordering::SeqCst), size);
     }
 }
index 5db96a504a6a69a1a72c1181464d92a5b7f40e12..f5a3d0cd4af87fd89e75bf81d3b38ae5b660df66 100644 (file)
@@ -59,7 +59,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use core::array::LengthAtMost32;
 use core::cmp::{self, Ordering};
 use core::fmt;
 use core::hash::{Hash, Hasher};
@@ -1274,11 +1273,10 @@ unsafe fn append_elements(&mut self, other: *const [T]) {
     /// Creates a draining iterator that removes the specified range in the vector
     /// and yields the removed items.
     ///
-    /// Note 1: The element range is removed even if the iterator is only
-    /// partially consumed or not consumed at all.
-    ///
-    /// Note 2: It is unspecified how many elements are removed from the vector
-    /// if the `Drain` value is leaked.
+    /// When the iterator **is** dropped, all elements in the range are removed
+    /// from the vector, even if the iterator was not fully consumed. If the
+    /// iterator **is not** dropped (with [`mem::forget`] for example), it is
+    /// unspecified how many elements are removed.
     ///
     /// # Panics
     ///
@@ -2379,18 +2377,18 @@ fn ne(&self, other: &$rhs) -> bool { self[..] != other[..] }
 __impl_slice_eq1! { [] Cow<'_, [A]>, Vec<B> where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
 __impl_slice_eq1! { [] Cow<'_, [A]>, &[B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
 __impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B] where A: Clone, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] }
-__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N] where [B; N]: LengthAtMost32, #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [const N: usize] Vec<A>, [B; N], #[stable(feature = "rust1", since = "1.0.0")] }
+__impl_slice_eq1! { [const N: usize] Vec<A>, &[B; N], #[stable(feature = "rust1", since = "1.0.0")] }
 
 // NOTE: some less important impls are omitted to reduce code bloat
 // FIXME(Centril): Reconsider this?
-//__impl_slice_eq1! { [const N: usize] Vec<A>, &mut [B; N], [B; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] [A; N], Vec<B>, [A; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] &[A; N], Vec<B>, [A; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec<B>, [A; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], [B; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], [B; N]: LengthAtMost32 }
-//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], [B; N]: LengthAtMost32 }
+//__impl_slice_eq1! { [const N: usize] Vec<A>, &mut [B; N], }
+//__impl_slice_eq1! { [const N: usize] [A; N], Vec<B>, }
+//__impl_slice_eq1! { [const N: usize] &[A; N], Vec<B>, }
+//__impl_slice_eq1! { [const N: usize] &mut [A; N], Vec<B>, }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, [B; N], }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &[B; N], }
+//__impl_slice_eq1! { [const N: usize] Cow<'a, [A]>, &mut [B; N], }
 
 /// Implements comparison of vectors, lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2494,10 +2492,7 @@ fn from(s: &mut [T]) -> Vec<T> {
 }
 
 #[stable(feature = "vec_from_array", since = "1.44.0")]
-impl<T, const N: usize> From<[T; N]> for Vec<T>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> From<[T; N]> for Vec<T> {
     #[cfg(not(test))]
     fn from(s: [T; N]) -> Vec<T> {
         <[T]>::into_vec(box s)
index ae7ae7044655bae38bfd4e7dae87938e31e3b726..7129f0f24029187bbb93712012dbf5c232f8501f 100644 (file)
@@ -131,7 +131,42 @@ pub const fn new<T>() -> Self {
     pub fn for_value<T: ?Sized>(t: &T) -> Self {
         let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
         debug_assert!(Layout::from_size_align(size, align).is_ok());
-        // SAFETY: see rationale in `new` for why this is using an unsafe variant below
+        // SAFETY: see rationale in `new` for why this is using the unsafe variant
+        unsafe { Layout::from_size_align_unchecked(size, align) }
+    }
+
+    /// Produces layout describing a record that could be used to
+    /// allocate backing structure for `T` (which could be a trait
+    /// or other unsized type like a slice).
+    ///
+    /// # Safety
+    ///
+    /// This function is only safe to call if the following conditions hold:
+    ///
+    /// - If `T` is `Sized`, this function is always safe to call.
+    /// - If the unsized tail of `T` is:
+    ///     - a [slice], then the length of the slice tail must be an intialized
+    ///       integer, and the size of the *entire value*
+    ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
+    ///     - a [trait object], then the vtable part of the pointer must point
+    ///       to a valid vtable for the type `T` acquired by an unsizing coersion,
+    ///       and the size of the *entire value*
+    ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
+    ///     - an (unstable) [extern type], then this function is always safe to
+    ///       call, but may panic or otherwise return the wrong value, as the
+    ///       extern type's layout is not known. This is the same behavior as
+    ///       [`Layout::for_value`] on a reference to an extern type tail.
+    ///     - otherwise, it is conservatively not allowed to call this function.
+    ///
+    /// [slice]: ../../std/primitive.slice.html
+    /// [trait object]: ../../book/ch17-02-trait-objects.html
+    /// [extern type]: ../../unstable-book/language-features/extern-types.html
+    #[unstable(feature = "layout_for_ptr", issue = "69835")]
+    pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
+        // SAFETY: we pass along the prerequisites of these functions to the caller
+        let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
+        debug_assert!(Layout::from_size_align(size, align).is_ok());
+        // SAFETY: see rationale in `new` for why this is using the unsafe variant
         unsafe { Layout::from_size_align_unchecked(size, align) }
     }
 
index f6b8d4ba081467647534044fe3dbbfe4428f4d3d..174f7e26efbace91d244be28e0640b452e73fa58 100644 (file)
@@ -1,6 +1,5 @@
 //! Defines the `IntoIter` owned iterator for arrays.
 
-use super::LengthAtMost32;
 use crate::{
     fmt,
     iter::{ExactSizeIterator, FusedIterator, TrustedLen},
 ///
 /// [array]: ../../std/primitive.array.html
 #[unstable(feature = "array_value_iter", issue = "65798")]
-pub struct IntoIter<T, const N: usize>
-where
-    [T; N]: LengthAtMost32,
-{
+pub struct IntoIter<T, const N: usize> {
     /// This is the array we are iterating over.
     ///
     /// Elements with index `i` where `alive.start <= i < alive.end` have not
@@ -39,10 +35,7 @@ pub struct IntoIter<T, const N: usize>
     alive: Range<usize>,
 }
 
-impl<T, const N: usize> IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> IntoIter<T, N> {
     /// Creates a new iterator over the given `array`.
     ///
     /// *Note*: this method might never get stabilized and/or removed in the
@@ -99,10 +92,7 @@ fn as_mut_slice(&mut self) -> &mut [T] {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Iterator for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> Iterator for IntoIter<T, N> {
     type Item = T;
     fn next(&mut self) -> Option<Self::Item> {
         if self.alive.start == self.alive.end {
@@ -146,10 +136,7 @@ fn last(mut self) -> Option<Self::Item> {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
     fn next_back(&mut self) -> Option<Self::Item> {
         if self.alive.start == self.alive.end {
             return None;
@@ -182,10 +169,7 @@ fn next_back(&mut self) -> Option<Self::Item> {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> Drop for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> Drop for IntoIter<T, N> {
     fn drop(&mut self) {
         // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
         // of elements that have not been moved out yet and that remain
@@ -195,10 +179,7 @@ fn drop(&mut self) {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
     fn len(&self) -> usize {
         // Will never underflow due to the invariant `alive.start <=
         // alive.end`.
@@ -210,20 +191,17 @@ fn is_empty(&self) -> bool {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T, const N: usize> FusedIterator for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
+impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
 
 // The iterator indeed reports the correct length. The number of "alive"
 // elements (that will still be yielded) is the length of the range `alive`.
 // This range is decremented in length in either `next` or `next_back`. It is
 // always decremented by 1 in those methods, but only if `Some(_)` is returned.
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
+unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: Clone, const N: usize> Clone for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
     fn clone(&self) -> Self {
         // SAFETY: each point of unsafety is documented inside the unsafe block
         unsafe {
@@ -249,10 +227,7 @@ fn clone(&self) -> Self {
 }
 
 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
-impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N>
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // Only print the elements that were not yielded yet: we cannot
         // access the yielded elements anymore.
index 549228ffffaa4d832ae1c92d750cf7665d6513a9..c0bf3833b9c3366a3ce5e82bb588f4902bd25ca7 100644 (file)
@@ -92,10 +92,7 @@ fn from(x: Infallible) -> TryFromSliceError {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, const N: usize> AsRef<[T]> for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> AsRef<[T]> for [T; N] {
     #[inline]
     fn as_ref(&self) -> &[T] {
         &self[..]
@@ -103,10 +100,7 @@ fn as_ref(&self) -> &[T] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, const N: usize> AsMut<[T]> for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> AsMut<[T]> for [T; N] {
     #[inline]
     fn as_mut(&mut self) -> &mut [T] {
         &mut self[..]
@@ -114,20 +108,14 @@ fn as_mut(&mut self) -> &mut [T] {
 }
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
-impl<T, const N: usize> Borrow<[T]> for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> Borrow<[T]> for [T; N] {
     fn borrow(&self) -> &[T] {
         self
     }
 }
 
 #[stable(feature = "array_borrow", since = "1.4.0")]
-impl<T, const N: usize> BorrowMut<[T]> for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
     fn borrow_mut(&mut self) -> &mut [T] {
         self
     }
@@ -137,7 +125,6 @@ fn borrow_mut(&mut self) -> &mut [T] {
 impl<T, const N: usize> TryFrom<&[T]> for [T; N]
 where
     T: Copy,
-    [T; N]: LengthAtMost32,
 {
     type Error = TryFromSliceError;
 
@@ -147,10 +134,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 }
 
 #[stable(feature = "try_from", since = "1.34.0")]
-impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
     type Error = TryFromSliceError;
 
     fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
@@ -165,10 +149,7 @@ fn borrow_mut(&mut self) -> &mut [T] {
 }
 
 #[stable(feature = "try_from", since = "1.34.0")]
-impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
     type Error = TryFromSliceError;
 
     fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
@@ -183,30 +164,21 @@ fn borrow_mut(&mut self) -> &mut [T] {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Hash, const N: usize> Hash for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: Hash, const N: usize> Hash for [T; N] {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         Hash::hash(&self[..], state)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&&self[..], f)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
     type Item = &'a T;
     type IntoIter = Iter<'a, T>;
 
@@ -216,10 +188,7 @@ fn into_iter(self) -> Iter<'a, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
     type Item = &'a mut T;
     type IntoIter = IterMut<'a, T>;
 
@@ -232,8 +201,6 @@ fn into_iter(self) -> IterMut<'a, T> {
 impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
 where
     A: PartialEq<B>,
-    [A; N]: LengthAtMost32,
-    [B; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &[B; N]) -> bool {
@@ -249,7 +216,6 @@ fn into_iter(self) -> IterMut<'a, T> {
 impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
 where
     A: PartialEq<B>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &[B]) -> bool {
@@ -265,7 +231,6 @@ fn ne(&self, other: &[B]) -> bool {
 impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
 where
     B: PartialEq<A>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &[A; N]) -> bool {
@@ -281,7 +246,6 @@ fn ne(&self, other: &[B]) -> bool {
 impl<'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
 where
     A: PartialEq<B>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &&'b [B]) -> bool {
@@ -297,7 +261,6 @@ fn ne(&self, other: &&'b [B]) -> bool {
 impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
 where
     B: PartialEq<A>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &[A; N]) -> bool {
@@ -313,7 +276,6 @@ fn ne(&self, other: &&'b [B]) -> bool {
 impl<'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
 where
     A: PartialEq<B>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &&'b mut [B]) -> bool {
@@ -329,7 +291,6 @@ fn ne(&self, other: &&'b mut [B]) -> bool {
 impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
 where
     B: PartialEq<A>,
-    [A; N]: LengthAtMost32,
 {
     #[inline]
     fn eq(&self, other: &[A; N]) -> bool {
@@ -346,13 +307,10 @@ fn ne(&self, other: &&'b mut [B]) -> bool {
 // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Eq, const N: usize> Eq for [T; N] where [T; N]: LengthAtMost32 {}
+impl<T: Eq, const N: usize> Eq for [T; N] {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialOrd, const N: usize> PartialOrd for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
     #[inline]
     fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
         PartialOrd::partial_cmp(&&self[..], &&other[..])
@@ -377,41 +335,13 @@ fn ne(&self, other: &&'b mut [B]) -> bool {
 
 /// Implements comparison of arrays lexicographically.
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord, const N: usize> Ord for [T; N]
-where
-    [T; N]: LengthAtMost32,
-{
+impl<T: Ord, const N: usize> Ord for [T; N] {
     #[inline]
     fn cmp(&self, other: &[T; N]) -> Ordering {
         Ord::cmp(&&self[..], &&other[..])
     }
 }
 
-/// Implemented for lengths where trait impls are allowed on arrays in core/std
-#[rustc_on_unimplemented(message = "arrays only have std trait implementations for lengths 0..=32")]
-#[unstable(
-    feature = "const_generic_impls_guard",
-    issue = "none",
-    reason = "will never be stable, just a temporary step until const generics are stable"
-)]
-pub trait LengthAtMost32 {}
-
-macro_rules! array_impls {
-    ($($N:literal)+) => {
-        $(
-            #[unstable(feature = "const_generic_impls_guard", issue = "none")]
-            impl<T> LengthAtMost32 for [T; $N] {}
-        )+
-    }
-}
-
-array_impls! {
-     0  1  2  3  4  5  6  7  8  9
-    10 11 12 13 14 15 16 17 18 19
-    20 21 22 23 24 25 26 27 28 29
-    30 31 32
-}
-
 // The Default impls cannot be generated using the array_impls! macro because
 // they require array literals.
 
index 94f7ff5c1f7fe7864f6bf1fd0399ae7d8b568eef..03b798d57db9bcf37ba50b1ba515730782f2e7bd 100644 (file)
@@ -677,7 +677,7 @@ fn as_ref(&self) -> &str {
 ///
 ///
 /// However there is one case where `!` syntax can be used
-/// before `!` is stabilized as a full-fleged type: in the position of a function’s return type.
+/// before `!` is stabilized as a full-fledged type: in the position of a function’s return type.
 /// Specifically, it is possible implementations for two different function pointer types:
 ///
 /// ```
index f6460470bfe18e5e3aec17b90cbf39b1351835ec..37202b2774dc63d95086c9d7ef6d7fa3f6231742 100644 (file)
@@ -33,9 +33,13 @@ pub enum Alignment {
     Unknown,
 }
 
+/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
 #[derive(Copy, Clone)]
 pub enum Count {
+    /// Specified with a literal number, stores the value
     Is(usize),
+    /// Specified using `$` and `*` syntaxes, stores the index into `args`
     Param(usize),
+    /// Not specified
     Implied,
 }
index f2bbf646f3272b87d1c5beb7e8b22721f985abce..a9882d54de4f18b3e47d86ce132d760c852e2ab6 100644 (file)
@@ -43,7 +43,7 @@ struct SipHasher24 {
 ///
 /// SipHash is a general-purpose hashing function: it runs at a good
 /// speed (competitive with Spooky and City) and permits strong _keyed_
-/// hashing. This lets you key your hashtables from a strong RNG, such as
+/// hashing. This lets you key your hash tables from a strong RNG, such as
 /// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
 ///
 /// Although the SipHash algorithm is considered to be generally strong,
index 049f51fb1035a3d2a3ea4496135eff651a85fa51..71780361d298e87c54d8ed20e86cded29a1ca5ee 100644 (file)
@@ -15,7 +15,7 @@
 //!
 //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
 //! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
-//! without T-lang consulation, because it bakes a feature into the language that cannot be
+//! without T-lang consultation, because it bakes a feature into the language that cannot be
 //! replicated in user code without compiler support.
 //!
 //! # Volatiles
     /// [`std::mem::align_of`](../../std/mem/fn.align_of.html).
     #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
-    /// The prefered alignment of a type.
+    /// The preferred alignment of a type.
     ///
     /// This intrinsic does not have a stable counterpart.
     #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")]
     ///     assert!(mid <= len);
     ///     unsafe {
     ///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
-    ///         // first: transmute is not typesafe; all it checks is that T and
+    ///         // first: transmute is not type safe; all it checks is that T and
     ///         // U are of the same size. Second, right here, you have two
     ///         // mutable references pointing to the same memory.
     ///         (&mut slice[0..mid], &mut slice2[mid..len])
     ///     }
     /// }
     ///
-    /// // This gets rid of the typesafety problems; `&mut *` will *only* give
+    /// // This gets rid of the type safety problems; `&mut *` will *only* give
     /// // you an `&mut T` from an `&mut T` or `*mut T`.
     /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
     ///                          -> (&mut [T], &mut [T]) {
     #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
-    /// Internal hook used by Miri to implement unwinding.
-    /// ICEs when encountered during non-Miri codegen.
-    ///
-    /// The `payload` ptr here will be exactly the one `do_catch` gets passed by `try`.
-    ///
-    /// Perma-unstable: do not use.
-    pub fn miri_start_panic(payload: *mut u8) -> !;
-
     /// Internal placeholder for injecting code coverage counters when the "instrument-coverage"
     /// option is enabled. The placeholder is replaced with `llvm.instrprof.increment` during code
     /// generation.
index 9f55f378a5cc1dde508a23c2c3ed8f8ec9b6c9f7..9f34aee1947cd8e8dcd1fdd2899dffc43641d821 100644 (file)
@@ -32,7 +32,7 @@ pub unsafe trait Step: Clone + PartialOrd + Sized {
     /// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
     ///   * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
     ///   * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
-    ///     this is the case wheen it would require more than `usize::MAX` steps to get to `b`
+    ///     this is the case when it would require more than `usize::MAX` steps to get to `b`
     /// * `steps_between(&a, &b) == None` if `a > b`
     fn steps_between(start: &Self, end: &Self) -> Option<usize>;
 
index b8faeb488e72d3cf776f324498c170d1cc6f319d..3ea3eeed6b0434f3f4f5fc7b3b5569051a255249 100644 (file)
@@ -1069,7 +1069,7 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     /// let vec = iter.collect::<Vec<_>>();
     ///
     /// // We have more elements which could fit in u32 (4, 5), but `map_while` returned `None` for `-3`
-    /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` entcountered.
+    /// // (as the `predicate` returned `None`) and `collect` stops at the first `None` encountered.
     /// assert_eq!(vec, vec![0, 1, 2]);
     /// ```
     ///
index 4ac366ab16408eb3de7c8d60359a9cd5fb8dbd05..3b9057b7e8377911feec5d30b98e163a787d0fab 100644 (file)
@@ -1047,7 +1047,7 @@ macro_rules! stringify {
         };
     }
 
-    /// Includes a utf8-encoded file as a string.
+    /// Includes a UTF-8 encoded file as a string.
     ///
     /// The file is located relative to the current file (similarly to how
     /// modules are found). The provided path is interpreted in a platform-specific
index d62de7617a00df5de0e4161462237247644e6a36..6ff7baab70f61eee903dde10278c4e06dcdeabe1 100644 (file)
@@ -348,11 +348,11 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
 ///
 /// - If `T` is `Sized`, this function is always safe to call.
 /// - If the unsized tail of `T` is:
-///     - a [slice], then the length of the slice tail must be an intialized
+///     - a [slice], then the length of the slice tail must be an initialized
 ///       integer, and the size of the *entire value*
 ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
 ///     - a [trait object], then the vtable part of the pointer must point
-///       to a valid vtable acquired by an unsizing coersion, and the size
+///       to a valid vtable acquired by an unsizing coercion, and the size
 ///       of the *entire value* (dynamic tail length + statically sized prefix)
 ///       must fit in `isize`.
 ///     - an (unstable) [extern type], then this function is always safe to
@@ -483,11 +483,11 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
 ///
 /// - If `T` is `Sized`, this function is always safe to call.
 /// - If the unsized tail of `T` is:
-///     - a [slice], then the length of the slice tail must be an intialized
+///     - a [slice], then the length of the slice tail must be an initialized
 ///       integer, and the size of the *entire value*
 ///       (dynamic tail length + statically sized prefix) must fit in `isize`.
 ///     - a [trait object], then the vtable part of the pointer must point
-///       to a valid vtable acquired by an unsizing coersion, and the size
+///       to a valid vtable acquired by an unsizing coercion, and the size
 ///       of the *entire value* (dynamic tail length + statically sized prefix)
 ///       must fit in `isize`.
 ///     - an (unstable) [extern type], then this function is always safe to
index 061d1ea6b1c46974ffe7f7e11d3c3a6a878c8842..9fb7296ce31cc32d873d7eb0e91ff21fe9929318 100644 (file)
@@ -242,7 +242,7 @@ pub mod consts {
     /// The full circle constant (Ï„)
     ///
     /// Equal to 2Ï€.
-    #[unstable(feature = "tau_constant", issue = "66770")]
+    #[stable(feature = "tau_constant", since = "1.47.0")]
     pub const TAU: f32 = 6.28318530717958647692528676655900577_f32;
 
     /// Ï€/2
index b0df4d64f6ee1880583c42f5bc83c8a5a6dbd9d2..a5b1eb3f1fd67c61adcc65d041319bc7b88f6f29 100644 (file)
@@ -242,7 +242,7 @@ pub mod consts {
     /// The full circle constant (Ï„)
     ///
     /// Equal to 2Ï€.
-    #[unstable(feature = "tau_constant", issue = "66770")]
+    #[stable(feature = "tau_constant", since = "1.47.0")]
     pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
 
     /// Ï€/2
@@ -687,7 +687,7 @@ pub fn to_bits(self) -> u64 {
     /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
     ///
     /// Rather than trying to preserve signaling-ness cross-platform, this
-    /// implementation favours preserving the exact bits. This means that
+    /// implementation favors preserving the exact bits. This means that
     /// any payloads encoded in NaNs will be preserved even if the result of
     /// this method is sent over the network from an x86 machine to a MIPS one.
     ///
@@ -696,7 +696,7 @@ pub fn to_bits(self) -> u64 {
     ///
     /// If the input isn't NaN, then there is no portability concern.
     ///
-    /// If you don't care about signalingness (very likely), then there is no
+    /// If you don't care about signaling-ness (very likely), then there is no
     /// portability concern.
     ///
     /// Note that this function is distinct from `as` casting, which attempts to
index 7392a678b0549277cb1efa95fbde7f52fd80455a..8e9a90352280295f8346ae018e6783727f7575d7 100644 (file)
@@ -1095,6 +1095,9 @@ pub const fn checked_abs(self) -> Option<Self> {
                           without modifying the original"]
             #[inline]
             pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
+                if exp == 0 {
+                    return Some(1);
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -1105,15 +1108,11 @@ pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
                     exp /= 2;
                     base = try_opt!(base.checked_mul(base));
                 }
-
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    acc = try_opt!(acc.checked_mul(base));
-                }
-
-                Some(acc)
+                Some(try_opt!(acc.checked_mul(base)))
             }
         }
 
@@ -1622,6 +1621,9 @@ pub const fn wrapping_abs(self) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_pow(self, mut exp: u32) -> Self {
+                if exp == 0 {
+                    return 1;
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -1633,14 +1635,11 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
                     base = base.wrapping_mul(base);
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    acc = acc.wrapping_mul(base);
-                }
-
-                acc
+                acc.wrapping_mul(base)
             }
         }
 
@@ -1989,6 +1988,9 @@ pub const fn overflowing_abs(self) -> (Self, bool) {
                           without modifying the original"]
             #[inline]
             pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+                if exp == 0 {
+                    return (1,false);
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
                 let mut overflown = false;
@@ -2007,16 +2009,13 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                     overflown |= r.1;
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    r = acc.overflowing_mul(base);
-                    acc = r.0;
-                    overflown |= r.1;
-                }
-
-                (acc, overflown)
+                r = acc.overflowing_mul(base);
+                r.1 |= overflown;
+                r
             }
         }
 
@@ -2040,6 +2039,9 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
             #[inline]
             #[rustc_inherit_overflow_checks]
             pub const fn pow(self, mut exp: u32) -> Self {
+                if exp == 0 {
+                    return 1;
+                }
                 let mut base = self;
                 let mut acc = 1;
 
@@ -2051,14 +2053,11 @@ pub const fn pow(self, mut exp: u32) -> Self {
                     base = base * base;
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    acc = acc * base;
-                }
-
-                acc
+                acc * base
             }
         }
 
@@ -3295,6 +3294,9 @@ pub const fn checked_shr(self, rhs: u32) -> Option<Self> {
                           without modifying the original"]
             #[inline]
             pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
+                if exp == 0 {
+                    return Some(1);
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -3306,14 +3308,12 @@ pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
                     base = try_opt!(base.checked_mul(base));
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    acc = try_opt!(acc.checked_mul(base));
-                }
 
-                Some(acc)
+                Some(try_opt!(acc.checked_mul(base)))
             }
         }
 
@@ -3704,6 +3704,9 @@ pub const fn wrapping_shr(self, rhs: u32) -> Self {
                           without modifying the original"]
             #[inline]
             pub const fn wrapping_pow(self, mut exp: u32) -> Self {
+                if exp == 0 {
+                    return 1;
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
 
@@ -3715,14 +3718,11 @@ pub const fn wrapping_pow(self, mut exp: u32) -> Self {
                     base = base.wrapping_mul(base);
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    acc = acc.wrapping_mul(base);
-                }
-
-                acc
+                acc.wrapping_mul(base)
             }
         }
 
@@ -4029,6 +4029,9 @@ pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
                           without modifying the original"]
             #[inline]
             pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
+                if exp == 0{
+                    return (1,false);
+                }
                 let mut base = self;
                 let mut acc: Self = 1;
                 let mut overflown = false;
@@ -4047,16 +4050,14 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
                     overflown |= r.1;
                 }
 
+                // since exp!=0, finally the exp must be 1.
                 // Deal with the final bit of the exponent separately, since
                 // squaring the base afterwards is not necessary and may cause a
                 // needless overflow.
-                if exp == 1 {
-                    r = acc.overflowing_mul(base);
-                    acc = r.0;
-                    overflown |= r.1;
-                }
+                r = acc.overflowing_mul(base);
+                r.1 |= overflown;
 
-                (acc, overflown)
+                r
             }
         }
 
@@ -4077,6 +4078,9 @@ pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
         #[inline]
         #[rustc_inherit_overflow_checks]
         pub const fn pow(self, mut exp: u32) -> Self {
+            if exp == 0 {
+                return 1;
+            }
             let mut base = self;
             let mut acc = 1;
 
@@ -4088,14 +4092,11 @@ pub const fn pow(self, mut exp: u32) -> Self {
                 base = base * base;
             }
 
+            // since exp!=0, finally the exp must be 1.
             // Deal with the final bit of the exponent separately, since
             // squaring the base afterwards is not necessary and may cause a
             // needless overflow.
-            if exp == 1 {
-                acc = acc * base;
-            }
-
-            acc
+            acc * base
         }
     }
 
index 22a738d0bc1c0515c71e484aa7878d64a070052c..4f08aa451875f78f5dcc72d566e7593ea7fceeed 100644 (file)
@@ -59,7 +59,7 @@
 #[rustc_on_unimplemented(
     on(
         Args = "()",
-        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
     message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
     label = "expected an `Fn<{Args}>` closure, found `{Self}`"
@@ -141,7 +141,7 @@ pub trait Fn<Args>: FnMut<Args> {
 #[rustc_on_unimplemented(
     on(
         Args = "()",
-        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
     message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
     label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
@@ -215,7 +215,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
 #[rustc_on_unimplemented(
     on(
         Args = "()",
-        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
+        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
     ),
     message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
     label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
index d86f39c4550c843fc3aa8f5212ccc5c633710e46..179038d1977c86ada516b1fce43454eb335c0fb5 100644 (file)
@@ -39,7 +39,7 @@
 /// [`Iterator`]: ../iter/trait.IntoIterator.html
 /// [slicing index]: ../slice/trait.SliceIndex.html
 #[doc(alias = "..")]
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFull;
 
@@ -71,7 +71,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// assert_eq!(arr[1..=3], [  1,2,3  ]);
 /// ```
 #[doc(alias = "..")]
-#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
+#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
     /// The lower bound of the range (inclusive).
index da299f026f8f16c87f0d7dd4f64fe3e62f37491b..9bcacd8ddcf77ee54bb950f8a9dcff1d280fbf6d 100644 (file)
 //!
 //! Crucially, we have to be able to rely on [`drop`] being called. If an element
 //! could be deallocated or otherwise invalidated without calling [`drop`], the pointers into it
-//! from its neighbouring elements would become invalid, which would break the data structure.
+//! from its neighboring elements would become invalid, which would break the data structure.
 //!
 //! Therefore, pinning also comes with a [`drop`]-related guarantee.
 //!
index 896ad740e1e692424a695f23fc0ca04576d326a8..a2acc239bd38f942da26c334b1254e4a6a24db00 100644 (file)
@@ -331,13 +331,13 @@ pub const fn guaranteed_eq(self, other: *const T) -> bool
         intrinsics::ptr_guaranteed_eq(self, other)
     }
 
-    /// Returns whether two pointers are guaranteed to be inequal.
+    /// Returns whether two pointers are guaranteed to be unequal.
     ///
     /// At runtime this function behaves like `self != other`.
     /// However, in some contexts (e.g., compile-time evaluation),
     /// it is not always possible to determine the inequality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be inequal.
-    /// But when it returns `true`, the pointers are guaranteed to be inequal.
+    /// spuriously return `false` for pointers that later actually turn out to be unequal.
+    /// But when it returns `true`, the pointers are guaranteed to be unequal.
     ///
     /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
     /// comparisons for which both functions return `false`.
index 96856e7512cabdcf5cad84e732ad9de4f30c543c..17fa90ecc08b5c81acc3e672bf9f3a6db429178d 100644 (file)
@@ -47,17 +47,22 @@ pub const fn cast<U>(self) -> *mut U {
     /// operation because the returned value could be pointing to invalid
     /// memory.
     ///
-    /// When calling this method, you have to ensure that if the pointer is
-    /// non-NULL, then it is properly aligned, dereferenceable (for the whole
-    /// size of `T`) and points to an initialized instance of `T`. This applies
-    /// even if the result of this method is unused!
+    /// When calling this method, you have to ensure that *either* the pointer is NULL *or*
+    /// all of the following is true:
+    /// - it is properly aligned
+    /// - it must point to an initialized instance of T; in particular, the pointer must be
+    ///   "dereferencable" in the sense defined [here].
+    ///
+    /// This applies even if the result of this method is unused!
     /// (The part about being initialized is not yet fully decided, but until
     /// it is, the only safe approach is to ensure that they are indeed initialized.)
     ///
     /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does
-    /// not necessarily reflect the actual lifetime of the data. It is up to the
-    /// caller to ensure that for the duration of this lifetime, the memory this
-    /// pointer points to does not get written to outside of `UnsafeCell<U>`.
+    /// not necessarily reflect the actual lifetime of the data. *You* must enforce
+    /// Rust's aliasing rules. In particular, for the duration of this lifetime,
+    /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`).
+    ///
+    /// [here]: crate::ptr#safety
     ///
     /// # Examples
     ///
@@ -312,13 +317,13 @@ pub const fn guaranteed_eq(self, other: *mut T) -> bool
         intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _)
     }
 
-    /// Returns whether two pointers are guaranteed to be inequal.
+    /// Returns whether two pointers are guaranteed to be unequal.
     ///
     /// At runtime this function behaves like `self != other`.
     /// However, in some contexts (e.g., compile-time evaluation),
     /// it is not always possible to determine the inequality of two pointers, so this function may
-    /// spuriously return `false` for pointers that later actually turn out to be inequal.
-    /// But when it returns `true`, the pointers are guaranteed to be inequal.
+    /// spuriously return `false` for pointers that later actually turn out to be unequal.
+    /// But when it returns `true`, the pointers are guaranteed to be unequal.
     ///
     /// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
     /// comparisons for which both functions return `false`.
index b362a49d604e7ffd2a3ccdecee89c4f33c17f440..9f843a570990d615b795f7233734686b42675ed2 100644 (file)
@@ -172,7 +172,7 @@ impl<T> NonNull<[T]> {
     /// assert_eq!(unsafe { slice.as_ref()[2] }, 7);
     /// ```
     ///
-    /// (Note that this example artifically demonstrates a use of this method,
+    /// (Note that this example artificially demonstrates a use of this method,
     /// but `let slice = NonNull::from(&x[..]);` would be a better way to write code like this.)
     #[unstable(feature = "nonnull_slice_from_raw_parts", issue = "71941")]
     #[rustc_const_unstable(feature = "const_nonnull_slice_from_raw_parts", issue = "71941")]
index 20b2c3d3c965a8eb2c4cbc7d5de1e2891492cd1b..9ed5a1f9622154603d84a00bf3cb11c1b3c1ff52 100644 (file)
@@ -1672,7 +1672,7 @@ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize
     /// Sorts the slice, but may not preserve the order of equal elements.
     ///
     /// This sort is unstable (i.e., may reorder equal elements), in-place
-    /// (i.e., does not allocate), and `O(n * log(n))` worst-case.
+    /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case.
     ///
     /// # Current implementation
     ///
@@ -1708,7 +1708,7 @@ pub fn sort_unstable(&mut self)
     /// elements.
     ///
     /// This sort is unstable (i.e., may reorder equal elements), in-place
-    /// (i.e., does not allocate), and `O(n * log(n))` worst-case.
+    /// (i.e., does not allocate), and *O*(*n* \* log(*n*)) worst-case.
     ///
     /// The comparator function must define a total ordering for the elements in the slice. If
     /// the ordering is not total, the order of the elements is unspecified. An order is a
@@ -1763,8 +1763,8 @@ pub fn sort_unstable_by<F>(&mut self, mut compare: F)
     /// elements.
     ///
     /// This sort is unstable (i.e., may reorder equal elements), in-place
-    /// (i.e., does not allocate), and `O(m * n * log(n))` worst-case, where the key function is
-    /// `O(m)`.
+    /// (i.e., does not allocate), and *O*(m \* *n* \* log(*n*)) worst-case, where the key function is
+    /// *O*(*m*).
     ///
     /// # Current implementation
     ///
@@ -1803,7 +1803,7 @@ pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
     /// This reordering has the additional property that any value at position `i < index` will be
     /// less than or equal to any value at a position `j > index`. Additionally, this reordering is
     /// unstable (i.e. any number of equal elements may end up at position `index`), in-place
-    /// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth
+    /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth
     /// element" in other libraries. It returns a triplet of the following values: all elements less
     /// than the one at the given index, the value at the given index, and all elements greater than
     /// the one at the given index.
@@ -1852,7 +1852,7 @@ pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T
     /// This reordering has the additional property that any value at position `i < index` will be
     /// less than or equal to any value at a position `j > index` using the comparator function.
     /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
-    /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
+    /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
     /// is also known as "kth element" in other libraries. It returns a triplet of the following
     /// values: all elements less than the one at the given index, the value at the given index,
     /// and all elements greater than the one at the given index, using the provided comparator
@@ -1906,7 +1906,7 @@ pub fn partition_at_index_by<F>(
     /// This reordering has the additional property that any value at position `i < index` will be
     /// less than or equal to any value at a position `j > index` using the key extraction function.
     /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at
-    /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function
+    /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function
     /// is also known as "kth element" in other libraries. It returns a triplet of the following
     /// values: all elements less than the one at the given index, the value at the given index, and
     /// all elements greater than the one at the given index, using the provided key extraction
@@ -2974,8 +2974,15 @@ fn index_mut(&mut self, index: I) -> &mut I::Output {
 #[inline(never)]
 #[cold]
 #[track_caller]
-fn slice_index_len_fail(index: usize, len: usize) -> ! {
-    panic!("index {} out of range for slice of length {}", index, len);
+fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
+    panic!("range start index {} out of range for slice of length {}", index, len);
+}
+
+#[inline(never)]
+#[cold]
+#[track_caller]
+fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
+    panic!("range end index {} out of range for slice of length {}", index, len);
 }
 
 #[inline(never)]
@@ -3160,7 +3167,7 @@ fn index(self, slice: &[T]) -> &[T] {
         if self.start > self.end {
             slice_index_order_fail(self.start, self.end);
         } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
+            slice_end_index_len_fail(self.end, slice.len());
         }
         unsafe { &*self.get_unchecked(slice) }
     }
@@ -3170,7 +3177,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
         if self.start > self.end {
             slice_index_order_fail(self.start, self.end);
         } else if self.end > slice.len() {
-            slice_index_len_fail(self.end, slice.len());
+            slice_end_index_len_fail(self.end, slice.len());
         }
         unsafe { &mut *self.get_unchecked_mut(slice) }
     }
@@ -3241,12 +3248,18 @@ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        (self.start..slice.len()).index(slice)
+        if self.start > slice.len() {
+            slice_start_index_len_fail(self.start, slice.len());
+        }
+        unsafe { &*self.get_unchecked(slice) }
     }
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        (self.start..slice.len()).index_mut(slice)
+        if self.start > slice.len() {
+            slice_start_index_len_fail(self.start, slice.len());
+        }
+        unsafe { &mut *self.get_unchecked_mut(slice) }
     }
 }
 
index 8b2ac294764ff5aa49fc17796b45a1a8f651910d..972a33d6489e986919558cfcd15f1bfaac392f02 100644 (file)
@@ -121,7 +121,7 @@ fn shift_tail<T, F>(v: &mut [T], is_less: &mut F)
 
 /// Partially sorts a slice by shifting several out-of-order elements around.
 ///
-/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case.
+/// Returns `true` if the slice is sorted at the end. This function is *O*(*n*) worst-case.
 #[cold]
 fn partial_insertion_sort<T, F>(v: &mut [T], is_less: &mut F) -> bool
 where
@@ -168,7 +168,7 @@ fn partial_insertion_sort<T, F>(v: &mut [T], is_less: &mut F) -> bool
     false
 }
 
-/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case.
+/// Sorts a slice using insertion sort, which is *O*(*n*^2) worst-case.
 fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
 where
     F: FnMut(&T, &T) -> bool,
@@ -178,7 +178,7 @@ fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
     }
 }
 
-/// Sorts `v` using heapsort, which guarantees `O(n * log(n))` worst-case.
+/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case.
 #[cold]
 pub fn heapsort<T, F>(v: &mut [T], is_less: &mut F)
 where
@@ -751,7 +751,7 @@ fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T
     }
 }
 
-/// Sorts `v` using pattern-defeating quicksort, which is `O(n * log(n))` worst-case.
+/// Sorts `v` using pattern-defeating quicksort, which is *O*(*n* \* log(*n*)) worst-case.
 pub fn quicksort<T, F>(v: &mut [T], mut is_less: F)
 where
     F: FnMut(&T, &T) -> bool,
index 8396a0dd62db91ad3fdb3c8f0ffcc30264d8d67a..58a585669122ca3b7859cf19b9bef7525354d705 100644 (file)
@@ -255,12 +255,43 @@ fn test_from_str_radix() {
             #[test]
             fn test_pow() {
                 let mut r = 2 as $T;
-
                 assert_eq!(r.pow(2), 4 as $T);
                 assert_eq!(r.pow(0), 1 as $T);
+                assert_eq!(r.wrapping_pow(2), 4 as $T);
+                assert_eq!(r.wrapping_pow(0), 1 as $T);
+                assert_eq!(r.checked_pow(2), Some(4 as $T));
+                assert_eq!(r.checked_pow(0), Some(1 as $T));
+                assert_eq!(r.overflowing_pow(2), (4 as $T, false));
+                assert_eq!(r.overflowing_pow(0), (1 as $T, false));
+                assert_eq!(r.saturating_pow(2), 4 as $T);
+                assert_eq!(r.saturating_pow(0), 1 as $T);
+
+                r = MAX;
+                // use `^` to represent .pow() with no overflow.
+                // if itest::MAX == 2^j-1, then itest is a `j` bit int,
+                // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
+                // thussaturating_pow the overflowing result is exactly 1.
+                assert_eq!(r.wrapping_pow(2), 1 as $T);
+                assert_eq!(r.checked_pow(2), None);
+                assert_eq!(r.overflowing_pow(2), (1 as $T, true));
+                assert_eq!(r.saturating_pow(2), MAX);
+                //test for negative exponent.
                 r = -2 as $T;
                 assert_eq!(r.pow(2), 4 as $T);
                 assert_eq!(r.pow(3), -8 as $T);
+                assert_eq!(r.pow(0), 1 as $T);
+                assert_eq!(r.wrapping_pow(2), 4 as $T);
+                assert_eq!(r.wrapping_pow(3), -8 as $T);
+                assert_eq!(r.wrapping_pow(0), 1 as $T);
+                assert_eq!(r.checked_pow(2), Some(4 as $T));
+                assert_eq!(r.checked_pow(3), Some(-8 as $T));
+                assert_eq!(r.checked_pow(0), Some(1 as $T));
+                assert_eq!(r.overflowing_pow(2), (4 as $T, false));
+                assert_eq!(r.overflowing_pow(3), (-8 as $T, false));
+                assert_eq!(r.overflowing_pow(0), (1 as $T, false));
+                assert_eq!(r.saturating_pow(2), 4 as $T);
+                assert_eq!(r.saturating_pow(3), -8 as $T);
+                assert_eq!(r.saturating_pow(0), 1 as $T);
             }
         }
     };
index 8f1ca8e6fac2c5a60be8072c349fa87cc5d233b5..b84a8a7d9f88ba3aee84214cc61ac21f764e9a56 100644 (file)
@@ -184,6 +184,31 @@ pub fn test_parse_bytes() {
                 assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
                 assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
             }
+
+            #[test]
+            fn test_pow() {
+                let mut r = 2 as $T;
+                assert_eq!(r.pow(2), 4 as $T);
+                assert_eq!(r.pow(0), 1 as $T);
+                assert_eq!(r.wrapping_pow(2), 4 as $T);
+                assert_eq!(r.wrapping_pow(0), 1 as $T);
+                assert_eq!(r.checked_pow(2), Some(4 as $T));
+                assert_eq!(r.checked_pow(0), Some(1 as $T));
+                assert_eq!(r.overflowing_pow(2), (4 as $T, false));
+                assert_eq!(r.overflowing_pow(0), (1 as $T, false));
+                assert_eq!(r.saturating_pow(2), 4 as $T);
+                assert_eq!(r.saturating_pow(0), 1 as $T);
+
+                r = MAX;
+                // use `^` to represent .pow() with no overflow.
+                // if itest::MAX == 2^j-1, then itest is a `j` bit int,
+                // so that `itest::MAX*itest::MAX == 2^(2*j)-2^(j+1)+1`,
+                // thussaturating_pow the overflowing result is exactly 1.
+                assert_eq!(r.wrapping_pow(2), 1 as $T);
+                assert_eq!(r.checked_pow(2), None);
+                assert_eq!(r.overflowing_pow(2), (1 as $T, true));
+                assert_eq!(r.saturating_pow(2), MAX);
+            }
         }
     };
 }
index fba73be92be09b527971a4e410dbf302106ce498..8e240832c13b839cdfd7df9d12eac7da5249f966 100644 (file)
@@ -1088,7 +1088,7 @@ fn simple() {
 
             good: data[6..] == [];
             bad: data[7..];
-            message: "but ends at"; // perhaps not ideal
+            message: "out of range";
         }
 
         in mod rangeto_len {
index 9d92b2b2f32078ae535ba9a142240806031d739c..d941b73b5fac10d4d870cf04d9329a7bc6f54d52 100644 (file)
@@ -6,11 +6,16 @@
 // Must be pointer-sized.
 type Payload = Box<Box<dyn Any + Send>>;
 
+extern "Rust" {
+    /// Miri-provided extern function to begin unwinding.
+    fn miri_start_panic(payload: *mut u8) -> !;
+}
+
 pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 {
     // The payload we pass to `miri_start_panic` will be exactly the argument we get
     // in `cleanup` below. So we just box it up once, to get something pointer-sized.
     let payload_box: Payload = Box::new(payload);
-    core::intrinsics::miri_start_panic(Box::into_raw(payload_box) as *mut u8)
+    miri_start_panic(Box::into_raw(payload_box) as *mut u8)
 }
 
 pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> {
index 0d36bd0b39d76b69a3f7e835e5e5c579828425f4..899f923b957fe3af07644fe48f79a65d5adc53dc 100644 (file)
@@ -1,6 +1,5 @@
 [package]
 authors = ["The Rust Project Developers"]
-build = "build.rs"
 name = "profiler_builtins"
 version = "0.0.0"
 edition = "2018"
index bb7d59e113c08a29fc9c61e26383c668adb577e7..d2cb873058c282f14f04317fe77e4cc6e46554b1 100644 (file)
@@ -9,6 +9,8 @@ fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
     let cfg = &mut cc::Build::new();
 
+    // FIXME: `rerun-if-changed` directives are not currently emitted and the build script
+    // will not rerun on changes in these source files or headers included into them.
     let mut profile_sources = vec![
         "GCDAProfiling.c",
         "InstrProfiling.c",
diff --git a/src/librustc_ast/build.rs b/src/librustc_ast/build.rs
deleted file mode 100644 (file)
index 9b861f9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL");
-    println!("cargo:rerun-if-env-changed=CFG_DISABLE_UNSTABLE_FEATURES");
-}
index 201972fcf264bd505b6e5f61b187f1e4e0be9541..abd5df537db99f14354b4ce904ab43d03cfc3e14 100644 (file)
@@ -9,7 +9,8 @@
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned};
+use rustc_span::hygiene::ForLoopLoc;
+use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
index b5d3beb4f8a9b70331639b0d3e9ec8aa7ce2645f..1c70eef3bf5e32259b5387ab81c510498818792a 100644 (file)
@@ -936,20 +936,7 @@ fn add_in_band_defs<T>(
                 })
             });
 
-        let mut lowered_params: Vec<_> =
-            lowered_generics.params.into_iter().chain(in_band_defs).collect();
-
-        // FIXME(const_generics): the compiler doesn't always cope with
-        // unsorted generic parameters at the moment, so we make sure
-        // that they're ordered correctly here for now. (When we chain
-        // the `in_band_defs`, we might make the order unsorted.)
-        lowered_params.sort_by_key(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
-            hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
-            hir::GenericParamKind::Const { .. } => ParamKindOrd::Const,
-        });
-
-        lowered_generics.params = lowered_params.into();
+        lowered_generics.params.extend(in_band_defs);
 
         let lowered_generics = lowered_generics.into_generics(self.arena);
         (lowered_generics, res)
index 975881d9a0ac0c898895c5318320f3dd6f9660a0..daf3e23d6a1234c2196fe76286000f792f60976c 100644 (file)
@@ -1118,13 +1118,26 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
     fn visit_generics(&mut self, generics: &'a Generics) {
         let mut prev_ty_default = None;
         for param in &generics.params {
-            if let GenericParamKind::Type { ref default, .. } = param.kind {
-                if default.is_some() {
+            match param.kind {
+                GenericParamKind::Lifetime => (),
+                GenericParamKind::Type { default: Some(_), .. } => {
                     prev_ty_default = Some(param.ident.span);
-                } else if let Some(span) = prev_ty_default {
-                    self.err_handler()
-                        .span_err(span, "type parameters with a default must be trailing");
-                    break;
+                }
+                GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
+                    if let Some(span) = prev_ty_default {
+                        let mut err = self.err_handler().struct_span_err(
+                            span,
+                            "type parameters with a default must be trailing",
+                        );
+                        if matches!(param.kind, GenericParamKind::Const { .. }) {
+                            err.note(
+                                "using type defaults and const parameters \
+                                 in the same parameter list is currently not permitted",
+                            );
+                        }
+                        err.emit();
+                        break;
+                    }
                 }
             }
         }
index 677796a8df0b37a89cc427c8754d7b8b190df517..496becb8f1b5948235438afe758fdc9db0282829 100644 (file)
@@ -3,7 +3,6 @@ authors = ["The Rust Project Developers"]
 name = "rustc_attr"
 version = "0.0.0"
 edition = "2018"
-build = "build.rs"
 
 [lib]
 name = "rustc_attr"
diff --git a/src/librustc_attr/build.rs b/src/librustc_attr/build.rs
deleted file mode 100644 (file)
index 863f2b7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_RELEASE");
-    println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL");
-}
index 0606fac2fe748f17aa13ee7e078ab363f146ecb6..1e088b52dcc35b5fffb03d09cde40843b6801e81 100644 (file)
@@ -124,13 +124,11 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
 ///
 /// - `#[stable]`
 /// - `#[unstable]`
-/// - `#[rustc_deprecated]`
 #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
-    pub rustc_depr: Option<RustcDeprecation>,
 }
 
 /// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
@@ -163,15 +161,6 @@ pub fn is_stable(&self) -> bool {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
-#[derive(HashStable_Generic)]
-pub struct RustcDeprecation {
-    pub since: Symbol,
-    pub reason: Symbol,
-    /// A text snippet used to completely replace any use of the deprecated item in an expression.
-    pub suggestion: Option<Symbol>,
-}
-
 /// Checks if `attrs` contains an attribute like `#![feature(feature_name)]`.
 /// This will not perform any "sanity checks" on the form of the attributes.
 pub fn contains_feature_attr(attrs: &[Attribute], feature_name: Symbol) -> bool {
@@ -205,7 +194,6 @@ fn find_stability_generic<'a, I>(
     use StabilityLevel::*;
 
     let mut stab: Option<Stability> = None;
-    let mut rustc_depr: Option<RustcDeprecation> = None;
     let mut const_stab: Option<ConstStability> = None;
     let mut promotable = false;
     let mut allow_const_fn_ptr = false;
@@ -213,7 +201,6 @@ fn find_stability_generic<'a, I>(
 
     'outer: for attr in attrs_iter {
         if ![
-            sym::rustc_deprecated,
             sym::rustc_const_unstable,
             sym::rustc_const_stable,
             sym::unstable,
@@ -258,76 +245,8 @@ fn find_stability_generic<'a, I>(
                 }
             };
 
-            macro_rules! get_meta {
-                ($($name:ident),+) => {
-                    $(
-                        let mut $name = None;
-                    )+
-                    for meta in metas {
-                        if let Some(mi) = meta.meta_item() {
-                            match mi.name_or_empty() {
-                                $(
-                                    sym::$name => if !get(mi, &mut $name) { continue 'outer },
-                                )+
-                                _ => {
-                                    let expected = &[ $( stringify!($name) ),+ ];
-                                    handle_errors(
-                                        sess,
-                                        mi.span,
-                                        AttrError::UnknownMetaItem(
-                                            pprust::path_to_string(&mi.path),
-                                            expected,
-                                        ),
-                                    );
-                                    continue 'outer
-                                }
-                            }
-                        } else {
-                            handle_errors(
-                                sess,
-                                meta.span(),
-                                AttrError::UnsupportedLiteral(
-                                    "unsupported literal",
-                                    false,
-                                ),
-                            );
-                            continue 'outer
-                        }
-                    }
-                }
-            }
-
             let meta_name = meta.name_or_empty();
             match meta_name {
-                sym::rustc_deprecated => {
-                    if rustc_depr.is_some() {
-                        struct_span_err!(
-                            diagnostic,
-                            item_sp,
-                            E0540,
-                            "multiple rustc_deprecated attributes"
-                        )
-                        .emit();
-                        continue 'outer;
-                    }
-
-                    get_meta!(since, reason, suggestion);
-
-                    match (since, reason) {
-                        (Some(since), Some(reason)) => {
-                            rustc_depr = Some(RustcDeprecation { since, reason, suggestion })
-                        }
-                        (None, _) => {
-                            handle_errors(sess, attr.span, AttrError::MissingSince);
-                            continue;
-                        }
-                        _ => {
-                            struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'")
-                                .emit();
-                            continue;
-                        }
-                    }
-                }
                 sym::rustc_const_unstable | sym::unstable => {
                     if meta_name == sym::unstable && stab.is_some() {
                         handle_errors(sess, attr.span, AttrError::MultipleStabilityLevels);
@@ -429,7 +348,7 @@ macro_rules! get_meta {
                         (Some(feature), reason, Some(_)) => {
                             let level = Unstable { reason, issue: issue_num, is_soft };
                             if sym::unstable == meta_name {
-                                stab = Some(Stability { level, feature, rustc_depr: None });
+                                stab = Some(Stability { level, feature });
                             } else {
                                 const_stab = Some(ConstStability {
                                     level,
@@ -501,7 +420,7 @@ macro_rules! get_meta {
                         (Some(feature), Some(since)) => {
                             let level = Stable { since };
                             if sym::stable == meta_name {
-                                stab = Some(Stability { level, feature, rustc_depr: None });
+                                stab = Some(Stability { level, feature });
                             } else {
                                 const_stab = Some(ConstStability {
                                     level,
@@ -526,22 +445,6 @@ macro_rules! get_meta {
         }
     }
 
-    // Merge the deprecation info into the stability info
-    if let Some(rustc_depr) = rustc_depr {
-        if let Some(ref mut stab) = stab {
-            stab.rustc_depr = Some(rustc_depr);
-        } else {
-            struct_span_err!(
-                diagnostic,
-                item_sp,
-                E0549,
-                "rustc_deprecated attribute must be paired with \
-                       either stable or unstable attribute"
-            )
-            .emit();
-        }
-    }
-
     // Merge the const-unstable info into the stability info
     if promotable || allow_const_fn_ptr {
         if let Some(ref mut stab) = const_stab {
@@ -714,7 +617,16 @@ pub fn eval_condition(
 #[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
+    /// The note to issue a reason.
     pub note: Option<Symbol>,
+    /// A text snippet used to completely replace any use of the deprecated item in an expression.
+    ///
+    /// This is currently unstable.
+    pub suggestion: Option<Symbol>,
+
+    /// Whether to treat the since attribute as being a Rust version identifier
+    /// (rather than an opaque string).
+    pub is_since_rustc_version: bool,
 }
 
 /// Finds the deprecation attribute. `None` if none exists.
@@ -738,7 +650,7 @@ fn find_deprecation_generic<'a, I>(
     let diagnostic = &sess.span_diagnostic;
 
     'outer: for attr in attrs_iter {
-        if !attr.check_name(sym::deprecated) {
+        if !(attr.check_name(sym::deprecated) || attr.check_name(sym::rustc_deprecated)) {
             continue;
         }
 
@@ -751,11 +663,12 @@ fn find_deprecation_generic<'a, I>(
             Some(meta) => meta,
             None => continue,
         };
-        depr = match &meta.kind {
-            MetaItemKind::Word => Some(Deprecation { since: None, note: None }),
-            MetaItemKind::NameValue(..) => {
-                meta.value_str().map(|note| Deprecation { since: None, note: Some(note) })
-            }
+        let mut since = None;
+        let mut note = None;
+        let mut suggestion = None;
+        match &meta.kind {
+            MetaItemKind::Word => {}
+            MetaItemKind::NameValue(..) => note = meta.value_str(),
             MetaItemKind::List(list) => {
                 let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                     if item.is_some() {
@@ -789,8 +702,6 @@ fn find_deprecation_generic<'a, I>(
                     }
                 };
 
-                let mut since = None;
-                let mut note = None;
                 for meta in list {
                     match meta {
                         NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
@@ -799,18 +710,32 @@ fn find_deprecation_generic<'a, I>(
                                     continue 'outer;
                                 }
                             }
-                            sym::note => {
+                            sym::note if attr.check_name(sym::deprecated) => {
+                                if !get(mi, &mut note) {
+                                    continue 'outer;
+                                }
+                            }
+                            sym::reason if attr.check_name(sym::rustc_deprecated) => {
                                 if !get(mi, &mut note) {
                                     continue 'outer;
                                 }
                             }
+                            sym::suggestion if attr.check_name(sym::rustc_deprecated) => {
+                                if !get(mi, &mut suggestion) {
+                                    continue 'outer;
+                                }
+                            }
                             _ => {
                                 handle_errors(
                                     sess,
                                     meta.span(),
                                     AttrError::UnknownMetaItem(
                                         pprust::path_to_string(&mi.path),
-                                        &["since", "note"],
+                                        if attr.check_name(sym::deprecated) {
+                                            &["since", "note"]
+                                        } else {
+                                            &["since", "reason", "suggestion"]
+                                        },
                                     ),
                                 );
                                 continue 'outer;
@@ -829,10 +754,29 @@ fn find_deprecation_generic<'a, I>(
                         }
                     }
                 }
+            }
+        }
+
+        if suggestion.is_some() && attr.check_name(sym::deprecated) {
+            unreachable!("only allowed on rustc_deprecated")
+        }
 
-                Some(Deprecation { since, note })
+        if attr.check_name(sym::rustc_deprecated) {
+            if since.is_none() {
+                handle_errors(sess, attr.span, AttrError::MissingSince);
+                continue;
             }
-        };
+
+            if note.is_none() {
+                struct_span_err!(diagnostic, attr.span, E0543, "missing 'reason'").emit();
+                continue;
+            }
+        }
+
+        mark_used(&attr);
+
+        let is_since_rustc_version = attr.check_name(sym::rustc_deprecated);
+        depr = Some(Deprecation { since, note, suggestion, is_since_rustc_version });
     }
 
     depr
index 099c402703d09f44260df9feab87947654dadcf5..7857ccb613bf8abd7fe212b11576986f80e49c7d 100644 (file)
@@ -366,7 +366,7 @@ fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         unsafe {
             llvm::LLVMPointerType(
                 self.llvm_type(cx),
-                cx.data_layout().instruction_address_space as c_uint,
+                cx.data_layout().instruction_address_space.0 as c_uint,
             )
         }
     }
diff --git a/src/librustc_codegen_llvm/build.rs b/src/librustc_codegen_llvm/build.rs
deleted file mode 100644 (file)
index d1fc624..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_VERSION");
-    println!("cargo:rerun-if-env-changed=CFG_PREFIX");
-    println!("cargo:rerun-if-env-changed=CFG_LLVM_ROOT");
-}
index d58aad340a1dcbc57044edd5f0b473098b84cfbd..8a1bb258d4274480afd58fa175e64fd129fcdd8a 100644 (file)
@@ -1330,7 +1330,12 @@ fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Si
         self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
     }
 
-    fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
+    pub(crate) fn phi(
+        &mut self,
+        ty: &'ll Type,
+        vals: &[&'ll Value],
+        bbs: &[&'ll BasicBlock],
+    ) -> &'ll Value {
         assert_eq!(vals.len(), bbs.len());
         let phi = unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED) };
         unsafe {
index 7b341651adf3dec5d0de0ef748257b44047b3cd9..75b4f2e3ca5a55aa0e4bb6dd79d3ccc6f76f4495 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_codegen_ssa::traits::*;
 
 use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
-use rustc_middle::ty::{Instance, TypeFoldable};
+use rustc_middle::ty::{self, Instance, TypeFoldable};
 
 /// Codegens a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
@@ -29,14 +29,18 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
 
     assert!(!instance.substs.needs_infer());
     assert!(!instance.substs.has_escaping_bound_vars());
-    assert!(!instance.substs.has_param_types_or_consts());
 
     if let Some(&llfn) = cx.instances.borrow().get(&instance) {
         return llfn;
     }
 
     let sym = tcx.symbol_name(instance).name;
-    debug!("get_fn({:?}: {:?}) => {}", instance, instance.monomorphic_ty(cx.tcx()), sym);
+    debug!(
+        "get_fn({:?}: {:?}) => {}",
+        instance,
+        instance.ty(cx.tcx(), ty::ParamEnv::reveal_all()),
+        sym
+    );
 
     let fn_abi = FnAbi::of_instance(cx, instance, &[]);
 
index 64140747871fec68ca8b27a2ebdb516ad2f004e7..2a50d4a46d279436ade2897007f8615097f59b7a 100644 (file)
@@ -16,7 +16,7 @@
 use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{self, HasDataLayout, LayoutOf, Pointer, Size};
+use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};
 
 use libc::{c_char, c_uint};
 use log::debug;
@@ -244,7 +244,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -
                 }
             }
             Scalar::Ptr(ptr) => {
-                let base_addr = match self.tcx.global_alloc(ptr.alloc_id) {
+                let (base_addr, base_addr_space) = match self.tcx.global_alloc(ptr.alloc_id) {
                     GlobalAlloc::Memory(alloc) => {
                         let init = const_alloc_to_llvm(self, alloc);
                         let value = match alloc.mutability {
@@ -254,18 +254,21 @@ fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -
                         if !self.sess().fewer_names() {
                             llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes());
                         }
-                        value
+                        (value, AddressSpace::DATA)
                     }
-                    GlobalAlloc::Function(fn_instance) => self.get_fn_addr(fn_instance),
+                    GlobalAlloc::Function(fn_instance) => (
+                        self.get_fn_addr(fn_instance.polymorphize(self.tcx)),
+                        self.data_layout().instruction_address_space,
+                    ),
                     GlobalAlloc::Static(def_id) => {
                         assert!(self.tcx.is_static(def_id));
                         assert!(!self.tcx.is_thread_local_static(def_id));
-                        self.get_static(def_id)
+                        (self.get_static(def_id), AddressSpace::DATA)
                     }
                 };
                 let llval = unsafe {
                     llvm::LLVMConstInBoundsGEP(
-                        self.const_bitcast(base_addr, self.type_i8p()),
+                        self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)),
                         &self.const_usize(ptr.offset.bytes()),
                         1,
                     )
index c954415f19f346c080508c8df49bc1aa29f83ed7..3e9e5d9c8c1f44e059030d9397441ca8b31feb44 100644 (file)
 use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::interpret::{
-    read_target_uint, Allocation, ConstValue, ErrorHandled, Pointer,
+    read_target_uint, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer,
 };
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
+use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
 
 use std::ffi::CStr;
 
@@ -53,10 +53,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         )
         .expect("const_alloc_to_llvm: could not read relocation pointer")
             as u64;
+
+        let address_space = match cx.tcx.global_alloc(alloc_id) {
+            GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space,
+            GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) => AddressSpace::DATA,
+        };
+
         llvals.push(cx.scalar_to_backend(
             Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
             &Scalar { value: Primitive::Pointer, valid_range: 0..=!0 },
-            cx.type_i8p(),
+            cx.type_i8p_ext(address_space),
         ));
         next_offset = offset + pointer_size;
     }
@@ -203,7 +209,7 @@ impl CodegenCx<'ll, 'tcx> {
             def_id
         );
 
-        let ty = instance.monomorphic_ty(self.tcx);
+        let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
         let sym = self.tcx.symbol_name(instance).name;
 
         debug!("get_static: sym={} instance={:?}", sym, instance);
@@ -361,7 +367,7 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
             };
 
             let instance = Instance::mono(self.tcx, def_id);
-            let ty = instance.monomorphic_ty(self.tcx);
+            let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
             let llty = self.layout_of(ty).llvm_type(self);
             let g = if val_llty == llty {
                 g
index 21ba97d15a485776362716ed8b84b6c946cd1f8d..33a3cdbfa9b443ff638b5e51d4f9c6bd3b851450 100644 (file)
@@ -190,7 +190,7 @@ pub unsafe fn create_module(
 
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
     if sess.target.target.options.is_like_msvc {
-        match sess.opts.debugging_opts.control_flow_guard {
+        match sess.opts.cg.control_flow_guard {
             CFGuard::Disabled => {}
             CFGuard::NoChecks => {
                 // Set `cfguard=1` module flag to emit metadata only.
@@ -510,6 +510,14 @@ macro_rules! vector_types {
         ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32);
         ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64);
         ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64);
+        ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32);
+        ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32);
+        ifn!("llvm.wasm.trunc.unsigned.i64.f32", fn(t_f32) -> t_i64);
+        ifn!("llvm.wasm.trunc.unsigned.i64.f64", fn(t_f64) -> t_i64);
+        ifn!("llvm.wasm.trunc.signed.i32.f32", fn(t_f32) -> t_i32);
+        ifn!("llvm.wasm.trunc.signed.i32.f64", fn(t_f64) -> t_i32);
+        ifn!("llvm.wasm.trunc.signed.i64.f32", fn(t_f32) -> t_i64);
+        ifn!("llvm.wasm.trunc.signed.i64.f64", fn(t_f64) -> t_i64);
 
         ifn!("llvm.trap", fn() -> void);
         ifn!("llvm.debugtrap", fn() -> void);
index ef9d42968ae2e0a1ae27a2fe6c92f9ffbea48405..6ae7c7efaee62b4933c33d8d578493e348a9fa55 100644 (file)
@@ -700,6 +700,8 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
             prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA)
                 .finalize(cx)
         }
+        // Type parameters from polymorphized functions.
+        ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false),
         _ => bug!("debuginfo: unexpected type in type_metadata: {:?}", t),
     };
 
@@ -955,6 +957,20 @@ fn pointer_type_metadata(
     }
 }
 
+fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
+    debug!("param_type_metadata: {:?}", t);
+    let name = format!("{:?}", t);
+    return unsafe {
+        llvm::LLVMRustDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr().cast(),
+            name.len(),
+            Size::ZERO.bits(),
+            DW_ATE_unsigned,
+        )
+    };
+}
+
 pub fn compile_unit_metadata(
     tcx: TyCtxt<'_>,
     codegen_unit_name: &str,
@@ -2465,7 +2481,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, def_id);
-    let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx);
+    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
     let type_metadata = type_metadata(cx, variable_type, span);
     let var_name = tcx.item_name(def_id).as_str();
     let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name;
index 44993d7602fe6e89ca9f16c0dce53391b527a88d..a01b8553721290697e789f760c95cc084718a72a 100644 (file)
@@ -26,7 +26,7 @@
 use rustc_middle::mir;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, Instance, ParamEnv, Ty};
+use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
 use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, BytePos, Span};
@@ -470,7 +470,9 @@ fn get_containing_scope<'ll, 'tcx>(
                     match impl_self_ty.kind {
                         ty::Adt(def, ..) if !def.is_box() => {
                             // Again, only create type information if full debuginfo is enabled
-                            if cx.sess().opts.debuginfo == DebugInfo::Full {
+                            if cx.sess().opts.debuginfo == DebugInfo::Full
+                                && !impl_self_ty.needs_subst()
+                            {
                                 Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
                             } else {
                                 Some(namespace::item_namespace(cx, def.did))
index 63ec8031483fed508f50f03fa06d6d29284f627a..11b1c95c58b3e14e10dfb341bb1ccea0752fe4a5 100644 (file)
@@ -160,7 +160,7 @@ fn codegen_intrinsic_call(
         caller_instance: ty::Instance<'tcx>,
     ) {
         let tcx = self.tcx;
-        let callee_ty = instance.monomorphic_ty(tcx);
+        let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
 
         let (def_id, substs) = match callee_ty.kind {
             ty::FnDef(def_id, substs) => (def_id, substs),
@@ -629,27 +629,24 @@ fn codegen_intrinsic_call(
             }
 
             sym::float_to_int_unchecked => {
-                if float_type_width(arg_tys[0]).is_none() {
-                    span_invalid_monomorphization_error(
-                        tcx.sess,
-                        span,
-                        &format!(
-                            "invalid monomorphization of `float_to_int_unchecked` \
+                let float_width = match float_type_width(arg_tys[0]) {
+                    Some(width) => width,
+                    None => {
+                        span_invalid_monomorphization_error(
+                            tcx.sess,
+                            span,
+                            &format!(
+                                "invalid monomorphization of `float_to_int_unchecked` \
                                   intrinsic: expected basic float type, \
                                   found `{}`",
-                            arg_tys[0]
-                        ),
-                    );
-                    return;
-                }
-                match int_type_width_signed(ret_ty, self.cx) {
-                    Some((width, signed)) => {
-                        if signed {
-                            self.fptosi(args[0].immediate(), self.cx.type_ix(width))
-                        } else {
-                            self.fptoui(args[0].immediate(), self.cx.type_ix(width))
-                        }
+                                arg_tys[0]
+                            ),
+                        );
+                        return;
                     }
+                };
+                let (width, signed) = match int_type_width_signed(ret_ty, self.cx) {
+                    Some(pair) => pair,
                     None => {
                         span_invalid_monomorphization_error(
                             tcx.sess,
@@ -663,7 +660,49 @@ fn codegen_intrinsic_call(
                         );
                         return;
                     }
+                };
+
+                // The LLVM backend can reorder and speculate `fptosi` and
+                // `fptoui`, so on WebAssembly the codegen for this instruction
+                // is quite heavyweight. To avoid this heavyweight codegen we
+                // instead use the raw wasm intrinsics which will lower to one
+                // instruction in WebAssembly (`iNN.trunc_fMM_{s,u}`). This one
+                // instruction will trap if the operand is out of bounds, but
+                // that's ok since this intrinsic is UB if the operands are out
+                // of bounds, so the behavior can be different on WebAssembly
+                // than other targets.
+                //
+                // Note, however, that when the `nontrapping-fptoint` feature is
+                // enabled in LLVM then LLVM will lower `fptosi` to
+                // `iNN.trunc_sat_fMM_{s,u}`, so if that's the case we don't
+                // bother with intrinsics.
+                let mut result = None;
+                if self.sess().target.target.arch == "wasm32"
+                    && !self.sess().target_features.contains(&sym::nontrapping_dash_fptoint)
+                {
+                    let name = match (width, float_width, signed) {
+                        (32, 32, true) => Some("llvm.wasm.trunc.signed.i32.f32"),
+                        (32, 64, true) => Some("llvm.wasm.trunc.signed.i32.f64"),
+                        (64, 32, true) => Some("llvm.wasm.trunc.signed.i64.f32"),
+                        (64, 64, true) => Some("llvm.wasm.trunc.signed.i64.f64"),
+                        (32, 32, false) => Some("llvm.wasm.trunc.unsigned.i32.f32"),
+                        (32, 64, false) => Some("llvm.wasm.trunc.unsigned.i32.f64"),
+                        (64, 32, false) => Some("llvm.wasm.trunc.unsigned.i64.f32"),
+                        (64, 64, false) => Some("llvm.wasm.trunc.unsigned.i64.f64"),
+                        _ => None,
+                    };
+                    if let Some(name) = name {
+                        let intrinsic = self.get_intrinsic(name);
+                        result = Some(self.call(intrinsic, &[args[0].immediate()], None));
+                    }
                 }
+                result.unwrap_or_else(|| {
+                    if signed {
+                        self.fptosi(args[0].immediate(), self.cx.type_ix(width))
+                    } else {
+                        self.fptoui(args[0].immediate(), self.cx.type_ix(width))
+                    }
+                })
             }
 
             sym::discriminant_value => {
index 486ea7f22dfffb1c968607e57fc60682ece68f11..0936deb7bb5a9c26d916e2a088d4e2cf5b98bd82 100644 (file)
@@ -10,7 +10,7 @@
 pub use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
 use rustc_middle::ty::layout::FnAbiExt;
-use rustc_middle::ty::{Instance, TypeFoldable};
+use rustc_middle::ty::{self, Instance, TypeFoldable};
 use rustc_target::abi::LayoutOf;
 
 impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -22,7 +22,7 @@ fn predefine_static(
         symbol_name: &str,
     ) {
         let instance = Instance::mono(self.tcx, def_id);
-        let ty = instance.monomorphic_ty(self.tcx);
+        let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
         let llty = self.layout_of(ty).llvm_type(self);
 
         let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
@@ -47,7 +47,7 @@ fn predefine_fn(
         visibility: Visibility,
         symbol_name: &str,
     ) {
-        assert!(!instance.substs.needs_infer() && !instance.substs.has_param_types_or_consts());
+        assert!(!instance.substs.needs_infer());
 
         let fn_abi = FnAbi::of_instance(self, instance, &[]);
         let lldecl = self.declare_fn(symbol_name, &fn_abi);
index 854eff31733805e349062e7876efd4889b756cc9..05e364884f66dcd66fac3e1b2d5e3fa8d7e89ce6 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::Ty;
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
-use rustc_target::abi::{Align, Integer, Size};
+use rustc_target::abi::{AddressSpace, Align, Integer, Size};
 
 use std::fmt;
 use std::ptr;
@@ -198,9 +198,13 @@ fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
         assert_ne!(
             self.type_kind(ty),
             TypeKind::Function,
-            "don't call ptr_to on function types, use ptr_to_llvm_type on FnAbi instead"
+            "don't call ptr_to on function types, use ptr_to_llvm_type on FnAbi instead or explicitly specify an address space if it makes sense"
         );
-        ty.ptr_to()
+        ty.ptr_to(AddressSpace::DATA)
+    }
+
+    fn type_ptr_to_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type {
+        ty.ptr_to(address_space)
     }
 
     fn element_type(&self, ty: &'ll Type) -> &'ll Type {
@@ -241,11 +245,11 @@ pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
     }
 
     pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
-        Type::i8_llcx(llcx).ptr_to()
+        Type::i8_llcx(llcx).ptr_to(AddressSpace::DATA)
     }
 
-    fn ptr_to(&self) -> &Type {
-        unsafe { llvm::LLVMPointerType(&self, 0) }
+    fn ptr_to(&self, address_space: AddressSpace) -> &Type {
+        unsafe { llvm::LLVMPointerType(&self, address_space.0) }
     }
 }
 
index 5a0da6be5980ed8d1192e63bf7eae7d189df5762..1d0adc5783f3d74dc99836108f59889fe23d1ce9 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
 use rustc_middle::ty::print::obsolete::DefPathBasedNames;
 use rustc_middle::ty::{self, Ty, TypeFoldable};
-use rustc_target::abi::{Abi, Align, FieldsShape};
+use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAndLayoutMethods, Variants};
 
@@ -310,12 +310,13 @@ fn scalar_llvm_type_at<'a>(
             F64 => cx.type_f64(),
             Pointer => {
                 // If we know the alignment, pick something better than i8.
-                let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
-                    cx.type_pointee_for_align(pointee.align)
-                } else {
-                    cx.type_i8()
-                };
-                cx.type_ptr_to(pointee)
+                let (pointee, address_space) =
+                    if let Some(pointee) = self.pointee_info_at(cx, offset) {
+                        (cx.type_pointee_for_align(pointee.align), pointee.address_space)
+                    } else {
+                        (cx.type_i8(), AddressSpace::DATA)
+                    };
+                cx.type_ptr_to_ext(pointee, address_space)
             }
         }
     }
index 8bc3579800ea81380214b01e823161a28bb8454b..54efa05aee81e315ea619eebb3b2bc827603f15d 100644 (file)
@@ -3,8 +3,9 @@
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use rustc_codegen_ssa::mir::operand::OperandRef;
-use rustc_codegen_ssa::traits::{
-    BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods,
+use rustc_codegen_ssa::{
+    common::IntPredicate,
+    traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
 };
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::Ty;
@@ -89,6 +90,81 @@ fn emit_ptr_va_arg(
     }
 }
 
+fn emit_aapcs_va_arg(
+    bx: &mut Builder<'a, 'll, 'tcx>,
+    list: OperandRef<'tcx, &'ll Value>,
+    target_ty: Ty<'tcx>,
+) -> &'ll Value {
+    // Implementation of the AAPCS64 calling convention for va_args see
+    // https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
+    let va_list_addr = list.immediate();
+    let layout = bx.cx.layout_of(target_ty);
+
+    let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg");
+    let mut in_reg = bx.build_sibling_block("va_arg.in_reg");
+    let mut on_stack = bx.build_sibling_block("va_arg.on_stack");
+    let mut end = bx.build_sibling_block("va_arg.end");
+    let zero = bx.const_i32(0);
+    let offset_align = Align::from_bytes(4).unwrap();
+    assert!(&*bx.tcx().sess.target.target.target_endian == "little");
+
+    let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
+    let (reg_off, reg_top_index, slot_size) = if gr_type {
+        let gr_offs = bx.struct_gep(va_list_addr, 7);
+        let nreg = (layout.size.bytes() + 7) / 8;
+        (gr_offs, 3, nreg * 8)
+    } else {
+        let vr_off = bx.struct_gep(va_list_addr, 9);
+        let nreg = (layout.size.bytes() + 15) / 16;
+        (vr_off, 5, nreg * 16)
+    };
+
+    // if the offset >= 0 then the value will be on the stack
+    let mut reg_off_v = bx.load(reg_off, offset_align);
+    let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
+    bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());
+
+    // The value at this point might be in a register, but there is a chance that
+    // it could be on the stack so we have to update the offset and then check
+    // the offset again.
+
+    if gr_type && layout.align.abi.bytes() > 8 {
+        reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15));
+        reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16));
+    }
+    let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32));
+
+    maybe_reg.store(new_reg_off_v, reg_off, offset_align);
+
+    // Check to see if we have overflowed the registers as a result of this.
+    // If we have then we need to use the stack for this value
+    let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
+    maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());
+
+    let top = in_reg.struct_gep(va_list_addr, reg_top_index);
+    let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);
+
+    // reg_value = *(@top + reg_off_v);
+    let top = in_reg.gep(top, &[reg_off_v]);
+    let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx)));
+    let reg_value = in_reg.load(top, layout.align.abi);
+    in_reg.br(&end.llbb());
+
+    // On Stack block
+    let stack_value =
+        emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true);
+    on_stack.br(&end.llbb());
+
+    let val = end.phi(
+        layout.immediate_llvm_type(bx),
+        &[reg_value, stack_value],
+        &[&in_reg.llbb(), &on_stack.llbb()],
+    );
+
+    *bx = end;
+    val
+}
+
 pub(super) fn emit_va_arg(
     bx: &mut Builder<'a, 'll, 'tcx>,
     addr: OperandRef<'tcx, &'ll Value>,
@@ -115,6 +191,7 @@ pub(super) fn emit_va_arg(
         ("aarch64", _) if target.target_os == "ios" => {
             emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
         }
+        ("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty),
         // Windows x86_64
         ("x86_64", true) => {
             let target_ty_size = bx.cx.size_of(target_ty).bytes();
index 2d65282ce7798751268970eb62534bf7349201b6..9191c68d4537aac7f7a43a8596d5adaa3d505680 100644 (file)
@@ -1598,7 +1598,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     }
 
     // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    cmd.add_eh_frame_header();
+    if sess.target.target.options.eh_frame_header {
+        cmd.add_eh_frame_header();
+    }
 
     // NO-OPT-OUT, OBJECT-FILES-NO
     if crt_objects_fallback {
@@ -1700,7 +1702,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     }
 
     // OBJECT-FILES-NO, AUDIT-ORDER
-    if sess.opts.debugging_opts.control_flow_guard != CFGuard::Disabled {
+    if sess.opts.cg.control_flow_guard != CFGuard::Disabled {
         cmd.control_flow_guard();
     }
 
index e64aafa599fd8ae39d63af34fbb8808cd810090e..d1ae9e372695fded7ad77293f052f541368ca746 100644 (file)
@@ -619,13 +619,7 @@ fn linker_plugin_lto(&mut self) {
     // Some versions of `gcc` add it implicitly, some (e.g. `musl-gcc`) don't,
     // so we just always add it.
     fn add_eh_frame_header(&mut self) {
-        if !self.sess.target.target.options.is_like_osx
-            && !self.sess.target.target.options.is_like_windows
-            && !self.sess.target.target.options.is_like_solaris
-            && self.sess.target.target.target_os != "uefi"
-        {
-            self.linker_arg("--eh-frame-hdr");
-        }
+        self.linker_arg("--eh-frame-hdr");
     }
 }
 
diff --git a/src/librustc_codegen_ssa/build.rs b/src/librustc_codegen_ssa/build.rs
deleted file mode 100644 (file)
index ea2af6e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_RELEASE_CHANNEL");
-}
index 20d440433cbb0bc4f5b27bc3f4490aabadecd39f..fb8f5a6298911f23584790e9cf62b39db5ec189d 100644 (file)
@@ -205,14 +205,17 @@ pub fn push_debuginfo_type_name<'tcx>(
                 tcx.def_key(def_id).disambiguated_data.disambiguator
             ));
         }
+        // Type parameters from polymorphized functions.
+        ty::Param(_) => {
+            output.push_str(&format!("{:?}", t));
+        }
         ty::Error(_)
         | ty::Infer(_)
         | ty::Placeholder(..)
         | ty::Projection(..)
         | ty::Bound(..)
         | ty::Opaque(..)
-        | ty::GeneratorWitness(..)
-        | ty::Param(_) => {
+        | ty::GeneratorWitness(..) => {
             bug!(
                 "debuginfo: Trying to create type name for \
                   unexpected type: {:?}",
index 199dd8c7df42fd7d0be1e33acb752b6d652b210e..bcc19c6a44bd829ffff227b9c606938cb26da6b5 100644 (file)
@@ -75,7 +75,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     }
 
     // Not in the cache; build it.
-    let nullptr = cx.const_null(cx.type_i8p());
+    let nullptr = cx.const_null(cx.type_i8p_ext(cx.data_layout().instruction_address_space));
 
     let methods_root;
     let methods = if let Some(trait_ref) = trait_ref {
@@ -94,7 +94,8 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
                     def_id,
                     substs,
                 )
-                .unwrap(),
+                .unwrap()
+                .polymorphize(cx.tcx()),
             )
         })
     });
index db935c2b3e2658a027ba7525da21a38e90146a44..2e386c1e5946bf141e409900e7eaba4a88338c19 100644 (file)
@@ -124,8 +124,7 @@ fn process_place(
                 let base_ty = self.fx.monomorphize(&base_ty);
 
                 // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty.projection_ty(cx.tcx(), elem).ty;
-                let elem_ty = self.fx.monomorphize(&elem_ty);
+                let elem_ty = base_ty.projection_ty(cx.tcx(), self.fx.monomorphize(&elem)).ty;
                 let span = self.fx.mir.local_decls[place_ref.local].source_info.span;
                 if cx.spanned_layout_of(elem_ty, span).is_zst() {
                     return;
index 7116bb8c92517d3fbf1fba318f5db2e30700ac9e..e8270b4fa0adba7b5802ef2bb95ff0b49b419b27 100644 (file)
@@ -543,7 +543,8 @@ fn codegen_call_terminator(
                 Some(
                     ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs)
                         .unwrap()
-                        .unwrap(),
+                        .unwrap()
+                        .polymorphize(bx.tcx()),
                 ),
                 None,
             ),
@@ -605,11 +606,6 @@ fn codegen_call_terminator(
             return;
         }
 
-        // For normal codegen, this Miri-specific intrinsic should never occur.
-        if intrinsic == Some(sym::miri_start_panic) {
-            bug!("`miri_start_panic` should never end up in compiled code");
-        }
-
         if self.codegen_panic_intrinsic(
             &helper,
             &mut bx,
@@ -887,7 +883,7 @@ fn codegen_asm_terminator(
                                 let ptr = Pointer::new(AllocId(0), offset);
                                 alloc
                                     .read_scalar(&bx, ptr, size)
-                                    .and_then(|s| s.not_undef())
+                                    .and_then(|s| s.check_init())
                                     .unwrap_or_else(|e| {
                                         bx.tcx().sess.span_err(
                                             span,
index 00b4bf96afa594b75e55115647bb84b9410c6179..f4d83e87710822836ccab73f7674d4bc417aef08 100644 (file)
@@ -6,6 +6,7 @@
 use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_target::abi::call::{FnAbi, PassMode};
+use rustc_target::abi::HasDataLayout;
 
 use std::iter;
 
@@ -323,7 +324,9 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                     // C++ personality function, but `catch (...)` has no type so
                     // it's null. The 64 here is actually a bitfield which
                     // represents that this is a catch-all block.
-                    let null = bx.const_null(bx.type_i8p());
+                    let null = bx.const_null(
+                        bx.type_i8p_ext(bx.cx().data_layout().instruction_address_space),
+                    );
                     let sixty_four = bx.const_i32(64);
                     funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
                     cp_bx.br(llbb);
index 4b2be7b5321ff8aec4cc808b133461cd6c3f88c9..9c108998bc9078928827a8114789a56b0f474e97 100644 (file)
@@ -190,17 +190,15 @@ pub fn codegen_rvalue_operand(
                                 if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) {
                                     bug!("reifying a fn ptr that requires const arguments");
                                 }
-                                OperandValue::Immediate(
-                                    bx.get_fn_addr(
-                                        ty::Instance::resolve_for_fn_ptr(
-                                            bx.tcx(),
-                                            ty::ParamEnv::reveal_all(),
-                                            def_id,
-                                            substs,
-                                        )
-                                        .unwrap(),
-                                    ),
+                                let instance = ty::Instance::resolve_for_fn_ptr(
+                                    bx.tcx(),
+                                    ty::ParamEnv::reveal_all(),
+                                    def_id,
+                                    substs,
                                 )
+                                .unwrap()
+                                .polymorphize(bx.cx().tcx());
+                                OperandValue::Immediate(bx.get_fn_addr(instance))
                             }
                             _ => bug!("{} cannot be reified to a fn ptr", operand.layout.ty),
                         }
@@ -213,7 +211,8 @@ pub fn codegen_rvalue_operand(
                                     def_id,
                                     substs,
                                     ty::ClosureKind::FnOnce,
-                                );
+                                )
+                                .polymorphize(bx.cx().tcx());
                                 OperandValue::Immediate(bx.cx().get_fn_addr(instance))
                             }
                             _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
index c55bf9858b972450c4cd607ee630221dacb23f38..726d948cfd40cf483be1e705af99a8412f59abd4 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_middle::ty::{self, Ty};
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
-use rustc_target::abi::Integer;
+use rustc_target::abi::{AddressSpace, Integer};
 
 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
 // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
@@ -27,6 +27,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
     fn type_kind(&self, ty: Self::Type) -> TypeKind;
     fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
+    fn type_ptr_to_ext(&self, ty: Self::Type, address_space: AddressSpace) -> Self::Type;
     fn element_type(&self, ty: Self::Type) -> Self::Type;
 
     /// Returns the number of elements in `self` if it is a LLVM vector type.
@@ -42,7 +43,11 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
 
 pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
     fn type_i8p(&self) -> Self::Type {
-        self.type_ptr_to(self.type_i8())
+        self.type_i8p_ext(AddressSpace::DATA)
+    }
+
+    fn type_i8p_ext(&self, address_space: AddressSpace) -> Self::Type {
+        self.type_ptr_to_ext(self.type_i8(), address_space)
     }
 
     fn type_int(&self) -> Self::Type {
index b7005ccdc998be72cb0276c20d2de5917e211a7d..2bb421a47efa689632dcc42dc445a584c0a8f845 100644 (file)
@@ -7,8 +7,8 @@
 use crate::stable_hasher::{HashStable, StableHasher};
 use rustc_index::vec::{Idx, IndexVec};
 
-/// An indexed multi-map that preserves insertion order while permitting both `O(log n)` lookup of
-/// an item by key and `O(1)` lookup by index.
+/// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of
+/// an item by key and *O*(1) lookup by index.
 ///
 /// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`,
 /// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order.
@@ -20,7 +20,7 @@
 /// items will be yielded in insertion order.
 ///
 /// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and
-/// `SortedIndexMultiMap` require `O(n)` time to insert a single item. This is because we may need
+/// `SortedIndexMultiMap` require *O*(*n*) time to insert a single item. This is because we may need
 /// to insert into the middle of the sorted array. Users should avoid mutating this data structure
 /// in-place.
 ///
index 97b02eaef35d0732b0c4ce8ab9a19cf30ba66147..c1c79b174f415e93d4637ca0f684f54856a6871f 100644 (file)
@@ -469,6 +469,15 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
     }
 }
 
+impl<T, CTX> HashStable<CTX> for bit_set::FiniteBitSet<T>
+where
+    T: HashStable<CTX> + bit_set::FiniteBitSetTy,
+{
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.0.hash_stable(hcx, hasher);
+    }
+}
+
 impl_stable_hash_via_hash!(::std::path::Path);
 impl_stable_hash_via_hash!(::std::path::PathBuf);
 
diff --git a/src/librustc_driver/build.rs b/src/librustc_driver/build.rs
deleted file mode 100644 (file)
index 414d134..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_RELEASE");
-    println!("cargo:rerun-if-env-changed=CFG_VERSION");
-    println!("cargo:rerun-if-env-changed=CFG_VER_DATE");
-    println!("cargo:rerun-if-env-changed=CFG_VER_HASH");
-}
index bbbd8359f0126b229ccf8f6f9bd79082a8819c2b..4e5e77f80c28a1208c4f0121777816cd98cbf24f 100644 (file)
 E0768: include_str!("./error_codes/E0768.md"),
 E0769: include_str!("./error_codes/E0769.md"),
 E0770: include_str!("./error_codes/E0770.md"),
+E0771: include_str!("./error_codes/E0771.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
     E0521, // borrowed data escapes outside of closure
     E0523,
 //  E0526, // shuffle indices are not constant
-    E0540, // multiple rustc_deprecated attributes
+//  E0540, // multiple rustc_deprecated attributes
     E0542, // missing 'since'
     E0543, // missing 'reason'
     E0544, // multiple stability levels
     E0755, // `#[ffi_pure]` is only allowed on foreign functions
     E0756, // `#[ffi_const]` is only allowed on foreign functions
     E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
+    E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
 }
index 38bc63550ac7ff0f0541becc1eef0e0076d47f77..057a0b1645c57c24164e80eb5752588e97caad0c 100644 (file)
@@ -1,4 +1,4 @@
-The value for an associated type has already been specified.
+An associated type value was specified more than once.
 
 Erroneous code example:
 
@@ -25,7 +25,7 @@ trait FooTrait {}
 trait BarTrait {}
 trait FooBarTrait: FooTrait + BarTrait {}
 
-struct Foo<T: Iterator<Item: FooBarTrait>> { f: T }
+struct Foo<T: Iterator<Item: FooBarTrait>> { f: T } // ok!
 ```
 
 For more information about associated types, see [the book][bk-at]. For more
index 7a7ba15485434836c9754da42db925d1a098a5d8..e8f84d0fc7d508deb202e5b1515149806bc83546 100644 (file)
@@ -1,4 +1,5 @@
-`#[ffi_returns_twice]` was used on non-foreign function.
+`#[ffi_returns_twice]` was used on something other than a foreign function
+declaration.
 
 Erroneous code example:
 
index be1b68e645d012ca3223c1627a8b5f3fe01d40ae..386daea0c57e3dfd4c6204c957b1572621221b32 100644 (file)
@@ -1,6 +1,6 @@
 A `yield` clause was used in an `async` context.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0727,edition2018
 #![feature(generators)]
diff --git a/src/librustc_error_codes/error_codes/E0771.md b/src/librustc_error_codes/error_codes/E0771.md
new file mode 100644 (file)
index 0000000..824a955
--- /dev/null
@@ -0,0 +1,23 @@
+A non-`'static` lifetime was used in a const generic. This is currently not
+allowed.
+
+Erroneous code example:
+
+```compile_fail,E0771
+#![feature(const_generics)]
+
+fn function_with_str<'a, const STRING: &'a str>() {} // error!
+```
+
+To fix this issue, the lifetime in the const generic need to be changed to
+`'static`:
+
+```
+#![feature(const_generics)]
+
+fn function_with_str<const STRING: &'static str>() {} // ok!
+```
+
+For more information, see [GitHub issue #74052].
+
+[GitHub issue #74052]: https://github.com/rust-lang/rust/issues/74052
index 64e2d5b3a467c84fd18b28223e40141680d8431b..daa75d423249aa4da01bb6146224a041acb36f2f 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_errors::{DiagnosticBuilder, ErrorReported};
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit};
-use rustc_span::def_id::DefId;
+use rustc_span::def_id::{DefId, LOCAL_CRATE};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
@@ -873,6 +873,8 @@ pub fn expn_data(
             local_inner_macros: self.local_inner_macros,
             edition: self.edition,
             macro_def_id,
+            krate: LOCAL_CRATE,
+            orig_id: None,
         }
     }
 }
index bd7a094c5e355737280dade8ea08d0a9748c6f39..e4c0fcaa298d282032bc662666997c1fa36d5ea1 100644 (file)
@@ -1,7 +1,7 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
 use crate::configure;
-use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext};
+use crate::hygiene::{ExpnData, ExpnKind, SyntaxContext};
 use crate::mbe::macro_rules::annotate_err_with_kind;
 use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
 use crate::placeholders::{placeholder, PlaceholderExpander};
@@ -17,6 +17,7 @@
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
 use rustc_data_structures::map_in_place::MapInPlace;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
@@ -27,7 +28,7 @@
 use rustc_session::Limit;
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{FileName, Span, DUMMY_SP};
+use rustc_span::{ExpnId, FileName, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
 use std::io::ErrorKind;
@@ -1165,7 +1166,7 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
                 self.check_attributes(&expr.attrs);
                 self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
             } else {
-                noop_visit_expr(&mut expr, self);
+                ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
                 expr
             }
         });
index d93c17b05b498c02baa6225f0173191cc519cca3..d16f023c00a6216109be48ace5e222590dcf5c10 100644 (file)
@@ -262,9 +262,9 @@ macro_rules! declare_features {
     /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
     (accepted, slice_patterns, "1.42.0", Some(62254), None),
     /// Allows the use of `if` and `match` in constants.
-    (accepted, const_if_match, "1.45.0", Some(49146), None),
+    (accepted, const_if_match, "1.46.0", Some(49146), None),
     /// Allows the use of `loop` and `while` in constants.
-    (accepted, const_loop, "1.45.0", Some(52000), None),
+    (accepted, const_loop, "1.46.0", Some(52000), None),
     /// Allows `#[track_caller]` to be used which provides
     /// accurate caller location reporting during panic (RFC 2091).
     (accepted, track_caller, "1.46.0", Some(47809), None),
index 4e2aea34fe7fb713d5eab44c83de0faea28ac7f0..879f06f89a70a8a92bc55be479634edb854578b3 100644 (file)
@@ -568,6 +568,7 @@ macro_rules! experimental {
     ),
     rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)),
+    rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)),
     rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")),
     rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
index f56522406b0a707f36cda83862b4bc684f47fb6b..6474dc318d329f73854c2c0526b8f075589c7f0b 100644 (file)
@@ -2198,7 +2198,17 @@ pub enum IsAsync {
     NotAsync,
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(
+    Copy,
+    Clone,
+    PartialEq,
+    RustcEncodable,
+    RustcDecodable,
+    Debug,
+    HashStable_Generic,
+    Eq,
+    Hash
+)]
 pub enum Defaultness {
     Default { has_value: bool },
     Final,
diff --git a/src/librustc_incremental/build.rs b/src/librustc_incremental/build.rs
deleted file mode 100644 (file)
index d230ba9..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_VERSION");
-}
index 3e1d4b68c6fa104f1184d1908c8740009174ceaf..b369be252185b378319eca659abce5966c96b855 100644 (file)
@@ -4,6 +4,7 @@
 use std::iter;
 use std::marker::PhantomData;
 use std::mem;
+use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Range, Shl};
 use std::slice;
 
 #[cfg(test)]
@@ -772,7 +773,7 @@ pub fn contains(&self, row: R, column: C) -> bool {
     }
 
     /// Returns those indices that are true in rows `a` and `b`. This
-    /// is an O(n) operation where `n` is the number of elements
+    /// is an *O*(*n*) operation where *n* is the number of elements
     /// (somewhat independent from the actual size of the
     /// intersection, in particular).
     pub fn intersect_rows(&self, row1: R, row2: R) -> Vec<C> {
@@ -1001,3 +1002,137 @@ fn word_index_and_mask<T: Idx>(elem: T) -> (usize, Word) {
     let mask = 1 << (elem % WORD_BITS);
     (word_index, mask)
 }
+
+/// Integral type used to represent the bit set.
+pub trait FiniteBitSetTy:
+    BitAnd<Output = Self>
+    + BitAndAssign
+    + BitOrAssign
+    + Clone
+    + Copy
+    + Shl
+    + Not<Output = Self>
+    + PartialEq
+    + Sized
+{
+    /// Size of the domain representable by this type, e.g. 64 for `u64`.
+    const DOMAIN_SIZE: u32;
+
+    /// Value which represents the `FiniteBitSet` having every bit set.
+    const FILLED: Self;
+    /// Value which represents the `FiniteBitSet` having no bits set.
+    const EMPTY: Self;
+
+    /// Value for one as the integral type.
+    const ONE: Self;
+    /// Value for zero as the integral type.
+    const ZERO: Self;
+
+    /// Perform a checked left shift on the integral type.
+    fn checked_shl(self, rhs: u32) -> Option<Self>;
+    /// Perform a checked right shift on the integral type.
+    fn checked_shr(self, rhs: u32) -> Option<Self>;
+}
+
+impl FiniteBitSetTy for u64 {
+    const DOMAIN_SIZE: u32 = 64;
+
+    const FILLED: Self = Self::MAX;
+    const EMPTY: Self = Self::MIN;
+
+    const ONE: Self = 1u64;
+    const ZERO: Self = 0u64;
+
+    fn checked_shl(self, rhs: u32) -> Option<Self> {
+        self.checked_shl(rhs)
+    }
+
+    fn checked_shr(self, rhs: u32) -> Option<Self> {
+        self.checked_shr(rhs)
+    }
+}
+
+impl std::fmt::Debug for FiniteBitSet<u64> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:064b}", self.0)
+    }
+}
+
+impl FiniteBitSetTy for u128 {
+    const DOMAIN_SIZE: u32 = 128;
+
+    const FILLED: Self = Self::MAX;
+    const EMPTY: Self = Self::MIN;
+
+    const ONE: Self = 1u128;
+    const ZERO: Self = 0u128;
+
+    fn checked_shl(self, rhs: u32) -> Option<Self> {
+        self.checked_shl(rhs)
+    }
+
+    fn checked_shr(self, rhs: u32) -> Option<Self> {
+        self.checked_shr(rhs)
+    }
+}
+
+impl std::fmt::Debug for FiniteBitSet<u128> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:0128b}", self.0)
+    }
+}
+
+/// 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)]
+pub struct FiniteBitSet<T: FiniteBitSetTy>(pub T);
+
+impl<T: FiniteBitSetTy> FiniteBitSet<T> {
+    /// Creates a new, empty bitset.
+    pub fn new_empty() -> Self {
+        Self(T::EMPTY)
+    }
+
+    /// Sets the `index`th bit.
+    pub fn set(&mut self, index: u32) {
+        self.0 |= T::ONE.checked_shl(index).unwrap_or(T::ZERO);
+    }
+
+    /// Unsets the `index`th bit.
+    pub fn clear(&mut self, index: u32) {
+        self.0 &= !T::ONE.checked_shl(index).unwrap_or(T::ZERO);
+    }
+
+    /// Sets the `i`th to `j`th bits.
+    pub fn set_range(&mut self, range: Range<u32>) {
+        let bits = T::FILLED
+            .checked_shl(range.end - range.start)
+            .unwrap_or(T::ZERO)
+            .not()
+            .checked_shl(range.start)
+            .unwrap_or(T::ZERO);
+        self.0 |= bits;
+    }
+
+    /// Is the set empty?
+    pub fn is_empty(&self) -> bool {
+        self.0 == T::EMPTY
+    }
+
+    /// Returns the domain size of the bitset.
+    pub fn within_domain(&self, index: u32) -> bool {
+        index < T::DOMAIN_SIZE
+    }
+
+    /// Returns if the `index`th bit is set.
+    pub fn contains(&self, index: u32) -> Option<bool> {
+        self.within_domain(index)
+            .then(|| ((self.0.checked_shr(index).unwrap_or(T::ONE)) & T::ONE) == T::ONE)
+    }
+}
+
+impl<T: FiniteBitSetTy> Default for FiniteBitSet<T> {
+    fn default() -> Self {
+        Self::new_empty()
+    }
+}
index eaef4c7b54a625d05f72ce44e88acd074481f30d..7ee881b0639daf53f363e82d6878fc12e0a1735c 100644 (file)
@@ -1,4 +1,5 @@
 #![feature(allow_internal_unstable)]
+#![feature(bool_to_option)]
 #![feature(const_fn)]
 #![feature(const_panic)]
 #![feature(extend_one)]
index 3b564e03d9a94e91ff1fe11b78e4ff7505147402..c63464e5baec9e3b1a71409ad0402cc1a710684e 100644 (file)
 
 use rustc_ast::ast;
 use rustc_hir::def_id::DefId;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use rustc_middle::ty::{IntType, UintType};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::DUMMY_SP;
 
 #[derive(Clone)]
 pub struct CombineFields<'infcx, 'tcx> {
@@ -367,10 +368,11 @@ fn generalize(
         };
 
         debug!("generalize: for_universe = {:?}", for_universe);
+        debug!("generalize: trace = {:?}", self.trace);
 
         let mut generalize = Generalizer {
             infcx: self.infcx,
-            span: self.trace.cause.span,
+            cause: &self.trace.cause,
             for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
             for_universe,
             ambient_variance,
@@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
 
     /// The span, used when creating new type variables and things.
-    span: Span,
+    cause: &'cx ObligationCause<'tcx>,
 
     /// The vid of the type variable that is in the process of being
     /// instantiated; if we find this within the type we are folding,
@@ -639,7 +641,7 @@ fn regions(
 
         // FIXME: This is non-ideal because we don't give a
         // very descriptive origin for this region variable.
-        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
+        Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
     }
 
     fn consts(
index 633589db2704cd7e37ed882b7d3f64b64bfcb997..063246f79fe362ff41c69a637fcca09d3e32260d 100644 (file)
@@ -1402,8 +1402,12 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         }
 
         debug!("note_type_err(diag={:?})", diag);
+        enum Mismatch<'a> {
+            Variable(ty::error::ExpectedFound<Ty<'a>>),
+            Fixed(&'static str),
+        }
         let (expected_found, exp_found, is_simple_error) = match values {
-            None => (None, None, false),
+            None => (None, Mismatch::Fixed("type"), false),
             Some(values) => {
                 let (is_simple_error, exp_found) = match values {
                     ValuePairs::Types(exp_found) => {
@@ -1417,9 +1421,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
                         )
                         .report(diag);
 
-                        (is_simple_err, Some(exp_found))
+                        (is_simple_err, Mismatch::Variable(exp_found))
                     }
-                    _ => (false, None),
+                    ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
+                    _ => (false, Mismatch::Fixed("type")),
                 };
                 let vals = match self.values_str(&values) {
                     Some((expected, found)) => Some((expected, found)),
@@ -1445,8 +1450,18 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
             }
         };
         if let Some((expected, found)) = expected_found {
-            let expected_label = exp_found.map_or("type".into(), |ef| ef.expected.prefix_string());
-            let found_label = exp_found.map_or("type".into(), |ef| ef.found.prefix_string());
+            let expected_label = match exp_found {
+                Mismatch::Variable(ef) => ef.expected.prefix_string(),
+                Mismatch::Fixed(s) => s.into(),
+            };
+            let found_label = match exp_found {
+                Mismatch::Variable(ef) => ef.found.prefix_string(),
+                Mismatch::Fixed(s) => s.into(),
+            };
+            let exp_found = match exp_found {
+                Mismatch::Variable(exp_found) => Some(exp_found),
+                Mismatch::Fixed(_) => None,
+            };
             match (&terr, expected == found) {
                 (TypeError::Sorts(values), extra) => {
                     let sort_string = |ty: Ty<'tcx>| match (extra, &ty.kind) {
@@ -1499,6 +1514,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
                 }
             }
         }
+        let exp_found = match exp_found {
+            Mismatch::Variable(exp_found) => Some(exp_found),
+            Mismatch::Fixed(_) => None,
+        };
         if let Some(exp_found) = exp_found {
             self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
         }
@@ -2010,7 +2029,7 @@ fn report_inference_failure(
             infer::MiscVariable(_) => String::new(),
             infer::PatternRegion(_) => " for pattern".to_string(),
             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
-            infer::Autoref(_) => " for autoref".to_string(),
+            infer::Autoref(_, _) => " for autoref".to_string(),
             infer::Coercion(_) => " for automatic coercion".to_string(),
             infer::LateBoundRegion(_, br, infer::FnCall) => {
                 format!(" for lifetime parameter {}in function call", br_string(br))
index b6e971feb0e5fdc4043f45411baa2264ea13cc19..4fa6d9d2394242cb56b69ad0ad19f5b3e4b4e745 100644 (file)
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use rustc_errors::{struct_span_err, Applicability, ErrorReported};
-use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
-use rustc_middle::ty::RegionKind;
+use crate::infer::{SubregionOrigin, TypeTrace};
+use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
+use rustc_hir::{
+    self as hir, GenericBound, ImplItem, Item, ItemKind, Lifetime, LifetimeName, Node, TraitItem,
+    TyKind,
+};
+use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
+use rustc_span::symbol::Ident;
+use rustc_span::{MultiSpan, Span};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
-    /// Print the error message for lifetime errors when the return type is a static impl Trait.
+    /// Print the error message for lifetime errors when the return type is a static `impl Trait`,
+    /// `dyn Trait` or if a method call on a trait object introduces a static requirement.
     pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
         debug!("try_report_static_impl_trait(error={:?})", self.error);
-        if let Some(RegionResolutionError::SubSupConflict(
-            _,
-            var_origin,
-            ref sub_origin,
-            sub_r,
-            ref sup_origin,
-            sup_r,
-        )) = self.error
-        {
-            debug!(
-                "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
-                var_origin, sub_origin, sub_r, sup_origin, sup_r
-            );
-            let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
-            debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
-            let fn_returns = self.tcx().return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
-            if fn_returns.is_empty() {
+        let tcx = self.tcx();
+        let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
+            RegionResolutionError::SubSupConflict(
+                _,
+                var_origin,
+                sub_origin,
+                sub_r,
+                sup_origin,
+                sup_r,
+            ) if **sub_r == RegionKind::ReStatic => {
+                (var_origin, sub_origin, sub_r, sup_origin, sup_r)
+            }
+            RegionResolutionError::ConcreteFailure(
+                SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
+                sub_r,
+                sup_r,
+            ) if **sub_r == RegionKind::ReStatic => {
+                // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`.
+                if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
+                    let param = self.find_param_with_region(sup_r, sub_r)?;
+                    let lifetime = if sup_r.has_name() {
+                        format!("lifetime `{}`", sup_r)
+                    } else {
+                        "an anonymous lifetime `'_`".to_string()
+                    };
+                    let mut err = struct_span_err!(
+                        tcx.sess,
+                        cause.span,
+                        E0772,
+                        "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
+                         requirement",
+                        param
+                            .param
+                            .pat
+                            .simple_ident()
+                            .map(|s| format!("`{}`", s))
+                            .unwrap_or_else(|| "`fn` parameter".to_string()),
+                        lifetime,
+                        ctxt.assoc_item.ident,
+                    );
+                    err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
+                    err.span_label(
+                        cause.span,
+                        &format!(
+                            "...is captured and required to live as long as `'static` here \
+                             because of an implicit lifetime bound on the {}",
+                            match ctxt.assoc_item.container {
+                                AssocItemContainer::TraitContainer(id) =>
+                                    format!("`impl` of `{}`", tcx.def_path_str(id)),
+                                AssocItemContainer::ImplContainer(_) =>
+                                    "inherent `impl`".to_string(),
+                            },
+                        ),
+                    );
+                    if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
+                        err.emit();
+                        return Some(ErrorReported);
+                    } else {
+                        err.cancel();
+                    }
+                }
                 return None;
             }
-            debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
-            if *sub_r == RegionKind::ReStatic {
-                let sp = var_origin.span();
-                let return_sp = sub_origin.span();
-                let param_info = self.find_param_with_region(sup_r, sub_r)?;
-                let (lifetime_name, lifetime) = if sup_r.has_name() {
-                    (sup_r.to_string(), format!("lifetime `{}`", sup_r))
-                } else {
-                    ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
-                };
-                let mut err = struct_span_err!(
-                    self.tcx().sess,
-                    sp,
-                    E0759,
-                    "cannot infer an appropriate lifetime"
-                );
+            _ => return None,
+        };
+        debug!(
+            "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
+            var_origin, sub_origin, sub_r, sup_origin, sup_r
+        );
+        let anon_reg_sup = tcx.is_suitable_region(sup_r)?;
+        debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
+        let sp = var_origin.span();
+        let return_sp = sub_origin.span();
+        let param = self.find_param_with_region(sup_r, sub_r)?;
+        let (lifetime_name, lifetime) = if sup_r.has_name() {
+            (sup_r.to_string(), format!("lifetime `{}`", sup_r))
+        } else {
+            ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
+        };
+        let param_name = param
+            .param
+            .pat
+            .simple_ident()
+            .map(|s| format!("`{}`", s))
+            .unwrap_or_else(|| "`fn` parameter".to_string());
+        let mut err = struct_span_err!(
+            tcx.sess,
+            sp,
+            E0759,
+            "{} has {} but it needs to satisfy a `'static` lifetime requirement",
+            param_name,
+            lifetime,
+        );
+        err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
+        debug!("try_report_static_impl_trait: param_info={:?}", param);
+
+        // We try to make the output have fewer overlapping spans if possible.
+        if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
+            && sup_origin.span() != return_sp
+        {
+            // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
+
+            // Customize the spans and labels depending on their relative order so
+            // that split sentences flow correctly.
+            if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
+                // Avoid the following:
+                //
+                // error: cannot infer an appropriate lifetime
+                //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+                //    |
+                // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+                //    |           ----                      ---------^-
+                //
+                // and instead show:
+                //
+                // error: cannot infer an appropriate lifetime
+                //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+                //    |
+                // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+                //    |           ----                               ^
                 err.span_label(
-                    param_info.param_ty_span,
-                    &format!("this data with {}...", lifetime),
+                    sup_origin.span(),
+                    "...is captured here, requiring it to live as long as `'static`",
                 );
-                debug!("try_report_static_impl_trait: param_info={:?}", param_info);
+            } else {
+                err.span_label(sup_origin.span(), "...is captured here...");
+                if return_sp < sup_origin.span() {
+                    err.span_note(
+                        return_sp,
+                        "...and is required to live as long as `'static` here",
+                    );
+                } else {
+                    err.span_label(
+                        return_sp,
+                        "...and is required to live as long as `'static` here",
+                    );
+                }
+            }
+        } else {
+            err.span_label(
+                return_sp,
+                "...is captured and required to live as long as `'static` here",
+            );
+        }
+
+        let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
 
-                // We try to make the output have fewer overlapping spans if possible.
-                if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
-                    && sup_origin.span() != return_sp
+        let mut override_error_code = None;
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
+            if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code {
+                // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
+                // `'static` lifetime when called as a method on a binding: `bar.qux()`.
+                if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
+                    override_error_code = Some(ctxt.assoc_item.ident);
+                }
+            }
+        }
+        if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
+            if let ObligationCauseCode::ItemObligation(item_def_id) = cause.code {
+                // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
+                // lifetime as above, but called using a fully-qualified path to the method:
+                // `Foo::qux(bar)`.
+                let mut v = TraitObjectVisitor(vec![]);
+                v.visit_ty(param.param_ty);
+                if let Some((ident, self_ty)) =
+                    self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0[..])
                 {
-                    // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
-
-                    // Customize the spans and labels depending on their relative order so
-                    // that split sentences flow correctly.
-                    if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
-                        // Avoid the following:
-                        //
-                        // error: cannot infer an appropriate lifetime
-                        //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
-                        //    |
-                        // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-                        //    |           ----                      ---------^-
-                        //
-                        // and instead show:
-                        //
-                        // error: cannot infer an appropriate lifetime
-                        //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
-                        //    |
-                        // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-                        //    |           ----                               ^
-                        err.span_label(
-                            sup_origin.span(),
-                            "...is captured here, requiring it to live as long as `'static`",
+                    if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0[..], ident, self_ty)
+                    {
+                        override_error_code = Some(ident);
+                    }
+                }
+            }
+        }
+        if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
+            // Provide a more targetted error code and description.
+            err.code(rustc_errors::error_code!(E0772));
+            err.set_primary_message(&format!(
+                "{} has {} but calling `{}` introduces an implicit `'static` lifetime \
+                requirement",
+                param_name, lifetime, ident,
+            ));
+        }
+
+        debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
+        // FIXME: account for the need of parens in `&(dyn Trait + '_)`
+        let consider = "consider changing the";
+        let declare = "to declare that the";
+        let arg = match param.param.pat.simple_ident() {
+            Some(simple_ident) => format!("argument `{}`", simple_ident),
+            None => "the argument".to_string(),
+        };
+        let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
+        let explicit_static = format!("explicit `'static` bound to the lifetime of {}", arg);
+        let captures = format!("captures data from {}", arg);
+        let add_static_bound = "alternatively, add an explicit `'static` bound to this reference";
+        let plus_lt = format!(" + {}", lifetime_name);
+        for fn_return in fn_returns {
+            if fn_return.span.desugaring_kind().is_some() {
+                // Skip `async` desugaring `impl Future`.
+                continue;
+            }
+            match fn_return.kind {
+                TyKind::OpaqueDef(item_id, _) => {
+                    let item = tcx.hir().item(item_id.id);
+                    let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
+                        opaque
+                    } else {
+                        err.emit();
+                        return Some(ErrorReported);
+                    };
+
+                    if let Some(span) = opaque
+                        .bounds
+                        .iter()
+                        .filter_map(|arg| match arg {
+                            GenericBound::Outlives(Lifetime {
+                                name: LifetimeName::Static,
+                                span,
+                                ..
+                            }) => Some(*span),
+                            _ => None,
+                        })
+                        .next()
+                    {
+                        err.span_suggestion_verbose(
+                            span,
+                            &format!("{} `impl Trait`'s {}", consider, explicit_static),
+                            lifetime_name.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.span_suggestion_verbose(
+                            param.param_ty_span,
+                            add_static_bound,
+                            param.param_ty.to_string(),
+                            Applicability::MaybeIncorrect,
                         );
+                    } else if let Some(_) = opaque
+                        .bounds
+                        .iter()
+                        .filter_map(|arg| match arg {
+                            GenericBound::Outlives(Lifetime { name, span, .. })
+                                if name.ident().to_string() == lifetime_name =>
+                            {
+                                Some(*span)
+                            }
+                            _ => None,
+                        })
+                        .next()
+                    {
                     } else {
-                        err.span_label(sup_origin.span(), "...is captured here...");
-                        if return_sp < sup_origin.span() {
-                            err.span_note(
-                                return_sp,
-                                "...and is required to live as long as `'static` here",
-                            );
-                        } else {
-                            err.span_label(
-                                return_sp,
-                                "...and is required to live as long as `'static` here",
-                            );
-                        }
+                        err.span_suggestion_verbose(
+                            fn_return.span.shrink_to_hi(),
+                            &format!(
+                                "{declare} `impl Trait` {captures}, {explicit}",
+                                declare = declare,
+                                captures = captures,
+                                explicit = explicit,
+                            ),
+                            plus_lt.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
                     }
-                } else {
-                    err.span_label(
-                        return_sp,
-                        "...is captured and required to live as long as `'static` here",
-                    );
                 }
+                TyKind::TraitObject(_, lt) => match lt.name {
+                    LifetimeName::ImplicitObjectLifetimeDefault => {
+                        err.span_suggestion_verbose(
+                            fn_return.span.shrink_to_hi(),
+                            &format!(
+                                "{declare} trait object {captures}, {explicit}",
+                                declare = declare,
+                                captures = captures,
+                                explicit = explicit,
+                            ),
+                            plus_lt.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    name if name.ident().to_string() != lifetime_name => {
+                        // With this check we avoid suggesting redundant bounds. This
+                        // would happen if there are nested impl/dyn traits and only
+                        // one of them has the bound we'd suggest already there, like
+                        // in `impl Foo<X = dyn Bar> + '_`.
+                        err.span_suggestion_verbose(
+                            lt.span,
+                            &format!("{} trait object's {}", consider, explicit_static),
+                            lifetime_name.clone(),
+                            Applicability::MaybeIncorrect,
+                        );
+                        err.span_suggestion_verbose(
+                            param.param_ty_span,
+                            add_static_bound,
+                            param.param_ty.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    _ => {}
+                },
+                _ => {}
+            }
+        }
+        err.emit();
+        Some(ErrorReported)
+    }
 
-                // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-                let consider = "consider changing the";
-                let declare = "to declare that the";
-                let arg = match param_info.param.pat.simple_ident() {
-                    Some(simple_ident) => format!("argument `{}`", simple_ident),
-                    None => "the argument".to_string(),
-                };
-                let explicit =
-                    format!("you can add an explicit `{}` lifetime bound", lifetime_name);
-                let explicit_static =
-                    format!("explicit `'static` bound to the lifetime of {}", arg);
-                let captures = format!("captures data from {}", arg);
-                let add_static_bound =
-                    "alternatively, add an explicit `'static` bound to this reference";
-                let plus_lt = format!(" + {}", lifetime_name);
-                for fn_return in fn_returns {
-                    if fn_return.span.desugaring_kind().is_some() {
-                        // Skip `async` desugaring `impl Future`.
-                        continue;
+    fn get_impl_ident_and_self_ty_from_trait(
+        &self,
+        def_id: DefId,
+        trait_objects: &[DefId],
+    ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
+        let tcx = self.tcx();
+        match tcx.hir().get_if_local(def_id) {
+            Some(Node::ImplItem(ImplItem { ident, hir_id, .. })) => {
+                match tcx.hir().find(tcx.hir().get_parent_item(*hir_id)) {
+                    Some(Node::Item(Item { kind: ItemKind::Impl { self_ty, .. }, .. })) => {
+                        Some((*ident, self_ty))
                     }
-                    match fn_return.kind {
-                        TyKind::OpaqueDef(item_id, _) => {
-                            let item = self.tcx().hir().item(item_id.id);
-                            let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
-                                opaque
-                            } else {
-                                err.emit();
-                                return Some(ErrorReported);
-                            };
-
-                            if let Some(span) = opaque
-                                .bounds
-                                .iter()
-                                .filter_map(|arg| match arg {
-                                    GenericBound::Outlives(Lifetime {
-                                        name: LifetimeName::Static,
-                                        span,
+                    _ => None,
+                }
+            }
+            Some(Node::TraitItem(TraitItem { ident, hir_id, .. })) => {
+                let parent_id = tcx.hir().get_parent_item(*hir_id);
+                match tcx.hir().find(parent_id) {
+                    Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
+                        // The method being called is defined in the `trait`, but the `'static`
+                        // obligation comes from the `impl`. Find that `impl` so that we can point
+                        // at it in the suggestion.
+                        let trait_did = tcx.hir().local_def_id(parent_id).to_def_id();
+                        match tcx
+                            .hir()
+                            .trait_impls(trait_did)
+                            .iter()
+                            .filter_map(|impl_node| {
+                                let impl_did = tcx.hir().local_def_id(*impl_node);
+                                match tcx.hir().get_if_local(impl_did.to_def_id()) {
+                                    Some(Node::Item(Item {
+                                        kind: ItemKind::Impl { self_ty, .. },
                                         ..
-                                    }) => Some(*span),
-                                    _ => None,
-                                })
-                                .next()
-                            {
-                                err.span_suggestion_verbose(
-                                    span,
-                                    &format!("{} `impl Trait`'s {}", consider, explicit_static),
-                                    lifetime_name.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                err.span_suggestion_verbose(
-                                    param_info.param_ty_span,
-                                    add_static_bound,
-                                    param_info.param_ty.to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else if let Some(_) = opaque
-                                .bounds
-                                .iter()
-                                .filter_map(|arg| match arg {
-                                    GenericBound::Outlives(Lifetime { name, span, .. })
-                                        if name.ident().to_string() == lifetime_name =>
+                                    })) if trait_objects.iter().all(|did| {
+                                        // FIXME: we should check `self_ty` against the receiver
+                                        // type in the `UnifyReceiver` context, but for now, use
+                                        // this imperfect proxy. This will fail if there are
+                                        // multiple `impl`s for the same trait like
+                                        // `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
+                                        // In that case, only the first one will get suggestions.
+                                        let mut hir_v = HirTraitObjectVisitor(vec![], *did);
+                                        hir_v.visit_ty(self_ty);
+                                        !hir_v.0.is_empty()
+                                    }) =>
                                     {
-                                        Some(*span)
+                                        Some(self_ty)
                                     }
                                     _ => None,
-                                })
-                                .next()
-                            {
-                            } else {
-                                err.span_suggestion_verbose(
-                                    fn_return.span.shrink_to_hi(),
-                                    &format!(
-                                        "{declare} `impl Trait` {captures}, {explicit}",
-                                        declare = declare,
-                                        captures = captures,
-                                        explicit = explicit,
-                                    ),
-                                    plus_lt.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
+                                }
+                            })
+                            .next()
+                        {
+                            Some(self_ty) => Some((*ident, self_ty)),
+                            _ => None,
                         }
-                        TyKind::TraitObject(_, lt) => match lt.name {
-                            LifetimeName::ImplicitObjectLifetimeDefault => {
-                                err.span_suggestion_verbose(
-                                    fn_return.span.shrink_to_hi(),
-                                    &format!(
-                                        "{declare} trait object {captures}, {explicit}",
-                                        declare = declare,
-                                        captures = captures,
-                                        explicit = explicit,
-                                    ),
-                                    plus_lt.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                            name if name.ident().to_string() != lifetime_name => {
-                                // With this check we avoid suggesting redundant bounds. This
-                                // would happen if there are nested impl/dyn traits and only
-                                // one of them has the bound we'd suggest already there, like
-                                // in `impl Foo<X = dyn Bar> + '_`.
-                                err.span_suggestion_verbose(
-                                    lt.span,
-                                    &format!("{} trait object's {}", consider, explicit_static),
-                                    lifetime_name.clone(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                                err.span_suggestion_verbose(
-                                    param_info.param_ty_span,
-                                    add_static_bound,
-                                    param_info.param_ty.to_string(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                            _ => {}
-                        },
-                        _ => {}
+                    }
+                    _ => None,
+                }
+            }
+            _ => None,
+        }
+    }
+
+    /// When we call a method coming from an `impl Foo for dyn Bar`, `dyn Bar` introduces a default
+    /// `'static` obligation. Suggest relaxing that implicit bound.
+    fn find_impl_on_dyn_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        ty: Ty<'_>,
+        ctxt: &UnifyReceiverContext<'tcx>,
+    ) -> bool {
+        let tcx = self.tcx();
+
+        // Find the method being called.
+        let instance = match ty::Instance::resolve(
+            tcx,
+            ctxt.param_env,
+            ctxt.assoc_item.def_id,
+            self.infcx.resolve_vars_if_possible(&ctxt.substs),
+        ) {
+            Ok(Some(instance)) => instance,
+            _ => return false,
+        };
+
+        let mut v = TraitObjectVisitor(vec![]);
+        v.visit_ty(ty);
+
+        // Get the `Ident` of the method being called and the corresponding `impl` (to point at
+        // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
+        let (ident, self_ty) =
+            match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0[..]) {
+                Some((ident, self_ty)) => (ident, self_ty),
+                None => return false,
+            };
+
+        // Find the trait object types in the argument, so we point at *only* the trait object.
+        self.suggest_constrain_dyn_trait_in_impl(err, &v.0[..], ident, self_ty)
+    }
+
+    fn suggest_constrain_dyn_trait_in_impl(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        found_dids: &[DefId],
+        ident: Ident,
+        self_ty: &hir::Ty<'_>,
+    ) -> bool {
+        let mut suggested = false;
+        for found_did in found_dids {
+            let mut hir_v = HirTraitObjectVisitor(vec![], *found_did);
+            hir_v.visit_ty(&self_ty);
+            for span in &hir_v.0 {
+                let mut multi_span: MultiSpan = vec![*span].into();
+                multi_span.push_span_label(
+                    *span,
+                    "this has an implicit `'static` lifetime requirement".to_string(),
+                );
+                multi_span.push_span_label(
+                    ident.span,
+                    "calling this method introduces the `impl`'s 'static` requirement".to_string(),
+                );
+                err.span_note(multi_span, "the used `impl` has a `'static` requirement");
+                err.span_suggestion_verbose(
+                    span.shrink_to_hi(),
+                    "consider relaxing the implicit `'static` requirement",
+                    " + '_".to_string(),
+                    Applicability::MaybeIncorrect,
+                );
+                suggested = true;
+            }
+        }
+        suggested
+    }
+}
+
+/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
+struct TraitObjectVisitor(Vec<DefId>);
+
+impl TypeVisitor<'_> for TraitObjectVisitor {
+    fn visit_ty(&mut self, t: Ty<'_>) -> bool {
+        match t.kind {
+            ty::Dynamic(preds, RegionKind::ReStatic) => {
+                if let Some(def_id) = preds.principal_def_id() {
+                    self.0.push(def_id);
+                }
+                false
+            }
+            _ => t.super_visit_with(self),
+        }
+    }
+}
+
+/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
+struct HirTraitObjectVisitor(Vec<Span>, DefId);
+
+impl<'tcx> Visitor<'tcx> for HirTraitObjectVisitor {
+    type Map = ErasedMap<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
+        match t.kind {
+            TyKind::TraitObject(
+                poly_trait_refs,
+                Lifetime { name: LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            ) => {
+                for ptr in poly_trait_refs {
+                    if Some(self.1) == ptr.trait_ref.trait_def_id() {
+                        self.0.push(ptr.span);
                     }
                 }
-                err.emit();
-                return Some(ErrorReported);
             }
+            _ => {}
         }
-        None
+        walk_ty(self, t);
     }
 }
index fa999abb1a86c46b672c88b81b49d1efc36f5fea..28e9dd90cfd674531eafece5122db6f3410fa2f5 100644 (file)
@@ -7,20 +7,18 @@
 use rustc_middle::ty::{self, DefIdTree, Region, Ty};
 use rustc_span::Span;
 
-// The struct contains the information about the anonymous region
-// we are searching for.
+/// Information about the anonymous region we are searching for.
 #[derive(Debug)]
 pub(super) struct AnonymousParamInfo<'tcx> {
-    // the parameter corresponding to the anonymous region
+    /// The parameter corresponding to the anonymous region.
     pub param: &'tcx hir::Param<'tcx>,
-    // the type corresponding to the anonymopus region parameter
+    /// The type corresponding to the anonymous region parameter.
     pub param_ty: Ty<'tcx>,
-    // the ty::BoundRegion corresponding to the anonymous region
+    /// The ty::BoundRegion corresponding to the anonymous region.
     pub bound_region: ty::BoundRegion,
-    // param_ty_span contains span of parameter type
+    /// The `Span` of the parameter type.
     pub param_ty_span: Span,
-    // corresponds to id the argument is the first parameter
-    // in the declaration
+    /// Signals that the argument is the first parameter in the declaration.
     pub is_first: bool,
 }
 
index 37883fcb07468e7256f7e50b7fe2b671695860e2..3744ad5d0324a59ebd145ae16ca0537210feb11d 100644 (file)
@@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
     AddrOfRegion(Span),
 
     /// Regions created as part of an autoref of a method receiver
-    Autoref(Span),
+    Autoref(Span, ty::AssocItem),
 
     /// Regions created as part of an automatic coercion
     Coercion(Span),
@@ -1800,15 +1800,15 @@ pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default:
 impl RegionVariableOrigin {
     pub fn span(&self) -> Span {
         match *self {
-            MiscVariable(a) => a,
-            PatternRegion(a) => a,
-            AddrOfRegion(a) => a,
-            Autoref(a) => a,
-            Coercion(a) => a,
-            EarlyBoundRegion(a, ..) => a,
-            LateBoundRegion(a, ..) => a,
+            MiscVariable(a)
+            | PatternRegion(a)
+            | AddrOfRegion(a)
+            | Autoref(a, _)
+            | Coercion(a)
+            | EarlyBoundRegion(a, ..)
+            | LateBoundRegion(a, ..)
+            | UpvarRegion(_, a) => a,
             BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
-            UpvarRegion(_, a) => a,
             NLL(..) => bug!("NLL variable used with `span`"),
         }
     }
index 0cd6585163c4e9ce2a6df197881ded29be98563e..bacb7fa153e43b1a0cca8d8f5272ec5c71d749f5 100644 (file)
@@ -13,6 +13,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
+#![feature(bindings_after_at)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/src/librustc_interface/build.rs b/src/librustc_interface/build.rs
deleted file mode 100644 (file)
index 79a343e..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=RUSTC_INSTALL_BINDIR");
-}
index 3c549b88523684fa812623d87bfb0aa48fdd9614..22197a66530ddddb7d1eaba67444109707e5ba2f 100644 (file)
@@ -420,6 +420,7 @@ macro_rules! tracked {
     // Make sure that changing a [TRACKED] option changes the hash.
     // This list is in alphabetical order.
     tracked!(code_model, Some(CodeModel::Large));
+    tracked!(control_flow_guard, CFGuard::Checks);
     tracked!(debug_assertions, Some(true));
     tracked!(debuginfo, 0xdeadbeef);
     tracked!(embed_bitcode, false);
@@ -537,7 +538,6 @@ macro_rules! tracked {
     tracked!(binary_dep_depinfo, true);
     tracked!(chalk, true);
     tracked!(codegen_backend, Some("abc".to_string()));
-    tracked!(control_flow_guard, CFGuard::Checks);
     tracked!(crate_attr, vec!["abc".to_string()]);
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
index 4fc02e348f64637a61aeff09833cd5a561fa9fef..9f2711eec10acb26b7d1e004bbb103e034daa6c9 100644 (file)
@@ -2,7 +2,6 @@
 authors = ["The Rust Project Developers"]
 name = "rustc_llvm"
 version = "0.0.0"
-build = "build.rs"
 edition = "2018"
 
 [lib]
@@ -14,8 +13,8 @@ static-libstdcpp = []
 emscripten = []
 
 [dependencies]
-libc = "0.2"
+libc = "0.2.73"
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0.1"
+cc = "1.0.58"
index 78e27b10ec657e35f83d37d51256f567aa0d5986..21b8080714c1744ca54130adbb6325ece0082bff 100644 (file)
@@ -2,12 +2,12 @@
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use build_helper::output;
+use build_helper::{output, tracked_env_var_os};
 
 fn detect_llvm_link() -> (&'static str, &'static str) {
     // Force the link mode we want, preferring static by default, but
     // possibly overridden by `configure --enable-llvm-link-shared`.
-    if env::var_os("LLVM_LINK_SHARED").is_some() {
+    if tracked_env_var_os("LLVM_LINK_SHARED").is_some() {
         ("dylib", "--link-shared")
     } else {
         ("static", "--link-static")
@@ -15,8 +15,7 @@ fn detect_llvm_link() -> (&'static str, &'static str) {
 }
 
 fn main() {
-    println!("cargo:rerun-if-env-changed=RUST_CHECK");
-    if env::var_os("RUST_CHECK").is_some() {
+    if tracked_env_var_os("RUST_CHECK").is_some() {
         // If we're just running `check`, there's no need for LLVM to be built.
         return;
     }
@@ -25,8 +24,8 @@ fn main() {
 
     let target = env::var("TARGET").expect("TARGET was not set");
     let llvm_config =
-        env::var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| {
-            if let Some(dir) = env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
+        tracked_env_var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| {
+            if let Some(dir) = tracked_env_var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
                 let to_test = dir
                     .parent()
                     .unwrap()
@@ -46,8 +45,6 @@ fn main() {
     }
     let llvm_config = llvm_config.unwrap_or_else(|| PathBuf::from("llvm-config"));
 
-    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
-
     // Test whether we're cross-compiling LLVM. This is a pretty rare case
     // currently where we're producing an LLVM for a different platform than
     // what this build script is currently running on.
@@ -163,12 +160,11 @@ fn main() {
         cfg.define(&flag, None);
     }
 
-    println!("cargo:rerun-if-changed-env=LLVM_RUSTLLVM");
-    if env::var_os("LLVM_RUSTLLVM").is_some() {
+    if tracked_env_var_os("LLVM_RUSTLLVM").is_some() {
         cfg.define("LLVM_RUSTLLVM", None);
     }
 
-    if env::var_os("LLVM_NDEBUG").is_some() {
+    if tracked_env_var_os("LLVM_NDEBUG").is_some() {
         cfg.define("NDEBUG", None);
         cfg.debug(false);
     }
@@ -255,7 +251,7 @@ fn main() {
     // librustc_llvm, for example when using static libc++, we may need to
     // manually specify the library search path and -ldl -lpthread as link
     // dependencies.
-    let llvm_linker_flags = env::var_os("LLVM_LINKER_FLAGS");
+    let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS");
     if let Some(s) = llvm_linker_flags {
         for lib in s.into_string().unwrap().split_whitespace() {
             if lib.starts_with("-l") {
@@ -266,8 +262,8 @@ fn main() {
         }
     }
 
-    let llvm_static_stdcpp = env::var_os("LLVM_STATIC_STDCPP");
-    let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX");
+    let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP");
+    let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX");
 
     let stdcppname = if target.contains("openbsd") {
         if target.contains("sparc64") { "estdc++" } else { "c++" }
diff --git a/src/librustc_metadata/build.rs b/src/librustc_metadata/build.rs
deleted file mode 100644 (file)
index 7d5c58e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_VERSION");
-    println!("cargo:rerun-if-env-changed=CFG_VIRTUAL_RUST_SOURCE_BASE_DIR");
-}
index 0d2101cb2cb0821f5bec673e3580f00f6291f4b1..724b4123fab6c9243857d92b2733ee52e5547b9f 100644 (file)
@@ -307,11 +307,16 @@ fn register_crate(
         let private_dep =
             self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false);
 
-        info!("register crate `{}` (private_dep = {})", crate_root.name(), private_dep);
-
         // Claim this crate number and cache it
         let cnum = self.cstore.alloc_new_crate_num();
 
+        info!(
+            "register crate `{}` (cnum = {}. private_dep = {})",
+            crate_root.name(),
+            cnum,
+            private_dep
+        );
+
         // Maintain a reference to the top most crate.
         // Stash paths for top-most crate locally if necessary.
         let crate_paths;
@@ -339,22 +344,21 @@ fn register_crate(
             None
         };
 
-        self.cstore.set_crate_data(
+        let crate_metadata = CrateMetadata::new(
+            self.sess,
+            metadata,
+            crate_root,
+            raw_proc_macros,
             cnum,
-            CrateMetadata::new(
-                self.sess,
-                metadata,
-                crate_root,
-                raw_proc_macros,
-                cnum,
-                cnum_map,
-                dep_kind,
-                source,
-                private_dep,
-                host_hash,
-            ),
+            cnum_map,
+            dep_kind,
+            source,
+            private_dep,
+            host_hash,
         );
 
+        self.cstore.set_crate_data(cnum, crate_metadata);
+
         Ok(cnum)
     }
 
@@ -569,6 +573,8 @@ fn resolve_crate_deps(
             let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?;
             crate_num_map.push(cnum);
         }
+
+        debug!("resolve_crate_deps: cnum_map for {:?} is {:?}", krate, crate_num_map);
         Ok(crate_num_map)
     }
 
index 76e39a476c6d89f73507f29525a488c62a8e5e67..d4add2ab7ade0898ab5f086f57c9c3f65849049d 100644 (file)
@@ -9,6 +9,7 @@
 #![feature(proc_macro_internals)]
 #![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
+#![feature(never_type)]
 #![recursion_limit = "256"]
 
 extern crate proc_macro;
index 4746e53ce59a92d332b6d081423ead4462117675..df4bb2502cbebcaaef99932e391d0185ec297fdd 100644 (file)
 use rustc_middle::util::common::record_time;
 use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
 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, Pos, Span, DUMMY_SP};
+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;
 
 pub use cstore_impl::{provide, provide_extern};
+use rustc_span::hygiene::HygieneDecodeContext;
 
 mod cstore_impl;
 
     /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
     host_hash: Option<Svh>,
 
+    /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext`
+    /// and `ExpnId`).
+    /// Note that we store a `HygieneDecodeContext` for each `CrateMetadat`. This is
+    /// because `SyntaxContext` ids are not globally unique, so we need
+    /// to track which ids we've decoded on a per-crate basis.
+    hygiene_context: HygieneDecodeContext,
+
     // --- Data used only for improving diagnostics ---
     /// Information about the `extern crate` item or path that caused this crate to be loaded.
     /// If this is `None`, then the crate was injected (e.g., by the allocator).
@@ -411,6 +421,7 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
 
         let lo = BytePos::decode(self)?;
         let len = BytePos::decode(self)?;
+        let ctxt = SyntaxContext::decode(self)?;
         let hi = lo + len;
 
         let sess = if let Some(sess) = self.sess {
@@ -524,7 +535,7 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         let hi =
             (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
 
-        Ok(Span::with_root_ctxt(lo, hi))
+        Ok(Span::new(lo, hi, ctxt))
     }
 }
 
@@ -1120,6 +1131,14 @@ fn is_item_mir_available(&self, id: DefIndex) -> bool {
         !self.is_proc_macro(id) && self.root.tables.mir.get(self, id).is_some()
     }
 
+    fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId {
+        if let EntryKind::Mod(m) = self.kind(id) {
+            m.decode((self, sess)).expansion
+        } else {
+            panic!("Expected module, found {:?}", self.local_def_id(id))
+        }
+    }
+
     fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
         self.root
             .tables
@@ -1132,6 +1151,16 @@ fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
             .decode((self, tcx))
     }
 
+    fn get_unused_generic_params(&self, id: DefIndex) -> FiniteBitSet<u64> {
+        self.root
+            .tables
+            .unused_generic_params
+            .get(self, id)
+            .filter(|_| !self.is_proc_macro(id))
+            .map(|params| params.decode(self))
+            .unwrap_or_default()
+    }
+
     fn get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec<Promoted, Body<'tcx>> {
         self.root
             .tables
@@ -1642,6 +1671,7 @@ impl CrateMetadata {
             private_dep,
             host_hash,
             extern_crate: Lock::new(None),
+            hygiene_context: Default::default(),
         }
     }
 
@@ -1774,3 +1804,57 @@ 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 be153758a2a0c0d0e76e2a1bb676148ef7388d2d..e51862be9a86fde19f8bf13abde658cf4de8e5a2 100644 (file)
 use rustc_session::utils::NativeLibKind;
 use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::{self, Span, Spanned};
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::Symbol;
 
 use rustc_data_structures::sync::Lrc;
+use rustc_span::ExpnId;
 use smallvec::SmallVec;
 use std::any::Any;
 
@@ -113,6 +114,7 @@ fn into_args(self) -> (DefId, DefId) {
     }
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
+    unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
@@ -416,13 +418,7 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
             attr::mark_used(attr);
         }
 
-        let ident = data
-            .def_key(id.index)
-            .disambiguated_data
-            .data
-            .get_opt_name()
-            .map(Ident::with_dummy_span) // FIXME: cross-crate hygiene
-            .expect("no name in load_macro");
+        let ident = data.item_ident(id.index, sess);
 
         LoadedMacro::MacroDef(
             ast::Item {
@@ -453,6 +449,10 @@ pub fn get_span_untracked(&self, def_id: DefId, sess: &Session) -> Span {
     pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
         self.get_crate_data(def_id.krate).get_generics(def_id.index, sess).own_counts().lifetimes
     }
+
+    pub fn module_expansion_untracked(&self, def_id: DefId, sess: &Session) -> ExpnId {
+        self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess)
+    }
 }
 
 impl CrateStore for CStore {
index a8c46d3e32e6a7fedc2ed9dd11a5bd03b00641f7..dc8d14a44f806ee06ff01cc92a46d9a8d3a4d9ea 100644 (file)
@@ -1,4 +1,4 @@
-use crate::rmeta::table::FixedSizeEncoding;
+use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
 use crate::rmeta::*;
 
 use log::{debug, trace};
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
 use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
 use rustc_session::config::CrateType;
+use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use rustc_target::abi::VariantIdx;
 use std::hash::Hash;
 use std::num::NonZeroUsize;
 use std::path::Path;
 
-struct EncodeContext<'tcx> {
+struct EncodeContext<'a, 'tcx> {
     opaque: opaque::Encoder,
     tcx: TyCtxt<'tcx>,
 
@@ -66,6 +67,7 @@ struct EncodeContext<'tcx> {
     // with a result containing a foreign `Span`.
     required_source_files: Option<GrowableBitSet<usize>>,
     is_proc_macro: bool,
+    hygiene_ctxt: &'a HygieneEncodeContext,
 }
 
 macro_rules! encoder_methods {
@@ -76,7 +78,7 @@ macro_rules! encoder_methods {
     }
 }
 
-impl<'tcx> Encoder for EncodeContext<'tcx> {
+impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
     type Error = <opaque::Encoder as Encoder>::Error;
 
     #[inline]
@@ -107,13 +109,13 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> {
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
+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<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
+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 {
@@ -123,7 +125,7 @@ fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
     }
 }
 
-impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
+impl<'a, 'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'a, 'tcx>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -133,14 +135,14 @@ fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::E
     }
 }
 
-impl<'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'tcx> {
+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())
     }
 }
 
-impl<'tcx> SpecializedEncoder<DefId> for EncodeContext<'tcx> {
+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;
@@ -150,14 +152,31 @@ fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
     }
 }
 
-impl<'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'tcx> {
+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> SpecializedEncoder<ExpnId> for EncodeContext<'a, 'tcx> {
+    fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+        rustc_span::hygiene::raw_encode_expn_id(
+            *expn,
+            &mut self.hygiene_ctxt,
+            ExpnDataEncodeMode::Metadata,
+            self,
+        )
+    }
+}
+
+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<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> {
+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);
@@ -234,26 +253,58 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         let len = hi - lo;
         len.encode(self)?;
 
+        // Don't serialize any `SyntaxContext`s from a proc-macro crate,
+        // since we don't load proc-macro dependencies during serialization.
+        // This means that any hygiene information from macros used *within*
+        // a proc-macro crate (e.g. invoking a macro that expands to a proc-macro
+        // definition) will be lost.
+        //
+        // This can show up in two ways:
+        //
+        // 1. Any hygiene information associated with identifier of
+        // a proc macro (e.g. `#[proc_macro] pub fn $name`) will be lost.
+        // Since proc-macros can only be invoked from a different crate,
+        // real code should never need to care about this.
+        //
+        // 2. Using `Span::def_site` or `Span::mixed_site` will not
+        // include any hygiene information associated with the defintion
+        // site. This means that a proc-macro cannot emit a `$crate`
+        // identifier which resolves to one of its dependencies,
+        // which also should never come up in practice.
+        //
+        // Additionally, this affects `Span::parent`, and any other
+        // span inspection APIs that would otherwise allow traversing
+        // the `SyntaxContexts` associated with a span.
+        //
+        // None of these user-visible effects should result in any
+        // cross-crate inconsistencies (getting one behavior in the same
+        // crate, and a different behavior in another crate) due to the
+        // limited surface that proc-macros can expose.
+        if self.is_proc_macro {
+            SyntaxContext::root().encode(self)?;
+        } else {
+            span.ctxt.encode(self)?;
+        }
+
         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)?;
         }
-        Ok(())
 
-        // Don't encode the expansion context.
+        Ok(())
     }
 }
 
-impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
+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, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
+impl<'a, 'b, 'c, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'c, 'tcx>
 where
     &'a ty::TyS<'b>: UseSpecializedEncodable,
 {
@@ -264,7 +315,7 @@ fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error
     }
 }
 
-impl<'b, 'tcx> SpecializedEncoder<ty::Predicate<'b>> for EncodeContext<'tcx> {
+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 =
@@ -275,7 +326,7 @@ fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Se
     }
 }
 
-impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
+impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
         use std::collections::hash_map::Entry;
         let index = match self.interpret_allocs.entry(*alloc_id) {
@@ -292,13 +343,13 @@ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Se
     }
 }
 
-impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
+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)
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
+impl<'a, 'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'a, 'tcx>
 where
     mir::ClearCrossCrate<T>: UseSpecializedEncodable,
 {
@@ -307,7 +358,7 @@ fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self
     }
 }
 
-impl<'tcx> TyEncoder for EncodeContext<'tcx> {
+impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
     fn position(&self) -> usize {
         self.opaque.position()
     }
@@ -315,17 +366,17 @@ fn position(&self) -> usize {
 
 /// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
 trait EncodeContentsForLazy<T: ?Sized + LazyMeta> {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> T::Meta;
+    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
 }
 
 impl<T: Encodable> EncodeContentsForLazy<T> for &T {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
+    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
         self.encode(ecx).unwrap()
     }
 }
 
 impl<T: Encodable> EncodeContentsForLazy<T> for T {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) {
+    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
         self.encode(ecx).unwrap()
     }
 }
@@ -335,7 +386,7 @@ impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
     I: IntoIterator,
     I::Item: EncodeContentsForLazy<T>,
 {
-    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize {
+    fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
         self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
     }
 }
@@ -352,7 +403,7 @@ macro_rules! record {
     }};
 }
 
-impl<'tcx> EncodeContext<'tcx> {
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     fn emit_lazy_distance<T: ?Sized + LazyMeta>(
         &mut self,
         lazy: Lazy<T>,
@@ -478,6 +529,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
 
         let mut i = self.position();
 
+        // Encode the crate deps
         let crate_deps = self.encode_crate_deps();
         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
@@ -556,12 +608,23 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
         let proc_macro_data_bytes = self.position() - i;
 
         // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
-        // this late to give the prefetching as much time as possible to complete.
+        // this as late as possible to give the prefetching as much time as possible to complete.
         i = self.position();
         let exported_symbols = tcx.exported_symbols(LOCAL_CRATE);
         let exported_symbols = self.encode_exported_symbols(&exported_symbols);
         let exported_symbols_bytes = self.position() - i;
 
+        // Encode the hygiene data,
+        // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
+        // of encoding other items (e.g. `optimized_mir`) may cause us to load
+        // data from the incremental cache. If this causes us to deserialize a `Span`,
+        // then we may load additional `SyntaxContext`s into the global `HygieneData`.
+        // Therefore, we need to encode the hygiene data last to ensure that we encode
+        // any `SyntaxContext`s that might be used.
+        i = self.position();
+        let (syntax_contexts, expn_data) = self.encode_hygiene();
+        let hygiene_bytes = self.position() - i;
+
         // Encode source_map. This needs to be done last,
         // since encoding `Span`s tells us which `SourceFiles` we actually
         // need to encode.
@@ -618,6 +681,8 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             exported_symbols,
             interpret_alloc_index,
             tables,
+            syntax_contexts,
+            expn_data,
         });
 
         let total_bytes = self.position();
@@ -643,6 +708,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
             println!("            item bytes: {}", item_bytes);
             println!("           table bytes: {}", tables_bytes);
+            println!("         hygiene bytes: {}", hygiene_bytes);
             println!("            zero bytes: {}", zero_bytes);
             println!("           total bytes: {}", total_bytes);
         }
@@ -651,7 +717,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
     }
 }
 
-impl EncodeContext<'tcx> {
+impl EncodeContext<'a, 'tcx> {
     fn encode_variances_of(&mut self, def_id: DefId) {
         debug!("EncodeContext::encode_variances_of({:?})", def_id);
         record!(self.tables.variances[def_id] <- &self.tcx.variances_of(def_id)[..]);
@@ -752,11 +818,12 @@ fn encode_info_for_mod(
         vis: &hir::Visibility<'_>,
     ) {
         let tcx = self.tcx;
-        let def_id = tcx.hir().local_def_id(id);
+        let local_def_id = tcx.hir().local_def_id(id);
+        let def_id = local_def_id.to_def_id();
         debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
-            reexports: match tcx.module_exports(def_id) {
+            reexports: match tcx.module_exports(local_def_id) {
                 Some(exports) => {
                     let hir_map = self.tcx.hir();
                     self.lazy(
@@ -767,10 +834,9 @@ fn encode_info_for_mod(
                 }
                 _ => Lazy::empty(),
             },
+            expansion: tcx.hir().definitions().expansion_that_defined(local_def_id),
         };
 
-        let def_id = def_id.to_def_id();
-
         record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data)));
         record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
         record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
@@ -1065,6 +1131,8 @@ fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
         debug!("EntryBuilder::encode_mir({:?})", def_id);
         if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) {
             record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id));
+            record!(self.tables.unused_generic_params[def_id.to_def_id()] <-
+                    self.tcx.unused_generic_params(def_id));
         }
     }
 
@@ -1423,6 +1491,25 @@ fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
         self.lazy(foreign_modules.iter().cloned())
     }
 
+    fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable) {
+        let mut syntax_contexts: TableBuilder<_, _> = Default::default();
+        let mut expn_data_table: TableBuilder<_, _> = Default::default();
+
+        let _: Result<(), !> = self.hygiene_ctxt.encode(
+            &mut (&mut *self, &mut syntax_contexts, &mut expn_data_table),
+            |(this, syntax_contexts, _), index, ctxt_data| {
+                syntax_contexts.set(index, this.lazy(ctxt_data));
+                Ok(())
+            },
+            |(this, _, expn_data_table), index, expn_data| {
+                expn_data_table.set(index, this.lazy(expn_data));
+                Ok(())
+            },
+        );
+
+        (syntax_contexts.encode(&mut self.opaque), expn_data_table.encode(&mut self.opaque))
+    }
+
     fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> {
         let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
         if is_proc_macro {
@@ -1612,7 +1699,7 @@ fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignIt
 }
 
 // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR.
-impl Visitor<'tcx> for EncodeContext<'tcx> {
+impl Visitor<'tcx> for EncodeContext<'a, 'tcx> {
     type Map = Map<'tcx>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -1650,7 +1737,7 @@ fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
     }
 }
 
-impl EncodeContext<'tcx> {
+impl EncodeContext<'a, 'tcx> {
     fn encode_fields(&mut self, adt_def: &ty::AdtDef) {
         for (variant_index, variant) in adt_def.variants.iter_enumerated() {
             for (field_index, _field) in variant.fields.iter().enumerate() {
@@ -1904,6 +1991,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
     encoder.emit_raw_bytes(&[0, 0, 0, 0]);
 
     let source_map_files = tcx.sess.source_map().files();
+    let hygiene_ctxt = HygieneEncodeContext::default();
 
     let mut ecx = EncodeContext {
         opaque: encoder,
@@ -1917,6 +2005,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
         interpret_allocs_inverse: Default::default(),
         required_source_files: Some(GrowableBitSet::with_capacity(source_map_files.len())),
         is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
+        hygiene_ctxt: &hygiene_ctxt,
     };
     drop(source_map_files);
 
index 8abc3784d6d2f003a1cab93feffbfb0a38c3d0f7..55ef66f1939c4e1a18c79db4e4cf7d24f16d6929 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, DefIndex};
 use rustc_hir::lang_items;
-use rustc_index::vec::IndexVec;
+use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
@@ -20,7 +20,7 @@
 use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, Span};
+use rustc_span::{self, ExpnData, ExpnId, Span};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use std::marker::PhantomData;
@@ -28,6 +28,7 @@
 
 pub use decoder::{provide, provide_extern};
 crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
+use rustc_span::hygiene::SyntaxContextData;
 
 mod decoder;
 mod encoder;
@@ -168,6 +169,9 @@ macro_rules! Lazy {
     ($T:ty) => {Lazy<$T, ()>};
 }
 
+type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
+type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
+
 #[derive(RustcEncodable, RustcDecodable)]
 crate struct CrateRoot<'tcx> {
     name: Symbol,
@@ -202,6 +206,10 @@ macro_rules! Lazy {
     proc_macro_data: Option<Lazy<[DefIndex]>>,
 
     exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
+
+    syntax_contexts: SyntaxContextTable,
+    expn_data: ExpnDataTable,
+
     source_map: Lazy<[rustc_span::SourceFile]>,
 
     compiler_builtins: bool,
@@ -277,6 +285,7 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     super_predicates: Table<DefIndex, Lazy!(ty::GenericPredicates<'tcx>)>,
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
+    unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u64>>>,
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
@@ -321,6 +330,7 @@ enum EntryKind {
 #[derive(RustcEncodable, RustcDecodable)]
 struct ModData {
     reexports: Lazy<[Export<hir::HirId>]>,
+    expansion: ExpnId,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
index bacb5a345fca9a7c28f39aaf92b55209856ab1b2..e1d0a0dbf2ffa2c77d37bfb554300622a7d425c7 100644 (file)
@@ -155,7 +155,7 @@ impl<I: Idx, T> TableBuilder<I, T>
 where
     Option<T>: FixedSizeEncoding,
 {
-    pub(super) fn set(&mut self, i: I, value: T) {
+    pub(crate) fn set(&mut self, i: I, value: T) {
         // FIXME(eddyb) investigate more compact encodings for sparse tables.
         // On the PR @michaelwoerister mentioned:
         // > Space requirements could perhaps be optimized by using the HAMT `popcnt`
@@ -170,7 +170,7 @@ pub(super) fn set(&mut self, i: I, value: T) {
         Some(value).write_to_bytes_at(&mut self.bytes, i);
     }
 
-    pub(super) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> {
+    pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> {
         let pos = buf.position();
         buf.emit_raw_bytes(&self.bytes);
         Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len())
diff --git a/src/librustc_middle/build.rs b/src/librustc_middle/build.rs
deleted file mode 100644 (file)
index af7723a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-use std::env;
-
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_LIBDIR_RELATIVE");
-    println!("cargo:rerun-if-env-changed=CFG_COMPILER_HOST_TRIPLE");
-    println!("cargo:rerun-if-env-changed=RUSTC_VERIFY_LLVM_IR");
-
-    if env::var_os("RUSTC_VERIFY_LLVM_IR").is_some() {
-        println!("cargo:rustc-cfg=always_verify_llvm_ir");
-    }
-}
index f5b0b73c49de1cf7230f100bfd2e3d53a377d7c5..19a7d2ec2218dd2222c574f96a57959e083b58b5 100644 (file)
@@ -14,6 +14,7 @@
 use rustc_span::symbol::Symbol;
 use rustc_span::{BytePos, CachingSourceMapView, SourceFile};
 
+use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
 use std::cmp::Ord;
 
@@ -229,6 +230,12 @@ fn hash_spans(&self) -> bool {
         self.hash_spans
     }
 
+    #[inline]
+    fn hash_crate_num(&mut self, cnum: CrateNum, hasher: &mut StableHasher) {
+        let hcx = self;
+        hcx.def_path_hash(DefId { krate: cnum, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
+    }
+
     #[inline]
     fn hash_def_id(&mut self, def_id: DefId, hasher: &mut StableHasher) {
         let hcx = self;
index 78b9167ddd9679ca96b4f9da13b4bfd28259fe37..c2d177b69b6b95409d95d90593de14b12f9a70d4 100644 (file)
@@ -147,13 +147,6 @@ fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash {
     }
 }
 
-impl<'a> HashStable<StableHashingContext<'a>> for CrateNum {
-    #[inline]
-    fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        hcx.def_path_hash(DefId { krate: *self, index: CRATE_DEF_INDEX }).hash_stable(hcx, hasher);
-    }
-}
-
 impl<'a> ToStableHashKey<StableHashingContext<'a>> for CrateNum {
     type KeyType = DefPathHash;
 
index a68301385b7a5b5a983609f57ce7d4057a438ebf..b7dccb8d8ce6d3ef3aab403891855949f17bae76 100644 (file)
@@ -27,7 +27,6 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(cmp_min_max_by)]
 #![feature(const_fn)]
 #![feature(const_panic)]
 #![feature(const_fn_transmute)]
index 3f0939239e85c1d1f2cae567c2cbed302943eeb8..25e5379881e70ad56df532f2490a61f1a028e74e 100644 (file)
@@ -346,6 +346,6 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
             // Dummy span for the `def_site` means it's an external macro.
             expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site)
         }
-        ExpnKind::Macro(..) => true, // definitely a plugin
+        ExpnKind::Macro { .. } => true, // definitely a plugin
     }
 }
index 54c05bca3bd2bbfac04dbc72c1b0e5422e55ef80..5f7ff54fd31c3ee5a3e329752aa59e6e19e96ad4 100644 (file)
@@ -5,7 +5,7 @@
 
 use crate::ty::{self, TyCtxt};
 use rustc_ast::ast::CRATE_NODE_ID;
-use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability};
+use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_feature::GateIssue;
@@ -130,14 +130,26 @@ pub fn report_unstable(
 
 /// Checks whether an item marked with `deprecated(since="X")` is currently
 /// deprecated (i.e., whether X is not greater than the current rustc version).
-pub fn deprecation_in_effect(since: &str) -> bool {
+pub fn deprecation_in_effect(is_since_rustc_version: bool, since: Option<&str>) -> bool {
+    let since = if let Some(since) = since {
+        if is_since_rustc_version {
+            since
+        } else {
+            // We assume that the deprecation is in effect if it's not a
+            // rustc version.
+            return true;
+        }
+    } else {
+        // If since attribute is not set, then we're definitely in effect.
+        return true;
+    };
     fn parse_version(ver: &str) -> Vec<u32> {
         // We ignore non-integer components of the version (e.g., "nightly").
         ver.split(|c| c == '.' || c == '-').flat_map(|s| s.parse()).collect()
     }
 
     if let Some(rustc) = option_env!("CFG_RELEASE") {
-        let since: Vec<u32> = parse_version(since);
+        let since: Vec<u32> = parse_version(&since);
         let rustc: Vec<u32> = parse_version(rustc);
         // We simply treat invalid `since` attributes as relating to a previous
         // Rust version, thus always displaying the warning.
@@ -167,31 +179,27 @@ pub fn deprecation_suggestion(
     }
 }
 
-fn deprecation_message_common(message: String, reason: Option<Symbol>) -> String {
-    match reason {
-        Some(reason) => format!("{}: {}", message, reason),
-        None => message,
-    }
-}
-
 pub fn deprecation_message(depr: &Deprecation, path: &str) -> (String, &'static Lint) {
-    let message = format!("use of deprecated item '{}'", path);
-    (deprecation_message_common(message, depr.note), DEPRECATED)
-}
-
-pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String, &'static Lint) {
-    let (message, lint) = if deprecation_in_effect(&depr.since.as_str()) {
+    let (message, lint) = if deprecation_in_effect(
+        depr.is_since_rustc_version,
+        depr.since.map(Symbol::as_str).as_deref(),
+    ) {
         (format!("use of deprecated item '{}'", path), DEPRECATED)
     } else {
         (
             format!(
                 "use of item '{}' that will be deprecated in future version {}",
-                path, depr.since
+                path,
+                depr.since.unwrap()
             ),
             DEPRECATED_IN_FUTURE,
         )
     };
-    (deprecation_message_common(message, Some(depr.reason)), lint)
+    let message = match depr.note {
+        Some(reason) => format!("{}: {}", message, reason),
+        None => message,
+    };
+    (message, lint)
 }
 
 pub fn early_report_deprecation(
@@ -289,10 +297,23 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
                     .lookup_deprecation_entry(parent_def_id.to_def_id())
                     .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
 
-                if !skip {
+                // #[deprecated] doesn't emit a notice if we're not on the
+                // topmost deprecation. For example, if a struct is deprecated,
+                // the use of a field won't be linted.
+                //
+                // #[rustc_deprecated] however wants to emit down the whole
+                // hierarchy.
+                if !skip || depr_entry.attr.is_since_rustc_version {
                     let (message, lint) =
                         deprecation_message(&depr_entry.attr, &self.def_path_str(def_id));
-                    late_report_deprecation(self, &message, None, lint, span, id);
+                    late_report_deprecation(
+                        self,
+                        &message,
+                        depr_entry.attr.suggestion,
+                        lint,
+                        span,
+                        id,
+                    );
                 }
             };
         }
@@ -310,16 +331,6 @@ pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> Eva
             def_id, span, stability
         );
 
-        if let Some(id) = id {
-            if let Some(stability) = stability {
-                if let Some(depr) = &stability.rustc_depr {
-                    let (message, lint) =
-                        rustc_deprecation_message(depr, &self.def_path_str(def_id));
-                    late_report_deprecation(self, &message, depr.suggestion, lint, span, id);
-                }
-            }
-        }
-
         // Only the cross-crate scenario matters when checking unstable APIs
         let cross_crate = !def_id.is_local();
         if !cross_crate {
index 96195db0bacd227aecb090741694413dadf3d798..dd4fc7adff11785a5edc1246c41da16ddf14179b 100644 (file)
@@ -105,7 +105,7 @@ pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
         Allocation::from_bytes(slice, Align::from_bytes(1).unwrap())
     }
 
-    pub fn undef(size: Size, align: Align) -> Self {
+    pub fn uninit(size: Size, align: Align) -> Self {
         Allocation {
             bytes: vec![0; size.bytes_usize()],
             relocations: Relocations::new(),
@@ -153,7 +153,7 @@ pub fn len(&self) -> usize {
         self.size.bytes_usize()
     }
 
-    /// Looks at a slice which may describe undefined bytes or describe a relocation. This differs
+    /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs
     /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the
     /// edges) at all. It further ignores `AllocationExtra` callbacks.
     /// This must not be used for reads affecting the interpreter execution.
@@ -192,7 +192,7 @@ fn check_bounds(&self, offset: Size, size: Size) -> Range<usize> {
         offset.bytes_usize()..end
     }
 
-    /// The last argument controls whether we error out when there are undefined
+    /// The last argument controls whether we error out when there are uninitialized
     /// or pointer bytes. You should never call this, call `get_bytes` or
     /// `get_bytes_with_undef_and_ptr` instead,
     ///
@@ -206,12 +206,12 @@ fn get_bytes_internal(
         cx: &impl HasDataLayout,
         ptr: Pointer<Tag>,
         size: Size,
-        check_defined_and_ptr: bool,
+        check_init_and_ptr: bool,
     ) -> InterpResult<'tcx, &[u8]> {
         let range = self.check_bounds(ptr.offset, size);
 
-        if check_defined_and_ptr {
-            self.check_defined(ptr, size)?;
+        if check_init_and_ptr {
+            self.check_init(ptr, size)?;
             self.check_relocations(cx, ptr, size)?;
         } else {
             // We still don't want relocations on the *edges*.
@@ -239,7 +239,7 @@ pub fn get_bytes(
         self.get_bytes_internal(cx, ptr, size, true)
     }
 
-    /// It is the caller's responsibility to handle undefined and pointer bytes.
+    /// It is the caller's responsibility to handle uninitialized and pointer bytes.
     /// However, this still checks that there are no relocations on the *edges*.
     ///
     /// It is the caller's responsibility to check bounds and alignment beforehand.
@@ -267,7 +267,7 @@ pub fn get_bytes_mut(
     ) -> InterpResult<'tcx, &mut [u8]> {
         let range = self.check_bounds(ptr.offset, size);
 
-        self.mark_definedness(ptr, size, true);
+        self.mark_init(ptr, size, true);
         self.clear_relocations(cx, ptr, size)?;
 
         AllocationExtra::memory_written(self, ptr, size)?;
@@ -303,7 +303,7 @@ pub fn read_c_str(
 
     /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
     /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the
-    /// given range contains neither relocations nor undef bytes.
+    /// given range contains neither relocations nor uninitialized bytes.
     pub fn check_bytes(
         &self,
         cx: &impl HasDataLayout,
@@ -313,9 +313,9 @@ pub fn check_bytes(
     ) -> InterpResult<'tcx> {
         // Check bounds and relocations on the edges.
         self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
-        // Check undef and ptr.
+        // Check uninit and ptr.
         if !allow_ptr_and_undef {
-            self.check_defined(ptr, size)?;
+            self.check_init(ptr, size)?;
             self.check_relocations(cx, ptr, size)?;
         }
         Ok(())
@@ -364,7 +364,7 @@ pub fn read_scalar(
         let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
         // Uninit check happens *after* we established that the alignment is correct.
         // We must not return `Ok()` for unaligned pointers!
-        if self.is_defined(ptr, size).is_err() {
+        if self.is_init(ptr, size).is_err() {
             // This inflates uninitialized bytes to the entire scalar, even if only a few
             // bytes are uninitialized.
             return Ok(ScalarMaybeUninit::Uninit);
@@ -416,7 +416,7 @@ pub fn write_scalar(
         let val = match val {
             ScalarMaybeUninit::Scalar(scalar) => scalar,
             ScalarMaybeUninit::Uninit => {
-                self.mark_definedness(ptr, type_size, false);
+                self.mark_init(ptr, type_size, false);
                 return Ok(());
             }
         };
@@ -512,7 +512,7 @@ fn clear_relocations(
         let start = ptr.offset;
         let end = start + size; // `Size` addition
 
-        // Mark parts of the outermost relocations as undefined if they partially fall outside the
+        // Mark parts of the outermost relocations as uninitialized if they partially fall outside the
         // given range.
         if first < start {
             self.init_mask.set_range(first, start, false);
@@ -542,20 +542,20 @@ fn check_relocation_edges(
     }
 }
 
-/// Undefined bytes.
+/// Uninitialized bytes.
 impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
-    /// Checks whether the given range  is entirely defined.
+    /// Checks whether the given range  is entirely initialized.
     ///
-    /// Returns `Ok(())` if it's defined. Otherwise returns the range of byte
-    /// indexes of the first contiguous undefined access.
-    fn is_defined(&self, ptr: Pointer<Tag>, size: Size) -> Result<(), Range<Size>> {
+    /// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte
+    /// indexes of the first contiguous uninitialized access.
+    fn is_init(&self, ptr: Pointer<Tag>, size: Size) -> Result<(), Range<Size>> {
         self.init_mask.is_range_initialized(ptr.offset, ptr.offset + size) // `Size` addition
     }
 
-    /// Checks that a range of bytes is defined. If not, returns the `InvalidUndefBytes`
-    /// error which will report the first range of bytes which is undefined.
-    fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
-        self.is_defined(ptr, size).or_else(|idx_range| {
+    /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes`
+    /// error which will report the first range of bytes which is uninitialized.
+    fn check_init(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
+        self.is_init(ptr, size).or_else(|idx_range| {
             throw_ub!(InvalidUninitBytes(Some(Box::new(UninitBytesAccess {
                 access_ptr: ptr.erase_tag(),
                 access_size: size,
@@ -565,44 +565,44 @@ fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
         })
     }
 
-    pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {
+    pub fn mark_init(&mut self, ptr: Pointer<Tag>, size: Size, is_init: bool) {
         if size.bytes() == 0 {
             return;
         }
-        self.init_mask.set_range(ptr.offset, ptr.offset + size, new_state);
+        self.init_mask.set_range(ptr.offset, ptr.offset + size, is_init);
     }
 }
 
-/// Run-length encoding of the undef mask.
+/// Run-length encoding of the uninit mask.
 /// Used to copy parts of a mask multiple times to another allocation.
-pub struct AllocationDefinedness {
-    /// The definedness of the first range.
+pub struct InitMaskCompressed {
+    /// Whether the first range is initialized.
     initial: bool,
     /// The lengths of ranges that are run-length encoded.
-    /// The definedness of the ranges alternate starting with `initial`.
+    /// The initialization state of the ranges alternate starting with `initial`.
     ranges: smallvec::SmallVec<[u64; 1]>,
 }
 
-impl AllocationDefinedness {
-    pub fn all_bytes_undef(&self) -> bool {
-        // The `ranges` are run-length encoded and of alternating definedness.
-        // So if `ranges.len() > 1` then the second block is a range of defined.
+impl InitMaskCompressed {
+    pub fn no_bytes_init(&self) -> bool {
+        // The `ranges` are run-length encoded and of alternating initialization state.
+        // So if `ranges.len() > 1` then the second block is an initialized range.
         !self.initial && self.ranges.len() == 1
     }
 }
 
-/// Transferring the definedness mask to other allocations.
+/// Transferring the initialization mask to other allocations.
 impl<Tag, Extra> Allocation<Tag, Extra> {
-    /// Creates a run-length encoding of the undef mask.
-    pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> AllocationDefinedness {
+    /// Creates a run-length encoding of the initialization mask.
+    pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed {
         // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
-        // a naive undef mask copying algorithm would repeatedly have to read the undef mask from
+        // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
         // the source and write it to the destination. Even if we optimized the memory accesses,
         // we'd be doing all of this `repeat` times.
-        // Therefore we precompute a compressed version of the undef mask of the source value and
+        // Therefore we precompute a compressed version of the initialization mask of the source value and
         // then write it back `repeat` times without computing any more information from the source.
 
-        // A precomputed cache for ranges of defined/undefined bits
+        // A precomputed cache for ranges of initialized / uninitialized bits
         // 0000010010001110 will become
         // `[5, 1, 2, 1, 3, 3, 1]`,
         // where each element toggles the state.
@@ -613,7 +613,7 @@ pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> AllocationD
         let mut cur = initial;
 
         for i in 1..size.bytes() {
-            // FIXME: optimize to bitshift the current undef block's bits and read the top bit.
+            // FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
             if self.init_mask.get(src.offset + Size::from_bytes(i)) == cur {
                 cur_len += 1;
             } else {
@@ -625,13 +625,13 @@ pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> AllocationD
 
         ranges.push(cur_len);
 
-        AllocationDefinedness { ranges, initial }
+        InitMaskCompressed { ranges, initial }
     }
 
-    /// Applies multiple instances of the run-length encoding to the undef mask.
-    pub fn mark_compressed_undef_range(
+    /// Applies multiple instances of the run-length encoding to the initialization mask.
+    pub fn mark_compressed_init_range(
         &mut self,
-        defined: &AllocationDefinedness,
+        defined: &InitMaskCompressed,
         dest: Pointer<Tag>,
         size: Size,
         repeat: u64,
@@ -740,7 +740,7 @@ pub fn mark_relocation_range(&mut self, relocations: AllocationRelocations<Tag>)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// Undefined byte tracking
+// Uninitialized byte tracking
 ////////////////////////////////////////////////////////////////////////////////
 
 type Block = u64;
@@ -778,11 +778,11 @@ pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<S
 
         match idx {
             Some(idx) => {
-                let undef_end = (idx.bytes()..end.bytes())
+                let uninit_end = (idx.bytes()..end.bytes())
                     .map(Size::from_bytes)
                     .find(|&i| self.get(i))
                     .unwrap_or(end);
-                Err(idx..undef_end)
+                Err(idx..uninit_end)
             }
             None => Ok(()),
         }
index ba2a2bd8a026f19550bf7309cb09c2eedf1f84c9..9de2d17457ab16e1d9172dc87a95ca4a0936eeaa 100644 (file)
@@ -606,7 +606,7 @@ pub fn erase_tag(self) -> ScalarMaybeUninit {
     }
 
     #[inline]
-    pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
+    pub fn check_init(self) -> InterpResult<'static, Scalar<Tag>> {
         match self {
             ScalarMaybeUninit::Scalar(scalar) => Ok(scalar),
             ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)),
@@ -615,72 +615,72 @@ pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
 
     #[inline(always)]
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
-        self.not_undef()?.to_bool()
+        self.check_init()?.to_bool()
     }
 
     #[inline(always)]
     pub fn to_char(self) -> InterpResult<'tcx, char> {
-        self.not_undef()?.to_char()
+        self.check_init()?.to_char()
     }
 
     #[inline(always)]
     pub fn to_f32(self) -> InterpResult<'tcx, Single> {
-        self.not_undef()?.to_f32()
+        self.check_init()?.to_f32()
     }
 
     #[inline(always)]
     pub fn to_f64(self) -> InterpResult<'tcx, Double> {
-        self.not_undef()?.to_f64()
+        self.check_init()?.to_f64()
     }
 
     #[inline(always)]
     pub fn to_u8(self) -> InterpResult<'tcx, u8> {
-        self.not_undef()?.to_u8()
+        self.check_init()?.to_u8()
     }
 
     #[inline(always)]
     pub fn to_u16(self) -> InterpResult<'tcx, u16> {
-        self.not_undef()?.to_u16()
+        self.check_init()?.to_u16()
     }
 
     #[inline(always)]
     pub fn to_u32(self) -> InterpResult<'tcx, u32> {
-        self.not_undef()?.to_u32()
+        self.check_init()?.to_u32()
     }
 
     #[inline(always)]
     pub fn to_u64(self) -> InterpResult<'tcx, u64> {
-        self.not_undef()?.to_u64()
+        self.check_init()?.to_u64()
     }
 
     #[inline(always)]
     pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
-        self.not_undef()?.to_machine_usize(cx)
+        self.check_init()?.to_machine_usize(cx)
     }
 
     #[inline(always)]
     pub fn to_i8(self) -> InterpResult<'tcx, i8> {
-        self.not_undef()?.to_i8()
+        self.check_init()?.to_i8()
     }
 
     #[inline(always)]
     pub fn to_i16(self) -> InterpResult<'tcx, i16> {
-        self.not_undef()?.to_i16()
+        self.check_init()?.to_i16()
     }
 
     #[inline(always)]
     pub fn to_i32(self) -> InterpResult<'tcx, i32> {
-        self.not_undef()?.to_i32()
+        self.check_init()?.to_i32()
     }
 
     #[inline(always)]
     pub fn to_i64(self) -> InterpResult<'tcx, i64> {
-        self.not_undef()?.to_i64()
+        self.check_init()?.to_i64()
     }
 
     #[inline(always)]
     pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
-        self.not_undef()?.to_machine_isize(cx)
+        self.check_init()?.to_machine_isize(cx)
     }
 }
 
index 1ad5008d28a987f264550781c599d21debf8bebb..bb204223b60607ee9079ac6ec8da1e3e02b9d5a1 100644 (file)
@@ -168,7 +168,7 @@ pub fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool {
             MonoItem::GlobalAsm(..) => return true,
         };
 
-        tcx.substitute_normalize_and_test_predicates((def_id, &substs))
+        !tcx.subst_and_check_impossible_predicates((def_id, &substs))
     }
 
     pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String {
index 4dd8723bd72a11d4dc4069e0c8036c41b472db8b..f857af28622d1047cd6dcbd02b60556e568d4c28 100644 (file)
@@ -103,9 +103,13 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         /// // ^ While calling `opt_const_param_of` for other bodies returns `None`.
         /// }
         /// ```
+        // It looks like caching this query on disk actually slightly
+        // worsened performance in #74376.
+        //
+        // Once const generics are more prevalently used, we might want to
+        // consider only caching calls returning `Some`.
         query opt_const_param_of(key: LocalDefId) -> Option<DefId> {
             desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) }
-            // FIXME(#74113): consider storing this query on disk.
         }
 
         /// Records the type of every item.
@@ -1309,6 +1313,13 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
         query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
             desc { "codegen_unit" }
         }
+        query unused_generic_params(key: DefId) -> FiniteBitSet<u64> {
+            cache_on_disk_if { key.is_local() }
+            desc {
+                |tcx| "determining which generic parameters are unused by `{}`",
+                    tcx.def_path_str(key)
+            }
+        }
         query backend_optimization_level(_: CrateNum) -> OptLevel {
             desc { "optimization level used by backend" }
         }
@@ -1461,9 +1472,9 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             desc { "normalizing `{:?}`", goal }
         }
 
-        query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
+        query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
             desc { |tcx|
-                "testing substituted normalized predicates:`{}`",
+                "impossible substituted predicates:`{}`",
                 tcx.def_path_str(key.0)
             }
         }
index c15c31a53f0c9fefafb2f06bdf6d086e95c08488..d2747e5fc659b9efcef4b621e1d6fea8eb33f347 100644 (file)
@@ -169,6 +169,13 @@ pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
     }
 }
 
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct UnifyReceiverContext<'tcx> {
+    pub assoc_item: ty::AssocItem,
+    pub param_env: ty::ParamEnv<'tcx>,
+    pub substs: SubstsRef<'tcx>,
+}
+
 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from the span.
@@ -300,6 +307,8 @@ pub enum ObligationCauseCode<'tcx> {
     /// Method receiver
     MethodReceiver,
 
+    UnifyReceiver(Box<UnifyReceiverContext<'tcx>>),
+
     /// `return` with no expression
     ReturnNoExpression,
 
index f4961617b81c6e8365a4ee6ec6be635b19c5ba7b..c9aae8980076f1a81c3446a03b2d88b0c04fbb91 100644 (file)
@@ -1,5 +1,6 @@
 use crate::ich::{self, StableHashingContext};
 use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::fold::TypeFoldable;
 use crate::ty::{self, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -226,7 +227,8 @@ pub fn ancestors(
     start_from_impl: DefId,
 ) -> Result<Ancestors<'tcx>, ErrorReported> {
     let specialization_graph = tcx.specialization_graph_of(trait_def_id);
-    if specialization_graph.has_errored {
+
+    if specialization_graph.has_errored || tcx.type_of(start_from_impl).references_error() {
         Err(ErrorReported)
     } else {
         Ok(Ancestors {
index 334462790edbcc5a2f03c2de543fcdf9148d0065..18b4371053a89c77b3340161b2eaab7cefaa92c2 100644 (file)
@@ -213,12 +213,26 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             super::StartFunctionType => Some(super::StartFunctionType),
             super::IntrinsicType => Some(super::IntrinsicType),
             super::MethodReceiver => Some(super::MethodReceiver),
+            super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)),
             super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
             super::TrivialBound => Some(super::TrivialBound),
         }
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> {
+    type Lifted = traits::UnifyReceiverContext<'tcx>;
+    fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.param_env).and_then(|param_env| {
+            tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext {
+                assoc_item: self.assoc_item,
+                param_env,
+                substs,
+            })
+        })
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
     type Lifted = traits::DerivedObligationCause<'tcx>;
     fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
index 0e86fcf53b247e0d460ab171e3ab18d45e5f73d5..11a8bedb6605bf6caa3de7fd23e818806f244f72 100644 (file)
@@ -85,7 +85,19 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             }
 
             &ty::Generator(_, ref substs, _) => {
-                self.add_substs(substs);
+                let substs = substs.as_generator();
+                let should_remove_further_specializable =
+                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+                self.add_substs(substs.parent_substs());
+                if should_remove_further_specializable {
+                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+                }
+
+                self.add_ty(substs.resume_ty());
+                self.add_ty(substs.return_ty());
+                self.add_ty(substs.witness());
+                self.add_ty(substs.yield_ty());
+                self.add_ty(substs.tupled_upvars_ty());
             }
 
             &ty::GeneratorWitness(ts) => {
@@ -95,7 +107,17 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             }
 
             &ty::Closure(_, substs) => {
-                self.add_substs(substs);
+                let substs = substs.as_closure();
+                let should_remove_further_specializable =
+                    !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+                self.add_substs(substs.parent_substs());
+                if should_remove_further_specializable {
+                    self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+                }
+
+                self.add_ty(substs.sig_as_fn_ptr_ty());
+                self.add_ty(substs.kind_ty());
+                self.add_ty(substs.tupled_upvars_ty());
             }
 
             &ty::Bound(debruijn, _) => {
index 5c9c9ef6487f16965c5501525e8f8f0c6a61afee..289a9db7327e0d1e344996de1fd5af74b4d79dad 100644 (file)
@@ -1,5 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::print::{FmtPrinter, Printer};
+use crate::ty::subst::InternalSubsts;
 use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
 use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
@@ -106,32 +107,9 @@ pub enum InstanceDef<'tcx> {
 }
 
 impl<'tcx> Instance<'tcx> {
-    /// Returns the `Ty` corresponding to this `Instance`,
-    /// with generic substitutions applied and lifetimes erased.
-    ///
-    /// This method can only be called when the 'substs' for this Instance
-    /// are fully monomorphic (no `ty::Param`'s are present).
-    /// This is usually the case (e.g. during codegen).
-    /// However, during constant evaluation, we may want
-    /// to try to resolve a `Instance` using generic parameters
-    /// (e.g. when we are attempting to to do const-propagation).
-    /// In this case, `Instance.ty_env` should be used to provide
-    /// the `ParamEnv` for our generic context.
-    pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        let ty = tcx.type_of(self.def.def_id());
-        // There shouldn't be any params - if there are, then
-        // Instance.ty_env should have been used to provide the proper
-        // ParamEnv
-        if self.substs.has_param_types_or_consts() {
-            bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs);
-        }
-        tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty)
-    }
-
-    /// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during
-    /// normalization. This method is only really useful during constant evaluation,
-    /// where we are dealing with potentially generic types.
-    pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
+    /// Returns the `Ty` corresponding to this `Instance`, with generic substitutions applied and
+    /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
+    pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
         let ty = tcx.type_of(self.def.def_id());
         tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty)
     }
@@ -486,6 +464,42 @@ pub fn substs_for_mir_body(&self) -> Option<SubstsRef<'tcx>> {
             | InstanceDef::VtableShim(..) => Some(self.substs),
         }
     }
+
+    /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
+    /// identify parameters if they are determined to be unused in `instance.def`.
+    pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
+        debug!("polymorphize: running polymorphization analysis");
+        if !tcx.sess.opts.debugging_opts.polymorphize {
+            return self;
+        }
+
+        if let InstanceDef::Item(def) = self.def {
+            let unused = tcx.unused_generic_params(def.did);
+
+            if unused.is_empty() {
+                // Exit early if every parameter was used.
+                return self;
+            }
+
+            debug!("polymorphize: unused={:?}", unused);
+            let polymorphized_substs =
+                InternalSubsts::for_item(tcx, def.did, |param, _| match param.kind {
+                // If parameter is a const or type parameter..
+                ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if
+                    // ..and is within range and unused..
+                    unused.contains(param.index).unwrap_or(false) =>
+                        // ..then use the identity for this parameter.
+                        tcx.mk_param_from_def(param),
+                // Otherwise, use the parameter as before.
+                _ => self.substs[param.index as usize],
+            });
+
+            debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs);
+            Self { def: self.def, substs: polymorphized_substs }
+        } else {
+            self
+        }
+    }
 }
 
 fn needs_fn_once_adapter_shim(
index 8ae9269a6bf684e566ee2fa0ef27c98f4758ac4a..215f44819b5d144996f2d8e20c289fffca4fb009 100644 (file)
@@ -876,8 +876,6 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                     .iter_enumerated()
                     .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32()));
 
-                let mut niche_filling_layout = None;
-
                 // Niche-filling enum optimization.
                 if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
                     let mut dataful_variant = None;
@@ -974,7 +972,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                             let largest_niche =
                                 Niche::from_scalar(dl, offset, niche_scalar.clone());
 
-                            niche_filling_layout = Some(Layout {
+                            return Ok(tcx.intern_layout(Layout {
                                 variants: Variants::Multiple {
                                     tag: niche_scalar,
                                     tag_encoding: TagEncoding::Niche {
@@ -993,7 +991,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                                 largest_niche,
                                 size,
                                 align,
-                            });
+                            }));
                         }
                     }
                 }
@@ -1216,7 +1214,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
 
                 let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone());
 
-                let tagged_layout = Layout {
+                tcx.intern_layout(Layout {
                     variants: Variants::Multiple {
                         tag,
                         tag_encoding: TagEncoding::Direct,
@@ -1231,23 +1229,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                     abi,
                     align,
                     size,
-                };
-
-                let best_layout = match (tagged_layout, niche_filling_layout) {
-                    (tagged_layout, Some(niche_filling_layout)) => {
-                        // Pick the smaller layout; otherwise,
-                        // pick the layout with the larger niche; otherwise,
-                        // pick tagged as it has simpler codegen.
-                        cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| {
-                            let niche_size =
-                                layout.largest_niche.as_ref().map_or(0, |n| n.available(dl));
-                            (layout.size, cmp::Reverse(niche_size))
-                        })
-                    }
-                    (tagged_layout, None) => tagged_layout,
-                };
-
-                tcx.intern_layout(best_layout)
+                })
             }
 
             // Types with no meaningful known layout.
@@ -2166,16 +2148,31 @@ fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
     }
 
     fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<PointeeInfo> {
-        match this.ty.kind {
+        let addr_space_of_ty = |ty: Ty<'tcx>| {
+            if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
+        };
+
+        let pointee_info = match this.ty.kind {
             ty::RawPtr(mt) if offset.bytes() == 0 => {
                 cx.layout_of(mt.ty).to_result().ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: None,
+                    address_space: addr_space_of_ty(mt.ty),
+                })
+            }
+            ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
+                cx.layout_of(cx.tcx().mk_fn_ptr(fn_sig)).to_result().ok().map(|layout| {
+                    PointeeInfo {
+                        size: layout.size,
+                        align: layout.align.abi,
+                        safe: None,
+                        address_space: cx.data_layout().instruction_address_space,
+                    }
                 })
             }
-
             ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
+                let address_space = addr_space_of_ty(ty);
                 let tcx = cx.tcx();
                 let is_freeze = ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env());
                 let kind = match mt {
@@ -2210,6 +2207,7 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
                     size: layout.size,
                     align: layout.align.abi,
                     safe: Some(kind),
+                    address_space,
                 })
             }
 
@@ -2254,7 +2252,9 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
                             result = field.to_result().ok().and_then(|field| {
                                 if ptr_end <= field_start + field.size {
                                     // We found the right field, look inside it.
-                                    field.pointee_info_at(cx, offset - field_start)
+                                    let field_info =
+                                        field.pointee_info_at(cx, offset - field_start);
+                                    field_info
                                 } else {
                                     None
                                 }
@@ -2277,7 +2277,14 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
 
                 result
             }
-        }
+        };
+
+        debug!(
+            "pointee_info_at (offset={:?}, type kind: {:?}) => {:?}",
+            offset, this.ty.kind, pointee_info
+        );
+
+        pointee_info
     }
 }
 
@@ -2299,12 +2306,22 @@ impl<'tcx> ty::Instance<'tcx> {
     // or should go through `FnAbi` instead, to avoid losing any
     // adjustments `FnAbi::of_instance` might be performing.
     fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
-        let ty = self.monomorphic_ty(tcx);
+        // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
+        let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
         match ty.kind {
-            ty::FnDef(..) |
-            // Shims currently have type FnPtr. Not sure this should remain.
-            ty::FnPtr(_) => {
-                let mut sig = ty.fn_sig(tcx);
+            ty::FnDef(..) => {
+                // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
+                // parameters unused if they show up in the signature, but not in the `mir::Body`
+                // (i.e. due to being inside a projection that got normalized, see
+                // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
+                // track of a polymorphization `ParamEnv` to allow normalizing later.
+                let mut sig = match ty.kind {
+                    ty::FnDef(def_id, substs) => tcx
+                        .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id))
+                        .subst(tcx, substs),
+                    _ => unreachable!(),
+                };
+
                 if let ty::InstanceDef::VtableShim(..) = self.def {
                     // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
                     sig = sig.map_bound(|mut sig| {
@@ -2320,13 +2337,15 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
                 let sig = substs.as_closure().sig();
 
                 let env_ty = tcx.closure_env_ty(def_id, substs).unwrap();
-                sig.map_bound(|sig| tcx.mk_fn_sig(
-                    iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
-                    sig.output(),
-                    sig.c_variadic,
-                    sig.unsafety,
-                    sig.abi
-                ))
+                sig.map_bound(|sig| {
+                    tcx.mk_fn_sig(
+                        iter::once(env_ty.skip_binder()).chain(sig.inputs().iter().cloned()),
+                        sig.output(),
+                        sig.c_variadic,
+                        sig.unsafety,
+                        sig.abi,
+                    )
+                })
             }
             ty::Generator(_, substs, _) => {
                 let sig = substs.as_generator().poly_sig();
@@ -2342,10 +2361,8 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
                 sig.map_bound(|sig| {
                     let state_did = tcx.require_lang_item(GeneratorStateLangItem, None);
                     let state_adt_ref = tcx.adt_def(state_did);
-                    let state_substs = tcx.intern_substs(&[
-                        sig.yield_ty.into(),
-                        sig.return_ty.into(),
-                    ]);
+                    let state_substs =
+                        tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
                     let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
 
                     tcx.mk_fn_sig(
@@ -2353,11 +2370,11 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
                         &ret_ty,
                         false,
                         hir::Unsafety::Normal,
-                        rustc_target::spec::abi::Abi::Rust
+                        rustc_target::spec::abi::Abi::Rust,
                     )
                 })
             }
-            _ => bug!("unexpected type {:?} in Instance::fn_sig", ty)
+            _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
         }
     }
 }
index 21745977b04b1b805b9f84db86653b68ae05c486..a5ddcdfdb0408b8767ef0c75c4534ab44a55b85a 100644 (file)
@@ -136,7 +136,7 @@ pub struct ResolverOutputs {
     pub extern_prelude: FxHashMap<Symbol, bool>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
 pub enum AssocItemContainer {
     TraitContainer(DefId),
     ImplContainer(DefId),
@@ -184,7 +184,7 @@ pub enum ImplPolarity {
     Reservation,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
 pub struct AssocItem {
     pub def_id: DefId,
     #[stable_hasher(project(name))]
@@ -199,7 +199,7 @@ pub struct AssocItem {
     pub fn_has_self_parameter: bool,
 }
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
 pub enum AssocKind {
     Const,
     Fn,
@@ -316,7 +316,7 @@ pub fn find_by_name_and_namespace(
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
 pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
@@ -890,6 +890,7 @@ pub fn own_requires_monomorphization(&self) -> bool {
         false
     }
 
+    /// Returns the `GenericParamDef` with the given index.
     pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
         if let Some(index) = param_index.checked_sub(self.parent_count) {
             &self.params[index]
@@ -899,6 +900,7 @@ pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx Gene
         }
     }
 
+    /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
     pub fn region_param(
         &'tcx self,
         param: &EarlyBoundRegion,
@@ -920,7 +922,7 @@ pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx Gener
         }
     }
 
-    /// Returns the `ConstParameterDef` associated with this `ParamConst`.
+    /// Returns the `GenericParamDef` associated with this `ParamConst`.
     pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
         let param = self.param_at(param.index as usize, tcx);
         match param.kind {
@@ -1615,12 +1617,33 @@ pub struct WithOptConstParam<T> {
 
 impl<T> WithOptConstParam<T> {
     /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
+    #[inline(always)]
     pub fn unknown(did: T) -> WithOptConstParam<T> {
         WithOptConstParam { did, const_param_did: None }
     }
 }
 
 impl WithOptConstParam<LocalDefId> {
+    /// Returns `Some((did, param_did))` if `def_id` is a const argument,
+    /// `None` otherwise.
+    #[inline(always)]
+    pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
+        tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
+    }
+
+    /// In case `self` is unknown but `self.did` is a const argument, this returns
+    /// a `WithOptConstParam` with the correct `const_param_did`.
+    #[inline(always)]
+    pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
+        if self.const_param_did.is_none() {
+            if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
+                return Some(WithOptConstParam { did: self.did, const_param_did });
+            }
+        }
+
+        None
+    }
+
     pub fn to_global(self) -> WithOptConstParam<DefId> {
         WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
     }
index 2f0a57c59eb14abc0d8672ca7b9ee5f19be510ce..48a62b64604672f59770171ef7b0db34ae17aef5 100644 (file)
@@ -54,7 +54,6 @@ pub fn normalize_erasing_late_bound_regions<T>(
     where
         T: TypeFoldable<'tcx>,
     {
-        assert!(!value.needs_subst());
         let value = self.erase_late_bound_regions(value);
         self.normalize_erasing_regions(param_env, value)
     }
index 67b6433b6114327e31737dd164bc38d72d1253a5..2ea7cd2a6dc7acb118d8d104ed771bd83515132a 100644 (file)
@@ -144,12 +144,14 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
                 let substs = substs.truncate_to(self.tcx, generics);
                 self.push_generic_params(substs, iter::empty(), output, debug);
             }
+            ty::Param(_) => {
+                output.push_str(&t.to_string());
+            }
             ty::Error(_)
             | ty::Bound(..)
             | ty::Infer(_)
             | ty::Placeholder(..)
             | ty::Projection(..)
-            | ty::Param(_)
             | ty::GeneratorWitness(_)
             | ty::Opaque(..) => {
                 if debug {
index 2ad49b1acce435c9ad1cac9f11bda2cdf60e0730..2f7a9aee536d84593461e77df6956f118f276b1a 100644 (file)
@@ -44,7 +44,7 @@
 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_index::vec::IndexVec;
+use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
 use rustc_session::CrateDisambiguator;
index 1ba305e63fb9cc8cd06275c84c98e1df4491ae96..643fbe793ab8072540f6ca078aa4b279e6768877 100644 (file)
     UseSpecializedDecodable, UseSpecializedEncodable,
 };
 use rustc_session::{CrateDisambiguator, Session};
-use rustc_span::hygiene::{ExpnId, SyntaxContext};
+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, SourceFile, Span, DUMMY_SP};
+use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
 use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
-const TAG_NO_EXPN_DATA: u8 = 0;
-const TAG_EXPN_DATA_SHORTHAND: u8 = 1;
-const TAG_EXPN_DATA_INLINE: u8 = 2;
-
 const TAG_VALID_SPAN: u8 = 0;
 const TAG_INVALID_SPAN: u8 = 1;
 
+const TAG_SYNTAX_CONTEXT: u8 = 0;
+const TAG_EXPN_DATA: u8 = 1;
+
 /// Provides an interface to incremental compilation data cached from the
 /// previous compilation session. This data will eventually include the results
 /// of a few selected queries (like `typeck` and `mir_optimized`) and
@@ -53,7 +55,6 @@ pub struct OnDiskCache<'sess> {
 
     // Caches that are populated lazily during decoding.
     file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
-    synthetic_syntax_contexts: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
 
     // A map from dep-node to the position of the cached query result in
     // `serialized_data`.
@@ -64,9 +65,28 @@ pub struct OnDiskCache<'sess> {
     prev_diagnostics_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>,
 
     alloc_decoding_state: AllocDecodingState,
+
+    // A map from syntax context ids to the position of their associated
+    // `SyntaxContextData`. We use a `u32` instead of a `SyntaxContext`
+    // to represent the fact that we are storing *encoded* ids. When we decode
+    // a `SyntaxContext`, a new id will be allocated from the global `HygieneData`,
+    // which will almost certainly be different than the serialized id.
+    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
+    // A map from the `DefPathHash` of an `ExpnId` to the position
+    // of their associated `ExpnData`. Ideally, we would store a `DefId`,
+    // but we need to decode this before we've constructed a `TyCtxt` (which
+    // makes it difficult to decode a `DefId`).
+
+    // Note that these `DefPathHashes` correspond to both local and foreign
+    // `ExpnData` (e.g `ExpnData.krate` may not be `LOCAL_CRATE`). Alternatively,
+    // we could look up the `ExpnData` from the metadata of foreign crates,
+    // but it seemed easier to have `OnDiskCache` be independent of the `CStore`.
+    expn_data: FxHashMap<u32, AbsoluteBytePos>,
+    // Additional information used when decoding hygiene data.
+    hygiene_context: HygieneDecodeContext,
 }
 
-// This type is used only for (de-)serialization.
+// This type is used only for serialization and deserialization.
 #[derive(RustcEncodable, RustcDecodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
@@ -75,6 +95,10 @@ struct Footer {
     diagnostics_index: EncodedQueryResultIndex,
     // The location of all allocations.
     interpret_alloc_index: Vec<u32>,
+    // See `OnDiskCache.syntax_contexts`
+    syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
+    // See `OnDiskCache.expn_data`
+    expn_data: FxHashMap<u32, AbsoluteBytePos>,
 }
 
 type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -116,6 +140,7 @@ pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
 
             // Decode the file footer, which contains all the lookup tables, etc.
             decoder.set_position(footer_pos);
+
             decode_tagged(&mut decoder, TAG_FILE_FOOTER)
                 .expect("error while trying to decode footer position")
         };
@@ -130,8 +155,10 @@ pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
             current_diagnostics: Default::default(),
             query_result_index: footer.query_result_index.into_iter().collect(),
             prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(),
-            synthetic_syntax_contexts: Default::default(),
             alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index),
+            syntax_contexts: footer.syntax_contexts,
+            expn_data: footer.expn_data,
+            hygiene_context: Default::default(),
         }
     }
 
@@ -146,8 +173,10 @@ pub fn new_empty(source_map: &'sess SourceMap) -> Self {
             current_diagnostics: Default::default(),
             query_result_index: Default::default(),
             prev_diagnostics_index: Default::default(),
-            synthetic_syntax_contexts: Default::default(),
             alloc_decoding_state: AllocDecodingState::new(Vec::new()),
+            syntax_contexts: FxHashMap::default(),
+            expn_data: FxHashMap::default(),
+            hygiene_context: Default::default(),
         }
     }
 
@@ -175,16 +204,18 @@ pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(
                 (file_to_file_index, file_index_to_stable_id)
             };
 
+            let hygiene_encode_context = HygieneEncodeContext::default();
+
             let mut encoder = CacheEncoder {
                 tcx,
                 encoder,
                 type_shorthands: Default::default(),
                 predicate_shorthands: Default::default(),
-                expn_data_shorthands: Default::default(),
                 interpret_allocs: Default::default(),
                 interpret_allocs_inverse: Vec::new(),
                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
                 file_to_file_index,
+                hygiene_context: &hygiene_encode_context,
             };
 
             // Load everything into memory so we can write it out to the on-disk
@@ -264,7 +295,29 @@ macro_rules! encode_queries {
                 })
                 .collect();
 
-            // Encode the file footer.
+            let mut syntax_contexts = FxHashMap::default();
+            let mut expn_ids = FxHashMap::default();
+
+            // Encode all hygiene data (`SyntaxContextData` and `ExpnData`) from the current
+            // session.
+
+            hygiene_encode_context.encode(
+                &mut encoder,
+                |encoder, index, ctxt_data| {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    encoder.encode_tagged(TAG_SYNTAX_CONTEXT, ctxt_data)?;
+                    syntax_contexts.insert(index, pos);
+                    Ok(())
+                },
+                |encoder, index, expn_data| {
+                    let pos = AbsoluteBytePos::new(encoder.position());
+                    encoder.encode_tagged(TAG_EXPN_DATA, expn_data)?;
+                    expn_ids.insert(index, pos);
+                    Ok(())
+                },
+            )?;
+
+            // `Encode the file footer.
             let footer_pos = encoder.position() as u64;
             encoder.encode_tagged(
                 TAG_FILE_FOOTER,
@@ -274,6 +327,8 @@ macro_rules! encode_queries {
                     query_result_index,
                     diagnostics_index,
                     interpret_alloc_index,
+                    syntax_contexts,
+                    expn_data: expn_ids,
                 },
             )?;
 
@@ -367,6 +422,21 @@ fn load_indexed<'tcx, T>(
     {
         let pos = index.get(&dep_node_index).cloned()?;
 
+        self.with_decoder(tcx, pos, |decoder| match decode_tagged(decoder, dep_node_index) {
+            Ok(v) => Some(v),
+            Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
+        })
+    }
+
+    fn with_decoder<'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+        &'sess self,
+        tcx: TyCtxt<'tcx>,
+        pos: AbsoluteBytePos,
+        f: F,
+    ) -> T
+    where
+        T: Decodable,
+    {
         let cnum_map =
             self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
 
@@ -375,16 +445,14 @@ fn load_indexed<'tcx, T>(
             opaque: opaque::Decoder::new(&self.serialized_data[..], pos.to_usize()),
             source_map: self.source_map,
             cnum_map,
-            synthetic_syntax_contexts: &self.synthetic_syntax_contexts,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
+            syntax_contexts: &self.syntax_contexts,
+            expn_data: &self.expn_data,
+            hygiene_context: &self.hygiene_context,
         };
-
-        match decode_tagged(&mut decoder, dep_node_index) {
-            Ok(v) => Some(v),
-            Err(e) => bug!("could not decode cached {}: {}", debug_tag, e),
-        }
+        f(&mut decoder)
     }
 
     // This function builds mapping from previous-session-`CrateNum` to
@@ -430,10 +498,12 @@ struct CacheDecoder<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
     source_map: &'a SourceMap,
     cnum_map: &'a IndexVec<CrateNum, Option<CrateNum>>,
-    synthetic_syntax_contexts: &'a Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>,
     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, StableSourceFileId>,
     alloc_decoding_session: AllocDecodingSession<'a>,
+    syntax_contexts: &'a FxHashMap<u32, AbsoluteBytePos>,
+    expn_data: &'a FxHashMap<u32, AbsoluteBytePos>,
+    hygiene_context: &'a HygieneDecodeContext,
 }
 
 impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
@@ -577,6 +647,43 @@ fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
 
 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| {
+            // 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();
+            this.with_position(pos.to_usize(), |decoder| {
+                let data: SyntaxContextData = decode_tagged(decoder, TAG_SYNTAX_CONTEXT)?;
+                Ok(data)
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> SpecializedDecoder<ExpnId> for CacheDecoder<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
+        let expn_data = self.expn_data;
+        rustc_span::hygiene::decode_expn_id(
+            self,
+            ExpnDataDecodeMode::incr_comp(self.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.
+                let pos = expn_data
+                    .get(&index)
+                    .unwrap_or_else(|| panic!("Bad index {:?} (map {:?})", index, expn_data));
+
+                this.with_position(pos.to_usize(), |decoder| {
+                    let data: ExpnData = decode_tagged(decoder, TAG_EXPN_DATA)?;
+                    Ok(data)
+                })
+            },
+        )
+    }
+}
+
 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;
@@ -598,48 +705,13 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
         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 = self.file_index_to_file(file_lo_index);
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
-        let expn_data_tag = u8::decode(self)?;
-
-        // FIXME(mw): This method does not restore `ExpnData::parent` or
-        // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things
-        // don't seem to be used after HIR lowering, so everything should be fine
-        // until we want incremental compilation to serialize Spans that we need
-        // full hygiene information for.
-        let location = || Span::with_root_ctxt(lo, hi);
-        let recover_from_expn_data = |this: &Self, expn_data, transparency, pos| {
-            let span = location().fresh_expansion_with_transparency(expn_data, transparency);
-            this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt());
-            span
-        };
-        Ok(match expn_data_tag {
-            TAG_NO_EXPN_DATA => location(),
-            TAG_EXPN_DATA_INLINE => {
-                let (expn_data, transparency) = Decodable::decode(self)?;
-                recover_from_expn_data(
-                    self,
-                    expn_data,
-                    transparency,
-                    AbsoluteBytePos::new(self.opaque.position()),
-                )
-            }
-            TAG_EXPN_DATA_SHORTHAND => {
-                let pos = AbsoluteBytePos::decode(self)?;
-                let cached_ctxt = self.synthetic_syntax_contexts.borrow().get(&pos).cloned();
-                if let Some(ctxt) = cached_ctxt {
-                    Span::new(lo, hi, ctxt)
-                } else {
-                    let (expn_data, transparency) =
-                        self.with_position(pos.to_usize(), |this| Decodable::decode(this))?;
-                    recover_from_expn_data(self, expn_data, transparency, pos)
-                }
-            }
-            _ => unreachable!(),
-        })
+        Ok(Span::new(lo, hi, ctxt))
     }
 }
 
@@ -695,11 +767,11 @@ struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> {
     encoder: &'a mut E,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
-    expn_data_shorthands: FxHashMap<ExpnId, AbsoluteBytePos>,
     interpret_allocs: FxHashMap<interpret::AllocId, usize>,
     interpret_allocs_inverse: Vec<interpret::AllocId>,
     source_map: CachingSourceMapView<'tcx>,
     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
+    hygiene_context: &'a HygieneEncodeContext,
 }
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
@@ -750,6 +822,29 @@ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Se
     }
 }
 
+impl<'a, 'tcx, E> SpecializedEncoder<SyntaxContext> for CacheEncoder<'a, 'tcx, E>
+where
+    E: 'a + TyEncoder,
+{
+    fn specialized_encode(&mut self, ctxt: &SyntaxContext) -> Result<(), Self::Error> {
+        rustc_span::hygiene::raw_encode_syntax_context(*ctxt, self.hygiene_context, self)
+    }
+}
+
+impl<'a, 'tcx, E> SpecializedEncoder<ExpnId> for CacheEncoder<'a, 'tcx, E>
+where
+    E: 'a + TyEncoder,
+{
+    fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+        rustc_span::hygiene::raw_encode_expn_id(
+            *expn,
+            self.hygiene_context,
+            ExpnDataEncodeMode::IncrComp,
+            self,
+        )
+    }
+}
+
 impl<'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
@@ -779,21 +874,8 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         line_lo.encode(self)?;
         col_lo.encode(self)?;
         len.encode(self)?;
-
-        if span_data.ctxt == SyntaxContext::root() {
-            TAG_NO_EXPN_DATA.encode(self)
-        } else {
-            let (expn_id, transparency, expn_data) = span_data.ctxt.outer_mark_with_data();
-            if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() {
-                TAG_EXPN_DATA_SHORTHAND.encode(self)?;
-                pos.encode(self)
-            } else {
-                TAG_EXPN_DATA_INLINE.encode(self)?;
-                let pos = AbsoluteBytePos::new(self.position());
-                self.expn_data_shorthands.insert(expn_id, pos);
-                (expn_data, transparency).encode(self)
-            }
-        }
+        span_data.ctxt.encode(self)?;
+        Ok(())
     }
 }
 
index 2f17db6223362229db7180ba80a4e98efd8787ca..03bf51c95c5a3d7d2a0ecb3beec2f190de0ebab0 100644 (file)
@@ -318,6 +318,7 @@ pub struct ClosureSubsts<'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>,
@@ -329,8 +330,13 @@ impl<'tcx> ClosureSubsts<'tcx> {
     /// ordering.
     fn split(self) -> SplitClosureSubsts<'tcx> {
         match self.substs[..] {
-            [.., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
-                SplitClosureSubsts { closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty }
+            [ref parent @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+                SplitClosureSubsts {
+                    parent,
+                    closure_kind_ty,
+                    closure_sig_as_fn_ptr_ty,
+                    tupled_upvars_ty,
+                }
             }
             _ => bug!("closure substs missing synthetics"),
         }
@@ -345,9 +351,20 @@ pub fn is_valid(self) -> bool {
         self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_))
     }
 
+    /// Returns the substitutions of the closure's parent.
+    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent
+    }
+
     #[inline]
     pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
-        self.split().tupled_upvars_ty.expect_ty().tuple_fields()
+        self.tupled_upvars_ty().tuple_fields()
+    }
+
+    /// Returns the tuple type representing the upvars for this closure.
+    #[inline]
+    pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
+        self.split().tupled_upvars_ty.expect_ty()
     }
 
     /// Returns the closure kind for this closure; may return a type
@@ -392,6 +409,7 @@ pub struct GeneratorSubsts<'tcx> {
 }
 
 struct SplitGeneratorSubsts<'tcx> {
+    parent: &'tcx [GenericArg<'tcx>],
     resume_ty: GenericArg<'tcx>,
     yield_ty: GenericArg<'tcx>,
     return_ty: GenericArg<'tcx>,
@@ -402,8 +420,15 @@ struct SplitGeneratorSubsts<'tcx> {
 impl<'tcx> GeneratorSubsts<'tcx> {
     fn split(self) -> SplitGeneratorSubsts<'tcx> {
         match self.substs[..] {
-            [.., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
-                SplitGeneratorSubsts { resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty }
+            [ref parent @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
+                SplitGeneratorSubsts {
+                    parent,
+                    resume_ty,
+                    yield_ty,
+                    return_ty,
+                    witness,
+                    tupled_upvars_ty,
+                }
             }
             _ => bug!("generator substs missing synthetics"),
         }
@@ -418,6 +443,11 @@ pub fn is_valid(self) -> bool {
         self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_))
     }
 
+    /// Returns the substitutions of the generator's parent.
+    pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+        self.split().parent
+    }
+
     /// This describes the types that can be contained in a generator.
     /// It will be a type variable initially and unified in the last stages of typeck of a body.
     /// It contains a tuple of all the types that could end up on a generator frame.
@@ -429,7 +459,13 @@ pub fn witness(self) -> Ty<'tcx> {
 
     #[inline]
     pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
-        self.split().tupled_upvars_ty.expect_ty().tuple_fields()
+        self.tupled_upvars_ty().tuple_fields()
+    }
+
+    /// Returns the tuple type representing the upvars for this generator.
+    #[inline]
+    pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
+        self.split().tupled_upvars_ty.expect_ty()
     }
 
     /// Returns the type representing the resume type of the generator.
index dd970d800fba0907a68174a2d2d6b6289a00e91d..8521f900988e49a212043b3119e46928b45ad068 100644 (file)
@@ -60,9 +60,7 @@ fn region_name_is_suggestable(name: &RegionName) -> bool {
             // Don't give suggestions for upvars, closure return types, or other unnamable
             // regions.
             RegionNameSource::SynthesizedFreeEnvRegion(..)
-            | RegionNameSource::CannotMatchHirTy(..)
-            | RegionNameSource::MatchedHirTy(..)
-            | RegionNameSource::MatchedAdtAndSegment(..)
+            | RegionNameSource::AnonRegionFromArgument(..)
             | RegionNameSource::AnonRegionFromUpvar(..)
             | RegionNameSource::AnonRegionFromOutput(..)
             | RegionNameSource::AnonRegionFromYieldTy(..)
index 26c2aea41d5dc616b9fc4953966ee7061a14b4c1..cc8a5e0768cba3ab721919ff033bb08b579fc153 100644 (file)
@@ -19,7 +19,7 @@
     MirBorrowckCtxt,
 };
 
-use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
+use super::{OutlivesSuggestionBuilder, RegionName};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -396,18 +396,8 @@ fn report_fnmut_error(
             diag.span_label(upvar_span, "variable captured here");
         }
 
-        match self.give_region_a_name(*outlived_fr).unwrap().source {
-            RegionNameSource::NamedEarlyBoundRegion(fr_span)
-            | RegionNameSource::NamedFreeRegion(fr_span)
-            | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
-            | RegionNameSource::CannotMatchHirTy(fr_span, _)
-            | RegionNameSource::MatchedHirTy(fr_span)
-            | RegionNameSource::MatchedAdtAndSegment(fr_span)
-            | RegionNameSource::AnonRegionFromUpvar(fr_span, _)
-            | RegionNameSource::AnonRegionFromOutput(fr_span, _, _) => {
-                diag.span_label(fr_span, "inferred to be a `FnMut` closure");
-            }
-            _ => {}
+        if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
+            diag.span_label(fr_span, "inferred to be a `FnMut` closure");
         }
 
         diag.note(
index 2240eb81e1fa778aae5d63abc338b6582e11ec39..32195adc60ef87980442f3a9054d650604be7da6 100644 (file)
     Static,
     /// The free region corresponding to the environment of a closure.
     SynthesizedFreeEnvRegion(Span, String),
-    /// The region name corresponds to a region where the type annotation is completely missing
-    /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
-    CannotMatchHirTy(Span, String),
-    /// The region name corresponds a reference that was found by traversing the type in the HIR.
-    MatchedHirTy(Span),
-    /// A region name from the generics list of a struct/enum/union.
-    MatchedAdtAndSegment(Span),
+    /// The region corresponding to an argument.
+    AnonRegionFromArgument(RegionNameHighlight),
     /// The region corresponding to a closure upvar.
     AnonRegionFromUpvar(Span, String),
     /// The region corresponding to the return type of a closure.
     AnonRegionFromAsyncFn(Span),
 }
 
+/// Describes what to highlight to explain to the user that we're giving an anonymous region a
+/// synthesized name, and how to highlight it.
+#[derive(Debug, Clone)]
+crate enum RegionNameHighlight {
+    /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR.
+    MatchedHirTy(Span),
+    /// The anonymous region corresponds to a `'_` in the generics list of a struct/enum/union.
+    MatchedAdtAndSegment(Span),
+    /// The anonymous region corresponds to a region where the type annotation is completely missing
+    /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
+    CannotMatchHirTy(Span, String),
+}
+
 impl RegionName {
     crate fn was_named(&self) -> bool {
         match self.source {
@@ -58,9 +66,7 @@ impl RegionName {
             | RegionNameSource::NamedFreeRegion(..)
             | RegionNameSource::Static => true,
             RegionNameSource::SynthesizedFreeEnvRegion(..)
-            | RegionNameSource::CannotMatchHirTy(..)
-            | RegionNameSource::MatchedHirTy(..)
-            | RegionNameSource::MatchedAdtAndSegment(..)
+            | RegionNameSource::AnonRegionFromArgument(..)
             | RegionNameSource::AnonRegionFromUpvar(..)
             | RegionNameSource::AnonRegionFromOutput(..)
             | RegionNameSource::AnonRegionFromYieldTy(..)
@@ -68,6 +74,24 @@ impl RegionName {
         }
     }
 
+    crate fn span(&self) -> Option<Span> {
+        match self.source {
+            RegionNameSource::Static => None,
+            RegionNameSource::NamedEarlyBoundRegion(span)
+            | RegionNameSource::NamedFreeRegion(span)
+            | RegionNameSource::SynthesizedFreeEnvRegion(span, _)
+            | RegionNameSource::AnonRegionFromUpvar(span, _)
+            | RegionNameSource::AnonRegionFromOutput(span, _, _)
+            | RegionNameSource::AnonRegionFromYieldTy(span, _)
+            | RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span),
+            RegionNameSource::AnonRegionFromArgument(ref highlight) => match *highlight {
+                RegionNameHighlight::MatchedHirTy(span)
+                | RegionNameHighlight::MatchedAdtAndSegment(span)
+                | RegionNameHighlight::CannotMatchHirTy(span, _) => Some(span),
+            },
+        }
+    }
+
     crate fn highlight_region_name(&self, diag: &mut DiagnosticBuilder<'_>) {
         match &self.source {
             RegionNameSource::NamedFreeRegion(span)
@@ -81,17 +105,22 @@ impl RegionName {
                 );
                 diag.note(&note);
             }
-            RegionNameSource::CannotMatchHirTy(span, type_name) => {
+            RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy(
+                span,
+                type_name,
+            )) => {
                 diag.span_label(*span, format!("has type `{}`", type_name));
             }
-            RegionNameSource::MatchedHirTy(span)
+            RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span))
             | RegionNameSource::AnonRegionFromAsyncFn(span) => {
                 diag.span_label(
                     *span,
                     format!("let's call the lifetime of this reference `{}`", self),
                 );
             }
-            RegionNameSource::MatchedAdtAndSegment(span) => {
+            RegionNameSource::AnonRegionFromArgument(
+                RegionNameHighlight::MatchedAdtAndSegment(span),
+            ) => {
                 diag.span_label(*span, format!("let's call this `{}`", self));
             }
             RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => {
@@ -307,21 +336,31 @@ fn give_name_if_anonymous_region_appears_in_arguments(
 
         let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
             [implicit_inputs + argument_index];
-        if let Some(region_name) =
-            self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index)
-        {
-            return Some(region_name);
-        }
+        let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
+            &self.body,
+            &self.local_names,
+            argument_index,
+        );
 
-        self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty)
+        self.get_argument_hir_ty_for_highlighting(argument_index)
+            .and_then(|arg_hir_ty| self.highlight_if_we_can_match_hir_ty(fr, arg_ty, arg_hir_ty))
+            .or_else(|| {
+                // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to
+                // the anonymous region. If it succeeds, the `synthesize_region_name` call below
+                // will increment the counter, "reserving" the number we just used.
+                let counter = *self.next_region_name.try_borrow().unwrap();
+                self.highlight_if_we_cannot_match_hir_ty(fr, arg_ty, span, counter)
+            })
+            .map(|highlight| RegionName {
+                name: self.synthesize_region_name(),
+                source: RegionNameSource::AnonRegionFromArgument(highlight),
+            })
     }
 
-    fn give_name_if_we_can_match_hir_ty_from_argument(
+    fn get_argument_hir_ty_for_highlighting(
         &self,
-        needle_fr: RegionVid,
-        argument_ty: Ty<'tcx>,
         argument_index: usize,
-    ) -> Option<RegionName> {
+    ) -> Option<&hir::Ty<'tcx>> {
         let mir_hir_id = self.infcx.tcx.hir().as_local_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)?;
@@ -333,7 +372,7 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
             // (`give_name_if_anonymous_region_appears_in_arguments`).
             hir::TyKind::Infer => None,
 
-            _ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty),
+            _ => Some(argument_hir_ty),
         }
     }
 
@@ -348,42 +387,28 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
     ///  |          |  has type `&'1 u32`
     ///  |          has type `&'2 u32`
     /// ```
-    fn give_name_if_we_cannot_match_hir_ty(
+    fn highlight_if_we_cannot_match_hir_ty(
         &self,
         needle_fr: RegionVid,
-        argument_ty: Ty<'tcx>,
-    ) -> Option<RegionName> {
-        let counter = *self.next_region_name.try_borrow().unwrap();
+        ty: Ty<'tcx>,
+        span: Span,
+        counter: usize,
+    ) -> Option<RegionNameHighlight> {
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(needle_fr, counter);
-        let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
+        let type_name = self.infcx.extract_type_name(&ty, Some(highlight)).0;
 
         debug!(
-            "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
+            "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
             type_name, needle_fr
         );
-        let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
+        if type_name.find(&format!("'{}", counter)).is_some() {
             // Only add a label if we can confirm that a region was labelled.
-            let argument_index =
-                self.regioncx.get_argument_index_for_region(self.infcx.tcx, needle_fr)?;
-            let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
-                &self.body,
-                &self.local_names,
-                argument_index,
-            );
-
-            Some(RegionName {
-                // This counter value will already have been used, so this function will increment
-                // it so the next value will be used next and return the region name that would
-                // have been used.
-                name: self.synthesize_region_name(),
-                source: RegionNameSource::CannotMatchHirTy(span, type_name),
-            })
+
+            Some(RegionNameHighlight::CannotMatchHirTy(span, type_name))
         } else {
             None
-        };
-
-        assigned_region_name
+        }
     }
 
     /// Attempts to highlight the specific part of a type annotation
@@ -395,9 +420,9 @@ fn give_name_if_we_cannot_match_hir_ty(
     ///  |                - let's call the lifetime of this reference `'1`
     /// ```
     ///
-    /// the way this works is that we match up `argument_ty`, which is
+    /// the way this works is that we match up `ty`, which is
     /// a `Ty<'tcx>` (the internal form of the type) with
-    /// `argument_hir_ty`, a `hir::Ty` (the syntax of the type
+    /// `hir_ty`, a `hir::Ty` (the syntax of the type
     /// annotation). We are descending through the types stepwise,
     /// looking in to find the region `needle_fr` in the internal
     /// type. Once we find that, we can use the span of the `hir::Ty`
@@ -407,18 +432,17 @@ fn give_name_if_we_cannot_match_hir_ty(
     /// keep track of the **closest** type we've found. If we fail to
     /// find the exact `&` or `'_` to highlight, then we may fall back
     /// to highlighting that closest type instead.
-    fn give_name_if_we_can_match_hir_ty(
+    fn highlight_if_we_can_match_hir_ty(
         &self,
         needle_fr: RegionVid,
-        argument_ty: Ty<'tcx>,
-        argument_hir_ty: &hir::Ty<'_>,
-    ) -> Option<RegionName> {
-        let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> =
-            &mut vec![(argument_ty, argument_hir_ty)];
+        ty: Ty<'tcx>,
+        hir_ty: &hir::Ty<'_>,
+    ) -> Option<RegionNameHighlight> {
+        let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)];
 
         while let Some((ty, hir_ty)) = search_stack.pop() {
             match (&ty.kind, &hir_ty.kind) {
-                // Check if the `argument_ty` is `&'X ..` where `'X`
+                // Check if the `ty` is `&'X ..` where `'X`
                 // is the region we are looking for -- if so, and we have a `&T`
                 // on the RHS, then we want to highlight the `&` like so:
                 //
@@ -429,16 +453,11 @@ fn give_name_if_we_can_match_hir_ty(
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
-                        let region_name = self.synthesize_region_name();
-
                         // Just grab the first character, the `&`.
                         let source_map = self.infcx.tcx.sess.source_map();
                         let ampersand_span = source_map.start_point(hir_ty.span);
 
-                        return Some(RegionName {
-                            name: region_name,
-                            source: RegionNameSource::MatchedHirTy(ampersand_span),
-                        });
+                        return Some(RegionNameHighlight::MatchedHirTy(ampersand_span));
                     }
 
                     // Otherwise, let's descend into the referent types.
@@ -458,13 +477,13 @@ fn give_name_if_we_can_match_hir_ty(
                         Res::Def(DefKind::TyAlias, _) => (),
                         _ => {
                             if let Some(last_segment) = path.segments.last() {
-                                if let Some(name) = self.match_adt_and_segment(
+                                if let Some(highlight) = self.match_adt_and_segment(
                                     substs,
                                     needle_fr,
                                     last_segment,
                                     search_stack,
                                 ) {
-                                    return Some(name);
+                                    return Some(highlight);
                                 }
                             }
                         }
@@ -507,7 +526,7 @@ fn match_adt_and_segment<'hir>(
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment<'hir>,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
-    ) -> Option<RegionName> {
+    ) -> Option<RegionNameHighlight> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
         let args = last_segment.args.as_ref()?;
         let lifetime =
@@ -517,12 +536,8 @@ fn match_adt_and_segment<'hir>(
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static
             | hir::LifetimeName::Underscore => {
-                let region_name = self.synthesize_region_name();
-                let ampersand_span = lifetime.span;
-                Some(RegionName {
-                    name: region_name,
-                    source: RegionNameSource::MatchedAdtAndSegment(ampersand_span),
-                })
+                let lifetime_span = lifetime.span;
+                Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
             }
 
             hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => {
index 1972b7149d569fb42a1066dd06eefe71129099a8..76cc03fa60909ba58b605fa105b6928bac3a6ea0 100644 (file)
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
-        mir_borrowck: |tcx, did| mir_borrowck(tcx, ty::WithOptConstParam::unknown(did)),
+        mir_borrowck: |tcx, did| {
+            if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
+                tcx.mir_borrowck_const_arg(def)
+            } else {
+                mir_borrowck(tcx, ty::WithOptConstParam::unknown(did))
+            }
+        },
         mir_borrowck_const_arg: |tcx, (did, param_did)| {
             mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
         },
@@ -100,12 +106,6 @@ fn mir_borrowck<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx BorrowCheckResult<'tcx> {
-    if def.const_param_did.is_none() {
-        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_borrowck_const_arg((def.did, param_did));
-        }
-    }
-
     let (input_body, promoted) = tcx.mir_validated(def);
     debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
 
index dc3e01f3d156128793a69a789b1b25c187fb4bac..42fba8982d23c3d0c91f1bd9771bf13904120699 100644 (file)
@@ -154,7 +154,7 @@ pub(super) fn op_to_const<'tcx>(
                 ScalarMaybeUninit::Uninit => to_const_value(op.assert_mem_place(ecx)),
             },
             Immediate::ScalarPair(a, b) => {
-                let (data, start) = match a.not_undef().unwrap() {
+                let (data, start) = match a.check_init().unwrap() {
                     Scalar::Ptr(ptr) => {
                         (ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes())
                     }
@@ -240,7 +240,7 @@ pub fn const_eval_validated_provider<'tcx>(
     // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
     // Catch such calls and evaluate them instead of trying to load a constant's MIR.
     if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
-        let ty = key.value.instance.ty_env(tcx, key.param_env);
+        let ty = key.value.instance.ty(tcx, key.param_env);
         let substs = match ty.kind {
             ty::FnDef(_, substs) => substs,
             _ => bug!("intrinsic with type {:?}", ty),
index 5836fc9c95a80af6cb330c332a4446f3094665e6..39ed3b607934b2a0f10f701845a95cea5d35f831 100644 (file)
@@ -12,7 +12,7 @@
 };
 use rustc_middle::ty;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size};
 
@@ -54,6 +54,9 @@ fn numeric_intrinsic<'tcx, Tag>(
     let name = tcx.item_name(def_id);
     Ok(match name {
         sym::type_name => {
+            if tp_ty.needs_subst() {
+                throw_inval!(TooGeneric);
+            }
             let alloc = type_name::alloc_type_name(tcx, tp_ty);
             ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
         }
@@ -68,7 +71,12 @@ fn numeric_intrinsic<'tcx, Tag>(
             };
             ConstValue::from_machine_usize(n, &tcx)
         }
-        sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty)),
+        sym::type_id => {
+            if tp_ty.needs_subst() {
+                throw_inval!(TooGeneric);
+            }
+            ConstValue::from_u64(tcx.type_id_hash(tp_ty))
+        }
         sym::variant_count => {
             if let ty::Adt(ref adt, _) = tp_ty.kind {
                 ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx)
@@ -142,7 +150,7 @@ pub fn emulate_intrinsic(
             | sym::bitreverse => {
                 let ty = substs.type_at(0);
                 let layout_of = self.layout_of(ty)?;
-                let val = self.read_scalar(args[0])?.not_undef()?;
+                let val = self.read_scalar(args[0])?.check_init()?;
                 let bits = self.force_bits(val, layout_of.size)?;
                 let kind = match layout_of.abi {
                     Abi::Scalar(ref scalar) => scalar.value,
@@ -273,9 +281,9 @@ pub fn emulate_intrinsic(
                 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
                 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
                 let layout = self.layout_of(substs.type_at(0))?;
-                let val = self.read_scalar(args[0])?.not_undef()?;
+                let val = self.read_scalar(args[0])?.check_init()?;
                 let val_bits = self.force_bits(val, layout.size)?;
-                let raw_shift = self.read_scalar(args[1])?.not_undef()?;
+                let raw_shift = self.read_scalar(args[1])?.check_init()?;
                 let raw_shift_bits = self.force_bits(raw_shift, layout.size)?;
                 let width_bits = u128::from(layout.size.bits());
                 let shift_bits = raw_shift_bits % width_bits;
@@ -290,7 +298,7 @@ pub fn emulate_intrinsic(
                 self.write_scalar(result, dest)?;
             }
             sym::offset => {
-                let ptr = self.read_scalar(args[0])?.not_undef()?;
+                let ptr = self.read_scalar(args[0])?.check_init()?;
                 let offset_count = self.read_scalar(args[1])?.to_machine_isize(self)?;
                 let pointee_ty = substs.type_at(0);
 
@@ -298,7 +306,7 @@ pub fn emulate_intrinsic(
                 self.write_scalar(offset_ptr, dest)?;
             }
             sym::arith_offset => {
-                let ptr = self.read_scalar(args[0])?.not_undef()?;
+                let ptr = self.read_scalar(args[0])?.check_init()?;
                 let offset_count = self.read_scalar(args[1])?.to_machine_isize(self)?;
                 let pointee_ty = substs.type_at(0);
 
index 8af1a8ac608ac8f2a56f4bb61d0c4d455a2a037b..39d2df968341c4208ba56715759fa428117b6670 100644 (file)
@@ -171,7 +171,7 @@ pub fn allocate(
         align: Align,
         kind: MemoryKind<M::MemoryKind>,
     ) -> Pointer<M::PointerTag> {
-        let alloc = Allocation::undef(size, align);
+        let alloc = Allocation::uninit(size, align);
         self.allocate_with(alloc, kind)
     }
 
@@ -716,7 +716,9 @@ fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
         }
     }
 
-    pub fn leak_report(&self) -> usize {
+    /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation
+    /// are not considered leaked. Leaks whose kind `may_leak()` returns true are not reported.
+    pub fn leak_report(&self, static_roots: &[AllocId]) -> usize {
         // Collect the set of allocations that are *reachable* from `Global` allocations.
         let reachable = {
             let mut reachable = FxHashSet::default();
@@ -724,6 +726,7 @@ pub fn leak_report(&self) -> usize {
             let mut todo: Vec<_> = self.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
                 if Some(kind) == global_kind { Some(id) } else { None }
             });
+            todo.extend(static_roots);
             while let Some(id) = todo.pop() {
                 if reachable.insert(id) {
                     // This is a new allocation, add its relocations to `todo`.
@@ -904,18 +907,18 @@ pub fn copy_repeatedly(
 
         let dest_bytes = dest_bytes.as_mut_ptr();
 
-        // Prepare a copy of the undef mask.
+        // Prepare a copy of the initialization mask.
         let compressed = self.get_raw(src.alloc_id)?.compress_undef_range(src, size);
 
-        if compressed.all_bytes_undef() {
-            // Fast path: If all bytes are `undef` then there is nothing to copy. The target range
-            // is marked as undef but we otherwise omit changing the byte representation which may
-            // be arbitrary for undef bytes.
+        if compressed.no_bytes_init() {
+            // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
+            // is marked as unititialized but we otherwise omit changing the byte representation which may
+            // be arbitrary for uninitialized bytes.
             // This also avoids writing to the target bytes so that the backing allocation is never
-            // touched if the bytes stay undef for the whole interpreter execution. On contemporary
+            // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary
             // operating system this can avoid physically allocating the page.
             let dest_alloc = self.get_raw_mut(dest.alloc_id)?;
-            dest_alloc.mark_definedness(dest, size * length, false); // `Size` multiplication
+            dest_alloc.mark_init(dest, size * length, false); // `Size` multiplication
             dest_alloc.mark_relocation_range(relocations);
             return Ok(());
         }
@@ -955,7 +958,7 @@ pub fn copy_repeatedly(
         }
 
         // now fill in all the data
-        self.get_raw_mut(dest.alloc_id)?.mark_compressed_undef_range(
+        self.get_raw_mut(dest.alloc_id)?.mark_compressed_init_range(
             &compressed,
             dest,
             size,
index face72d70cea0b6d36fd2f7265f2a36024cd9998..9f86f2bc588fc86b07fda021af3b9f3b7e48f5ae 100644 (file)
@@ -63,7 +63,7 @@ pub fn new_dyn_trait(val: Scalar<Tag>, vtable: Pointer<Tag>) -> Self {
     }
 
     #[inline]
-    pub fn to_scalar_or_undef(self) -> ScalarMaybeUninit<Tag> {
+    pub fn to_scalar_or_uninit(self) -> ScalarMaybeUninit<Tag> {
         match self {
             Immediate::Scalar(val) => val,
             Immediate::ScalarPair(..) => bug!("Got a wide pointer where a scalar was expected"),
@@ -72,14 +72,14 @@ pub fn to_scalar_or_undef(self) -> ScalarMaybeUninit<Tag> {
 
     #[inline]
     pub fn to_scalar(self) -> InterpResult<'tcx, Scalar<Tag>> {
-        self.to_scalar_or_undef().not_undef()
+        self.to_scalar_or_uninit().check_init()
     }
 
     #[inline]
     pub fn to_scalar_pair(self) -> InterpResult<'tcx, (Scalar<Tag>, Scalar<Tag>)> {
         match self {
             Immediate::Scalar(..) => bug!("Got a thin pointer where a scalar pair was expected"),
-            Immediate::ScalarPair(a, b) => Ok((a.not_undef()?, b.not_undef()?)),
+            Immediate::ScalarPair(a, b) => Ok((a.check_init()?, b.check_init()?)),
         }
     }
 }
@@ -333,7 +333,7 @@ pub fn read_scalar(
         &self,
         op: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, ScalarMaybeUninit<M::PointerTag>> {
-        Ok(self.read_immediate(op)?.to_scalar_or_undef())
+        Ok(self.read_immediate(op)?.to_scalar_or_uninit())
     }
 
     // Turn the wide MPlace into a string (must already be dereferenced!)
index 270be98606454516c75556e848315006030428b9..80a5e56059d0906b0a6cee559bb7ad644a61c460 100644 (file)
@@ -292,9 +292,9 @@ pub fn ref_to_mplace(
             val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
         let layout = self.layout_of(pointee_type)?;
         let (ptr, meta) = match *val {
-            Immediate::Scalar(ptr) => (ptr.not_undef()?, MemPlaceMeta::None),
+            Immediate::Scalar(ptr) => (ptr.check_init()?, MemPlaceMeta::None),
             Immediate::ScalarPair(ptr, meta) => {
-                (ptr.not_undef()?, MemPlaceMeta::Meta(meta.not_undef()?))
+                (ptr.check_init()?, MemPlaceMeta::Meta(meta.check_init()?))
             }
         };
 
@@ -541,7 +541,7 @@ pub(super) fn mplace_projection(
                 let n = self.access_local(self.frame(), local, Some(layout))?;
                 let n = self.read_scalar(n)?;
                 let n = u64::try_from(
-                    self.force_bits(n.not_undef()?, self.tcx.data_layout.pointer_size)?,
+                    self.force_bits(n.check_init()?, self.tcx.data_layout.pointer_size)?,
                 )
                 .unwrap();
                 self.mplace_index(base, n)?
index 4681079a22ddf4f3ef7abca68251054098c2ed30..9a036a0f299e47bd7c6621b91b58f3c1496bd289 100644 (file)
@@ -58,7 +58,7 @@ pub(super) fn eval_terminator(
                 let (fn_val, abi) = match func.layout.ty.kind {
                     ty::FnPtr(sig) => {
                         let caller_abi = sig.abi();
-                        let fn_ptr = self.read_scalar(func)?.not_undef()?;
+                        let fn_ptr = self.read_scalar(func)?.check_init()?;
                         let fn_val = self.memory.get_fn(fn_ptr)?;
                         (fn_val, caller_abi)
                     }
@@ -221,7 +221,7 @@ fn eval_fn_call(
         // ABI check
         {
             let callee_abi = {
-                let instance_ty = instance.ty_env(*self.tcx, self.param_env);
+                let instance_ty = instance.ty(*self.tcx, self.param_env);
                 match instance_ty.kind {
                     ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
                     ty::Closure(..) => Abi::RustCall,
index a1d124bb7602ebb1408107d5840e90e073e56fbb..589da04d6a387468b50049143057e67821b7ce4f 100644 (file)
@@ -118,7 +118,7 @@ pub fn get_vtable_slot(
             .memory
             .get_raw(vtable_slot.alloc_id)?
             .read_ptr_sized(self, vtable_slot)?
-            .not_undef()?;
+            .check_init()?;
         Ok(self.memory.get_fn(fn_ptr)?)
     }
 
@@ -137,12 +137,12 @@ pub fn read_drop_type_from_vtable(
             )?
             .expect("cannot be a ZST");
         let drop_fn =
-            self.memory.get_raw(vtable.alloc_id)?.read_ptr_sized(self, vtable)?.not_undef()?;
+            self.memory.get_raw(vtable.alloc_id)?.read_ptr_sized(self, vtable)?.check_init()?;
         // We *need* an instance here, no other kind of function value, to be able
         // to determine the type.
         let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
         trace!("Found drop fn: {:?}", drop_instance);
-        let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx);
+        let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx);
         let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
         let args = fn_sig.inputs();
@@ -165,10 +165,10 @@ pub fn read_size_and_align_from_vtable(
             .check_ptr_access(vtable, 3 * pointer_size, self.tcx.data_layout.pointer_align.abi)?
             .expect("cannot be a ZST");
         let alloc = self.memory.get_raw(vtable.alloc_id)?;
-        let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?)?.not_undef()?;
+        let size = alloc.read_ptr_sized(self, vtable.offset(pointer_size, self)?)?.check_init()?;
         let size = u64::try_from(self.force_bits(size, pointer_size)?).unwrap();
         let align =
-            alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.not_undef()?;
+            alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.check_init()?;
         let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
 
         if size >= self.tcx.data_layout.obj_size_bound() {
index 84f39ac8955b6f0d91e7033801bff073e6f604f9..f1c5a67ed33f163ae497fa022d80492f78891f9d 100644 (file)
@@ -500,7 +500,7 @@ fn try_visit_primitive(
                 // types below!
                 if self.ref_tracking_for_consts.is_some() {
                     // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
-                    let is_bits = value.not_undef().map_or(false, |v| v.is_bits());
+                    let is_bits = value.check_init().map_or(false, |v| v.is_bits());
                     if !is_bits {
                         throw_validation_failure!(self.path,
                             { "{}", value } expected { "initialized plain (non-pointer) bytes" }
@@ -537,7 +537,7 @@ fn try_visit_primitive(
             ty::FnPtr(_sig) => {
                 let value = self.ecx.read_scalar(value)?;
                 let _fn = try_validation!(
-                    value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
+                    value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
                     err_ub!(InvalidFunctionPointer(..)) |
@@ -596,7 +596,7 @@ fn visit_scalar(
         }
         // At least one value is excluded. Get the bits.
         let value = try_validation!(
-            value.not_undef(),
+            value.check_init(),
             self.path,
             err_ub!(InvalidUninitBytes(None)) => { "{}", value }
                 expected { "something {}", wrapping_range_format(valid_range, max_hi) },
index cd6c38997f18f6a7d843214aad8d2e2c00af0a81..4e7142a93aedc7c20afbe97eca387192d3764f88 100644 (file)
@@ -51,6 +51,7 @@ pub fn provide(providers: &mut Providers) {
     shim::provide(providers);
     transform::provide(providers);
     monomorphize::partitioning::provide(providers);
+    monomorphize::polymorphize::provide(providers);
     providers.const_eval_validated = const_eval::const_eval_validated_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
     providers.const_caller_location = const_eval::const_caller_location;
index 35fb950ce66b9397eeb632da6c2dd240f9d07184..e724180f4d833d588c199cc4bdf46bab1c681410 100644 (file)
@@ -358,9 +358,9 @@ fn collect_items_rec<'tcx>(
             let instance = Instance::mono(tcx, def_id);
 
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_monomorphize_locally(tcx, &instance));
+            debug_assert!(should_codegen_locally(tcx, &instance));
 
-            let ty = instance.monomorphic_ty(tcx);
+            let ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
             visit_drop_use(tcx, ty, true, starting_point.span, &mut neighbors);
 
             recursion_depth_reset = None;
@@ -371,7 +371,7 @@ fn collect_items_rec<'tcx>(
         }
         MonoItem::Fn(instance) => {
             // Sanity check whether this ended up being collected accidentally
-            debug_assert!(should_monomorphize_locally(tcx, &instance));
+            debug_assert!(should_codegen_locally(tcx, &instance));
 
             // Keep track of the monomorphization recursion depth
             recursion_depth_reset =
@@ -584,8 +584,8 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                             substs,
                             ty::ClosureKind::FnOnce,
                         );
-                        if should_monomorphize_locally(self.tcx, &instance) {
-                            self.output.push(create_fn_mono_item(instance, span));
+                        if should_codegen_locally(self.tcx, &instance) {
+                            self.output.push(create_fn_mono_item(self.tcx, instance, span));
                         }
                     }
                     _ => bug!(),
@@ -596,14 +596,14 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                 let exchange_malloc_fn_def_id =
                     tcx.require_lang_item(ExchangeMallocFnLangItem, None);
                 let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
-                if should_monomorphize_locally(tcx, &instance) {
-                    self.output.push(create_fn_mono_item(instance, span));
+                if should_codegen_locally(tcx, &instance) {
+                    self.output.push(create_fn_mono_item(self.tcx, instance, span));
                 }
             }
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(self.tcx.is_thread_local_static(def_id));
                 let instance = Instance::mono(self.tcx, def_id);
-                if should_monomorphize_locally(self.tcx, &instance) {
+                if should_codegen_locally(self.tcx, &instance) {
                     trace!("collecting thread-local static {:?}", def_id);
                     self.output.push(respan(span, MonoItem::Static(def_id)));
                 }
@@ -627,8 +627,9 @@ fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location)
                     Ok(val) => collect_const_value(self.tcx, val, self.output),
                     Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted) => {}
                     Err(ErrorHandled::TooGeneric) => span_bug!(
-                        self.tcx.def_span(def.did),
-                        "collection encountered polymorphic constant",
+                        self.body.source_info(location).span,
+                        "collection encountered polymorphic constant: {}",
+                        substituted_constant
                     ),
                 }
             }
@@ -664,7 +665,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
                         }
                         mir::InlineAsmOperand::SymStatic { def_id } => {
                             let instance = Instance::mono(self.tcx, def_id);
-                            if should_monomorphize_locally(self.tcx, &instance) {
+                            if should_codegen_locally(self.tcx, &instance) {
                                 trace!("collecting asm sym static {:?}", def_id);
                                 self.output.push(respan(source, MonoItem::Static(def_id)));
                             }
@@ -735,7 +736,7 @@ fn visit_instance_use<'tcx>(
     output: &mut Vec<Spanned<MonoItem<'tcx>>>,
 ) {
     debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
-    if !should_monomorphize_locally(tcx, &instance) {
+    if !should_codegen_locally(tcx, &instance) {
         return;
     }
 
@@ -748,7 +749,7 @@ fn visit_instance_use<'tcx>(
         ty::InstanceDef::DropGlue(_, None) => {
             // Don't need to emit noop drop glue if we are calling directly.
             if !is_direct_call {
-                output.push(create_fn_mono_item(instance, source));
+                output.push(create_fn_mono_item(tcx, instance, source));
             }
         }
         ty::InstanceDef::DropGlue(_, Some(_))
@@ -758,7 +759,7 @@ fn visit_instance_use<'tcx>(
         | ty::InstanceDef::Item(..)
         | ty::InstanceDef::FnPtrShim(..)
         | ty::InstanceDef::CloneShim(..) => {
-            output.push(create_fn_mono_item(instance, source));
+            output.push(create_fn_mono_item(tcx, instance, source));
         }
     }
 }
@@ -766,7 +767,7 @@ fn visit_instance_use<'tcx>(
 // Returns `true` if we should codegen an instance in the local crate.
 // Returns `false` if we can just link to the upstream crate and therefore don't
 // need a mono item.
-fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
+fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
     let def_id = match instance.def {
         ty::InstanceDef::Item(def) => def.did,
         ty::InstanceDef::DropGlue(def_id, Some(_)) => def_id,
@@ -781,20 +782,19 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
     };
 
     if tcx.is_foreign_item(def_id) {
-        // Foreign items are always linked against, there's no way of
-        // instantiating them.
+        // Foreign items are always linked against, there's no way of instantiating them.
         return false;
     }
 
     if def_id.is_local() {
-        // Local items cannot be referred to locally without
-        // monomorphizing them locally.
+        // Local items cannot be referred to locally without monomorphizing them locally.
         return true;
     }
 
-    if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(tcx).is_some() {
-        // We can link to the item in question, no instance needed
-        // in this crate.
+    if tcx.is_reachable_non_generic(def_id)
+        || instance.polymorphize(tcx).upstream_monomorphization(tcx).is_some()
+    {
+        // We can link to the item in question, no instance needed in this crate.
         return false;
     }
 
@@ -903,9 +903,13 @@ fn find_vtable_types_for_unsizing<'tcx>(
     }
 }
 
-fn create_fn_mono_item(instance: Instance<'_>, source: Span) -> Spanned<MonoItem<'_>> {
+fn create_fn_mono_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    source: Span,
+) -> Spanned<MonoItem<'tcx>> {
     debug!("create_fn_mono_item(instance={})", instance);
-    respan(source, MonoItem::Fn(instance))
+    respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
 }
 
 /// Creates a `MonoItem` for each method that is referenced by the vtable for
@@ -917,12 +921,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
     source: Span,
     output: &mut Vec<Spanned<MonoItem<'tcx>>>,
 ) {
-    assert!(
-        !trait_ty.needs_subst()
-            && !trait_ty.has_escaping_bound_vars()
-            && !impl_ty.needs_subst()
-            && !impl_ty.has_escaping_bound_vars()
-    );
+    assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars());
 
     if let ty::Dynamic(ref trait_ty, ..) = trait_ty.kind {
         if let Some(principal) = trait_ty.principal() {
@@ -944,8 +943,8 @@ fn create_mono_items_for_vtable_methods<'tcx>(
                     )
                     .unwrap()
                 })
-                .filter(|&instance| should_monomorphize_locally(tcx, &instance))
-                .map(|item| create_fn_mono_item(item, source));
+                .filter(|&instance| should_codegen_locally(tcx, &instance))
+                .map(|item| create_fn_mono_item(tcx, item, source));
             output.extend(methods);
         }
 
@@ -997,7 +996,7 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
                         );
 
                         let ty = Instance::new(def_id.to_def_id(), InternalSubsts::empty())
-                            .monomorphic_ty(self.tcx);
+                            .ty(self.tcx, ty::ParamEnv::reveal_all());
                         visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
                     }
                 }
@@ -1069,7 +1068,7 @@ fn push_if_root(&mut self, def_id: LocalDefId) {
             debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
 
             let instance = Instance::mono(self.tcx, def_id.to_def_id());
-            self.output.push(create_fn_mono_item(instance, DUMMY_SP));
+            self.output.push(create_fn_mono_item(self.tcx, instance, DUMMY_SP));
         }
     }
 
@@ -1106,7 +1105,7 @@ fn push_extra_entry_roots(&mut self) {
         .unwrap()
         .unwrap();
 
-        self.output.push(create_fn_mono_item(start_instance, DUMMY_SP));
+        self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP));
     }
 }
 
@@ -1163,9 +1162,8 @@ fn create_mono_items_for_default_impls<'tcx>(
                         .unwrap()
                         .unwrap();
 
-                    let mono_item = create_fn_mono_item(instance, DUMMY_SP);
-                    if mono_item.node.is_instantiable(tcx)
-                        && should_monomorphize_locally(tcx, &instance)
+                    let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
+                    if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance)
                     {
                         output.push(mono_item);
                     }
@@ -1186,7 +1184,7 @@ fn collect_miri<'tcx>(
         GlobalAlloc::Static(def_id) => {
             assert!(!tcx.is_thread_local_static(def_id));
             let instance = Instance::mono(tcx, def_id);
-            if should_monomorphize_locally(tcx, &instance) {
+            if should_codegen_locally(tcx, &instance) {
                 trace!("collecting static {:?}", def_id);
                 output.push(dummy_spanned(MonoItem::Static(def_id)));
             }
@@ -1200,9 +1198,9 @@ fn collect_miri<'tcx>(
             }
         }
         GlobalAlloc::Function(fn_instance) => {
-            if should_monomorphize_locally(tcx, &fn_instance) {
+            if should_codegen_locally(tcx, &fn_instance) {
                 trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
-                output.push(create_fn_mono_item(fn_instance, DUMMY_SP));
+                output.push(create_fn_mono_item(tcx, fn_instance, DUMMY_SP));
             }
         }
     }
index 76c1c465a8be0ac9a951dffeee14fcccd6965933..15d7b11124071a59b9e0f01eb2abf1791f8ba50f 100644 (file)
@@ -6,6 +6,7 @@
 
 pub mod collector;
 pub mod partitioning;
+pub mod polymorphize;
 
 pub fn custom_coerce_unsize_info<'tcx>(
     tcx: TyCtxt<'tcx>,
diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs
new file mode 100644 (file)
index 0000000..071b9bb
--- /dev/null
@@ -0,0 +1,285 @@
+//! Polymorphization Analysis
+//! =========================
+//!
+//! This module implements an analysis of functions, methods and closures to determine which
+//! generic parameters are unused (and eventually, in what ways generic parameters are used - only
+//! for their size, offset of a field, etc.).
+
+use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_index::bit_set::FiniteBitSet;
+use rustc_middle::mir::{
+    visit::{TyContext, Visitor},
+    Local, LocalDecl, Location,
+};
+use rustc_middle::ty::{
+    self,
+    fold::{TypeFoldable, TypeVisitor},
+    query::Providers,
+    Const, Ty, TyCtxt,
+};
+use rustc_span::symbol::sym;
+use std::convert::TryInto;
+
+/// Provide implementations of queries relating to polymorphization analysis.
+pub fn provide(providers: &mut Providers) {
+    providers.unused_generic_params = unused_generic_params;
+}
+
+/// Determine which generic parameters are used by the function/method/closure represented by
+/// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
+/// indicates all parameters are used).
+fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u64> {
+    debug!("unused_generic_params({:?})", def_id);
+
+    if !tcx.sess.opts.debugging_opts.polymorphize {
+        // If polymorphization disabled, then all parameters are used.
+        return FiniteBitSet::new_empty();
+    }
+
+    let generics = tcx.generics_of(def_id);
+    debug!("unused_generic_params: generics={:?}", generics);
+
+    // Exit early when there are no parameters to be unused.
+    if generics.count() == 0 {
+        return FiniteBitSet::new_empty();
+    }
+
+    // Exit early when there is no MIR available.
+    if !tcx.is_mir_available(def_id) {
+        debug!("unused_generic_params: (no mir available) def_id={:?}", def_id);
+        return FiniteBitSet::new_empty();
+    }
+
+    // Create a bitset with N rightmost ones for each parameter.
+    let generics_count: u32 =
+        generics.count().try_into().expect("more generic parameters than can fit into a `u32`");
+    let mut unused_parameters = FiniteBitSet::<u64>::new_empty();
+    unused_parameters.set_range(0..generics_count);
+    debug!("unused_generic_params: (start) unused_parameters={:?}", unused_parameters);
+    mark_used_by_default_parameters(tcx, def_id, generics, &mut unused_parameters);
+    debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters);
+
+    // 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 };
+    vis.visit_body(body);
+    debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
+
+    mark_used_by_predicates(tcx, def_id, &mut unused_parameters);
+    debug!("unused_generic_params: (end) unused_parameters={:?}", unused_parameters);
+
+    // Emit errors for debugging and testing if enabled.
+    if !unused_parameters.is_empty() {
+        emit_unused_generic_params_error(tcx, def_id, generics, &unused_parameters);
+    }
+
+    unused_parameters
+}
+
+/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
+/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
+/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
+fn mark_used_by_default_parameters<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    generics: &'tcx ty::Generics,
+    unused_parameters: &mut FiniteBitSet<u64>,
+) {
+    if !tcx.is_trait(def_id) && (tcx.is_closure(def_id) || tcx.type_of(def_id).is_generator()) {
+        for param in &generics.params {
+            debug!("mark_used_by_default_parameters: (closure/gen) param={:?}", param);
+            unused_parameters.clear(param.index);
+        }
+    } else {
+        for param in &generics.params {
+            debug!("mark_used_by_default_parameters: (other) param={:?}", param);
+            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                unused_parameters.clear(param.index);
+            }
+        }
+    }
+
+    if let Some(parent) = generics.parent {
+        mark_used_by_default_parameters(tcx, parent, tcx.generics_of(parent), unused_parameters);
+    }
+}
+
+/// Search the predicates on used generic parameters for any unused generic parameters, and mark
+/// those as used.
+fn mark_used_by_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    unused_parameters: &mut FiniteBitSet<u64>,
+) {
+    let def_id = tcx.closure_base_def_id(def_id);
+
+    let is_self_ty_used = |unused_parameters: &mut FiniteBitSet<u64>, 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 mark_ty = |unused_parameters: &mut FiniteBitSet<u64>, ty: Ty<'tcx>| {
+        let mut vis = UsedGenericParametersVisitor { tcx, def_id, unused_parameters };
+        ty.visit_with(&mut vis);
+    };
+
+    let predicates = tcx.explicit_predicates_of(def_id);
+    debug!("mark_parameters_used_in_predicates: predicates_of={:?}", predicates);
+    for (predicate, _) in predicates.predicates {
+        match predicate.kind() {
+            ty::PredicateKind::Trait(predicate, ..) => {
+                let trait_ref = predicate.skip_binder().trait_ref;
+                if is_self_ty_used(unused_parameters, trait_ref.self_ty()) {
+                    for ty in trait_ref.substs.types() {
+                        debug!("unused_generic_params: (trait) ty={:?}", ty);
+                        mark_ty(unused_parameters, ty);
+                    }
+                }
+            }
+            ty::PredicateKind::Projection(predicate, ..) => {
+                let self_ty = predicate.skip_binder().projection_ty.self_ty();
+                if is_self_ty_used(unused_parameters, self_ty) {
+                    let ty = predicate.ty();
+                    debug!("unused_generic_params: (projection) ty={:?}", ty);
+                    mark_ty(unused_parameters, ty.skip_binder());
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
+/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
+/// parameter which was unused.
+fn emit_unused_generic_params_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    generics: &'tcx ty::Generics,
+    unused_parameters: &FiniteBitSet<u64>,
+) {
+    debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
+    let base_def_id = tcx.closure_base_def_id(def_id);
+    if !tcx.get_attrs(base_def_id).iter().any(|a| a.check_name(sym::rustc_polymorphize_error)) {
+        return;
+    }
+
+    debug!("emit_unused_generic_params_error: unused_parameters={:?}", unused_parameters);
+    let fn_span = match tcx.opt_item_name(def_id) {
+        Some(ident) => ident.span,
+        _ => tcx.def_span(def_id),
+    };
+
+    let mut err = tcx.sess.struct_span_err(fn_span, "item has unused generic parameters");
+
+    let mut next_generics = Some(generics);
+    while let Some(generics) = next_generics {
+        for param in &generics.params {
+            if unused_parameters.contains(param.index).unwrap_or(false) {
+                debug!("emit_unused_generic_params_error: param={:?}", param);
+                let def_span = tcx.def_span(param.def_id);
+                err.span_label(def_span, &format!("generic parameter `{}` is unused", param.name));
+            }
+        }
+
+        next_generics = generics.parent.map(|did| tcx.generics_of(did));
+    }
+
+    err.emit();
+}
+
+/// Visitor used to aggregate generic parameter uses.
+struct UsedGenericParametersVisitor<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+    unused_parameters: &'a mut FiniteBitSet<u64>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'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) {
+            let def_kind = self.tcx.def_kind(self.def_id);
+            if matches!(def_kind, DefKind::Closure | DefKind::Generator) {
+                // Skip visiting the closure/generator that is currently being processed. This only
+                // happens because the first argument to the closure is a reference to itself and
+                // that will call `visit_substs`, resulting in each generic parameter captured being
+                // considered used by default.
+                debug!("visit_local_decl: skipping closure substs");
+                return;
+            }
+        }
+
+        self.super_local_decl(local, local_decl);
+    }
+
+    fn visit_const(&mut self, c: &&'tcx Const<'tcx>, _: Location) {
+        c.visit_with(self);
+    }
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
+        ty.visit_with(self);
+    }
+}
+
+impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
+    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) => {
+                debug!("visit_const: param={:?}", param);
+                self.unused_parameters.clear(param.index);
+                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::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => {
+                debug!("visit_ty: def_id={:?}", def_id);
+                // Avoid cycle errors with generators.
+                if def_id == self.def_id {
+                    return false;
+                }
+
+                // Consider any generic parameters used by any closures/generators as used in the
+                // parent.
+                let unused = self.tcx.unused_generic_params(def_id);
+                debug!(
+                    "visit_ty: unused_parameters={:?} unused={:?}",
+                    self.unused_parameters, unused
+                );
+                for (i, arg) in substs.iter().enumerate() {
+                    let i = i.try_into().unwrap();
+                    if !unused.contains(i).unwrap_or(false) {
+                        arg.visit_with(self);
+                    }
+                }
+                debug!("visit_ty: unused_parameters={:?}", self.unused_parameters);
+
+                false
+            }
+            ty::Param(param) => {
+                debug!("visit_ty: param={:?}", param);
+                self.unused_parameters.clear(param.index);
+                false
+            }
+            _ => ty.super_visit_with(self),
+        }
+    }
+}
index 98286cddea68b8d03085f7772b080adac3a37ca4..bfa9bb9e0f0e1a6657ac8dce2b864fa3342838dc 100644 (file)
@@ -4,7 +4,7 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 
 use rustc_index::vec::{Idx, IndexVec};
@@ -36,11 +36,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id), None)
         }
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
-            // FIXME(eddyb) support generating shims for a "shallow type",
-            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
-            // `Foo<Bar>` or `[String]` etc.
-            assert!(!ty.needs_subst());
-
             let trait_ = tcx.trait_of_item(def_id).unwrap();
             let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) {
                 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
@@ -83,22 +78,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
                 None,
             )
         }
-        ty::InstanceDef::DropGlue(def_id, ty) => {
-            // FIXME(eddyb) support generating shims for a "shallow type",
-            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
-            // `Foo<Bar>` or `[String]` etc.
-            assert!(!ty.needs_subst());
-
-            build_drop_shim(tcx, def_id, ty)
-        }
-        ty::InstanceDef::CloneShim(def_id, ty) => {
-            // FIXME(eddyb) support generating shims for a "shallow type",
-            // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
-            // `Foo<Bar>` or `[String]` etc.
-            assert!(!ty.needs_subst());
-
-            build_clone_shim(tcx, def_id, ty)
-        }
+        ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
+        ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
         ty::InstanceDef::Virtual(..) => {
             bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
         }
index 81d7ac089262206aa24957a226f5c50ea627701e..9c06e173bcd5713b2b946af7faa85dd4a341614b 100644 (file)
@@ -439,7 +439,11 @@ fn check_target_features(&mut self, func_did: DefId) {
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         unsafety_check_result: |tcx, def_id| {
-            unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
+            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+                tcx.unsafety_check_result_for_const_arg(def)
+            } else {
+                unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
+            }
         },
         unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
             unsafety_check_result(
@@ -499,12 +503,6 @@ fn unsafety_check_result<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx UnsafetyCheckResult {
-    if def.const_param_did.is_none() {
-        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
-            return tcx.unsafety_check_result_for_const_arg((def.did, param_did));
-        }
-    }
-
     debug!("unsafety_violations({:?})", def);
 
     // N.B., this borrow is valid because all the consumers of
index 237a5a64f8bf851cc600a24ff2f782d48c3dd6b8..6489d7ab1667a9ba4320af7a0381366c205c9345 100644 (file)
@@ -28,9 +28,9 @@
 
 use crate::const_eval::error_to_const_error;
 use crate::interpret::{
-    self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState,
-    LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer,
-    ScalarMaybeUninit, StackPopCleanup,
+    self, compile_time_machine, truncate, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx,
+    LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy,
+    Pointer, ScalarMaybeUninit, StackPopCleanup,
 };
 use crate::transform::{MirPass, MirSource};
 
@@ -116,7 +116,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'
             .predicates
             .iter()
             .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
-        if !traits::normalize_and_test_predicates(
+        if traits::impossible_predicates(
             tcx,
             traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
         ) {
@@ -527,11 +527,11 @@ fn check_binary_op(
         right: &Operand<'tcx>,
         source_info: SourceInfo,
     ) -> Option<()> {
-        let r =
-            self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?;
+        let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?));
         let l = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(left, None)?));
         // Check for exceeding shifts *even if* we cannot evaluate the LHS.
         if op == BinOp::Shr || op == BinOp::Shl {
+            let r = r?;
             // We need the type of the LHS. We cannot use `place_layout` as that is the type
             // of the result, which for checked binops is not the same!
             let left_ty = left.ty(&self.local_decls, self.tcx);
@@ -564,24 +564,51 @@ fn check_binary_op(
             }
         }
 
-        let l = l?;
-
-        // The remaining operators are handled through `overflowing_binary_op`.
-        if self.use_ecx(|this| {
-            let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
-            Ok(overflow)
-        })? {
-            self.report_assert_as_lint(
-                lint::builtin::ARITHMETIC_OVERFLOW,
-                source_info,
-                "this arithmetic operation will overflow",
-                AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
-            )?;
+        if let (Some(l), Some(r)) = (l, r) {
+            // The remaining operators are handled through `overflowing_binary_op`.
+            if self.use_ecx(|this| {
+                let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
+                Ok(overflow)
+            })? {
+                self.report_assert_as_lint(
+                    lint::builtin::ARITHMETIC_OVERFLOW,
+                    source_info,
+                    "this arithmetic operation will overflow",
+                    AssertKind::Overflow(op, l.to_const_int(), r.to_const_int()),
+                )?;
+            }
         }
-
         Some(())
     }
 
+    fn propagate_operand(&mut self, operand: &mut Operand<'tcx>) {
+        match *operand {
+            Operand::Copy(l) | Operand::Move(l) => {
+                if let Some(value) = self.get_const(l) {
+                    if self.should_const_prop(value) {
+                        // FIXME(felix91gr): this code only handles `Scalar` cases.
+                        // For now, we're not handling `ScalarPair` cases because
+                        // doing so here would require a lot of code duplication.
+                        // We should hopefully generalize `Operand` handling into a fn,
+                        // and use it to do const-prop here and everywhere else
+                        // where it makes sense.
+                        if let interpret::Operand::Immediate(interpret::Immediate::Scalar(
+                            ScalarMaybeUninit::Scalar(scalar),
+                        )) = *value
+                        {
+                            *operand = self.operand_from_scalar(
+                                scalar,
+                                value.layout.ty,
+                                self.source_info.unwrap().span,
+                            );
+                        }
+                    }
+                }
+            }
+            Operand::Constant(_) => (),
+        }
+    }
+
     fn const_prop(
         &mut self,
         rvalue: &Rvalue<'tcx>,
@@ -659,9 +686,74 @@ fn const_prop(
             return None;
         }
 
+        if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 {
+            self.eval_rvalue_with_identities(rvalue, place)
+        } else {
+            self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place))
+        }
+    }
+
+    // Attempt to use albegraic identities to eliminate constant expressions
+    fn eval_rvalue_with_identities(
+        &mut self,
+        rvalue: &Rvalue<'tcx>,
+        place: Place<'tcx>,
+    ) -> Option<()> {
         self.use_ecx(|this| {
-            trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place);
-            this.ecx.eval_rvalue_into_place(rvalue, place)?;
+            match rvalue {
+                Rvalue::BinaryOp(op, left, right) | Rvalue::CheckedBinaryOp(op, left, right) => {
+                    let l = this.ecx.eval_operand(left, None);
+                    let r = this.ecx.eval_operand(right, None);
+
+                    let const_arg = match (l, r) {
+                        (Ok(x), Err(_)) | (Err(_), Ok(x)) => this.ecx.read_immediate(x)?,
+                        (Err(e), Err(_)) => return Err(e),
+                        (Ok(_), Ok(_)) => {
+                            this.ecx.eval_rvalue_into_place(rvalue, place)?;
+                            return Ok(());
+                        }
+                    };
+
+                    let arg_value =
+                        this.ecx.force_bits(const_arg.to_scalar()?, const_arg.layout.size)?;
+                    let dest = this.ecx.eval_place(place)?;
+
+                    match op {
+                        BinOp::BitAnd => {
+                            if arg_value == 0 {
+                                this.ecx.write_immediate(*const_arg, dest)?;
+                            }
+                        }
+                        BinOp::BitOr => {
+                            if arg_value == truncate(u128::MAX, const_arg.layout.size)
+                                || (const_arg.layout.ty.is_bool() && arg_value == 1)
+                            {
+                                this.ecx.write_immediate(*const_arg, dest)?;
+                            }
+                        }
+                        BinOp::Mul => {
+                            if const_arg.layout.ty.is_integral() && arg_value == 0 {
+                                if let Rvalue::CheckedBinaryOp(_, _, _) = rvalue {
+                                    let val = Immediate::ScalarPair(
+                                        const_arg.to_scalar()?.into(),
+                                        Scalar::from_bool(false).into(),
+                                    );
+                                    this.ecx.write_immediate(val, dest)?;
+                                } else {
+                                    this.ecx.write_immediate(*const_arg, dest)?;
+                                }
+                            }
+                        }
+                        _ => {
+                            this.ecx.eval_rvalue_into_place(rvalue, place)?;
+                        }
+                    }
+                }
+                _ => {
+                    this.ecx.eval_rvalue_into_place(rvalue, place)?;
+                }
+            }
+
             Ok(())
         })
     }
@@ -905,6 +997,16 @@ fn visit_body(&mut self, body: &mut Body<'tcx>) {
         }
     }
 
+    fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
+        self.super_operand(operand, location);
+
+        // Only const prop copies and moves on `mir_opt_level=3` as doing so
+        // currently increases compile time.
+        if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 {
+            self.propagate_operand(operand)
+        }
+    }
+
     fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
@@ -1072,18 +1174,13 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                     }
                 }
             }
-            TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => {
-                if let Some(value) = self.eval_operand(&discr, source_info) {
-                    if self.should_const_prop(value) {
-                        if let ScalarMaybeUninit::Scalar(scalar) =
-                            self.ecx.read_scalar(value).unwrap()
-                        {
-                            *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span);
-                        }
-                    }
-                }
+            TerminatorKind::SwitchInt { ref mut discr, .. } => {
+                // FIXME: This is currently redundant with `visit_operand`, but sadly
+                // always visiting operands currently causes a perf regression in LLVM codegen, so
+                // `visit_operand` currently only runs for propagates places for `mir_opt_level=3`.
+                self.propagate_operand(discr)
             }
-            // None of these have Operands to const-propagate
+            // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
             | TerminatorKind::Abort
@@ -1096,61 +1193,16 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. } => {}
-            // Every argument in our function calls can be const propagated.
-            TerminatorKind::Call { ref mut args, .. } => {
-                let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
-                // Constant Propagation into function call arguments is gated
-                // under mir-opt-level 2, because LLVM codegen gives performance
-                // regressions with it.
-                if mir_opt_level >= 2 {
-                    for opr in args {
-                        /*
-                          The following code would appear to be incomplete, because
-                          the function `Operand::place()` returns `None` if the
-                          `Operand` is of the variant `Operand::Constant`. In this
-                          context however, that variant will never appear. This is why:
-
-                          When constructing the MIR, all function call arguments are
-                          copied into `Locals` of `LocalKind::Temp`. At least, all arguments
-                          that are not unsized (Less than 0.1% are unsized. See #71170
-                          to learn more about those).
-
-                          This means that, conversely, all `Operands` found as function call
-                          arguments are of the variant `Operand::Copy`. This allows us to
-                          simplify our handling of `Operands` in this case.
-                        */
-                        if let Some(l) = opr.place() {
-                            if let Some(value) = self.get_const(l) {
-                                if self.should_const_prop(value) {
-                                    // FIXME(felix91gr): this code only handles `Scalar` cases.
-                                    // For now, we're not handling `ScalarPair` cases because
-                                    // doing so here would require a lot of code duplication.
-                                    // We should hopefully generalize `Operand` handling into a fn,
-                                    // and use it to do const-prop here and everywhere else
-                                    // where it makes sense.
-                                    if let interpret::Operand::Immediate(
-                                        interpret::Immediate::Scalar(ScalarMaybeUninit::Scalar(
-                                            scalar,
-                                        )),
-                                    ) = *value
-                                    {
-                                        *opr = self.operand_from_scalar(
-                                            scalar,
-                                            value.layout.ty,
-                                            source_info.span,
-                                        );
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
+            // Every argument in our function calls have already been propagated in `visit_operand`.
+            //
+            // NOTE: because LLVM codegen gives performance regressions with it, so this is gated
+            // on `mir_opt_level=3`.
+            TerminatorKind::Call { .. } => {}
         }
 
         // We remove all Locals which are restricted in propagation to their containing blocks and
         // which were modified in the current block.
-        // Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`
+        // Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`.
         let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals);
         for &local in locals.iter() {
             Self::remove_const(&mut self.ecx, local);
index 51a9e76e762ebe50a66548dd4db53e0214da7417..283e4b289f286925979d94c6733fe9c7867cb058 100644 (file)
@@ -48,8 +48,13 @@ pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
         mir_keys,
         mir_const,
-        mir_const_qualif: |tcx, did| {
-            mir_const_qualif(tcx, ty::WithOptConstParam::unknown(did.expect_local()))
+        mir_const_qualif: |tcx, def_id| {
+            let def_id = def_id.expect_local();
+            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+                tcx.mir_const_qualif_const_arg(def)
+            } else {
+                mir_const_qualif(tcx, ty::WithOptConstParam::unknown(def_id))
+            }
         },
         mir_const_qualif_const_arg: |tcx, (did, param_did)| {
             mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
@@ -60,7 +65,12 @@ pub(crate) fn provide(providers: &mut Providers) {
         optimized_mir_of_const_arg,
         is_mir_available,
         promoted_mir: |tcx, def_id| {
-            promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id.expect_local()))
+            let def_id = def_id.expect_local();
+            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+                tcx.promoted_mir_of_const_arg(def)
+            } else {
+                promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id))
+            }
         },
         promoted_mir_of_const_arg: |tcx, (did, param_did)| {
             promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
@@ -221,12 +231,6 @@ pub fn run_passes(
 }
 
 fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
-    if def.const_param_did.is_none() {
-        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_const_qualif_const_arg((def.did, param_did));
-        }
-    }
-
     let const_kind = tcx.hir().body_const_context(def.did);
 
     // No need to const-check a non-const `fn`.
@@ -266,10 +270,8 @@ fn mir_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx Steal<Body<'tcx>> {
-    if def.const_param_did.is_none() {
-        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_const(ty::WithOptConstParam { const_param_did, ..def });
-        }
+    if let Some(def) = def.try_upgrade(tcx) {
+        return tcx.mir_const(def);
     }
 
     // Unsafety check uses the raw mir, so make sure it is run.
@@ -312,10 +314,8 @@ fn mir_validated(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
-    if def.const_param_did.is_none() {
-        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_validated(ty::WithOptConstParam { const_param_did, ..def });
-        }
+    if let Some(def) = def.try_upgrade(tcx) {
+        return tcx.mir_validated(def);
     }
 
     // Ensure that we compute the `mir_const_qualif` for constants at
@@ -357,13 +357,8 @@ fn mir_drops_elaborated_and_const_checked<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx Steal<Body<'tcx>> {
-    if def.const_param_did.is_none() {
-        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam {
-                const_param_did,
-                ..def
-            });
-        }
+    if let Some(def) = def.try_upgrade(tcx) {
+        return tcx.mir_drops_elaborated_and_const_checked(def);
     }
 
     // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
@@ -490,8 +485,8 @@ fn run_optimization_passes<'tcx>(
 
 fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
     let did = did.expect_local();
-    if let Some(param_did) = tcx.opt_const_param_of(did) {
-        tcx.optimized_mir_of_const_arg((did, param_did))
+    if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
+        tcx.optimized_mir_of_const_arg(def)
     } else {
         tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did)))
     }
@@ -528,12 +523,6 @@ fn promoted_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
-    if def.const_param_did.is_none() {
-        if let Some(param_did) = tcx.opt_const_param_of(def.did) {
-            return tcx.promoted_mir_of_const_arg((def.did, param_did));
-        }
-    }
-
     if tcx.is_constructor(def.did.to_def_id()) {
         return tcx.arena.alloc(IndexVec::new());
     }
index eaef6bb37faa591a40ee9b4e4bafbeabe52eb474..36f8034336ba1d856e345798b905fffbc4a76a2d 100644 (file)
@@ -5,6 +5,7 @@
 use crate::hair::*;
 use rustc_ast::ast::InlineAsmOptions;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation};
@@ -43,7 +44,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let block_and = match expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
                 let region_scope = (region_scope, source_info);
-                this.in_scope(region_scope, lint_level, |this| this.into(destination, block, value))
+                ensure_sufficient_stack(|| {
+                    this.in_scope(region_scope, lint_level, |this| {
+                        this.into(destination, block, value)
+                    })
+                })
             }
             ExprKind::Block { body: ast_block } => {
                 this.ast_block(destination, block, ast_block, source_info)
index eb47195c06278d189fff0ac7c9c8204af936e97e..1e677f3d2aba82693e775972cefab82ce3a1dc38 100644 (file)
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> &'tcx ty::steal::Steal<Body<'tcx>> {
-    if def.const_param_did.is_none() {
-        if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
-            return tcx.mir_built(ty::WithOptConstParam { const_param_did, ..def });
-        }
+    if let Some(def) = def.try_upgrade(tcx) {
+        return tcx.mir_built(def);
     }
 
     tcx.alloc_steal_mir(mir_build(tcx, def))
index 372cb783f503f7c7b16c5cd7cb2b61450da86f50..3202f7d1b1b88a036598e159d7c37c7a5c88c40c 100644 (file)
@@ -2614,7 +2614,7 @@ fn specialize_one_pattern<'p, 'tcx>(
             let pats = cx.pattern_arena.alloc_from_iter((0..n).filter_map(|i| {
                 let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
                 let scalar = alloc.read_scalar(&cx.tcx, ptr, layout.size).ok()?;
-                let scalar = scalar.not_undef().ok()?;
+                let scalar = scalar.check_init().ok()?;
                 let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
                 let pattern = Pat { ty, span: pat.span, kind: box PatKind::Constant { value } };
                 Some(pattern)
index 4fa23906a35684c0b3048eba6a1155885f1a9393..a5c87bc963f49bd84232eccadbd88c8789c6be01 100644 (file)
@@ -509,11 +509,6 @@ fn normalize_range_pattern_ends(
     fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         let mut ty = self.typeck_results.node_type(pat.hir_id);
 
-        if let ty::Error(_) = ty.kind {
-            // Avoid ICEs (e.g., #50577 and #50585).
-            return Pat { span: pat.span, ty, kind: Box::new(PatKind::Wild) };
-        }
-
         let kind = match pat.kind {
             hir::PatKind::Wild => PatKind::Wild,
 
index 3244b35e89b0e0062d1bfa48e0fdfe5bb2a8830f..609a0c961e97113b9fb09feec0dfccd113446c26 100644 (file)
@@ -1,8 +1,10 @@
 use super::ty::AllowPlus;
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
-use rustc_ast::ast::{self, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Item, Param};
-use rustc_ast::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind};
+use rustc_ast::ast::{
+    self, AngleBracketedArgs, AttrVec, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind,
+    Item, ItemKind, Mutability, Param, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
+};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Lit, LitKind, TokenKind};
 use rustc_ast::util::parser::AssocOp;
@@ -488,6 +490,57 @@ pub(super) fn check_trailing_angle_brackets(
         false
     }
 
+    /// Check if a method call with an intended turbofish has been written without surrounding
+    /// angle brackets.
+    pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) {
+        if token::ModSep == self.token.kind && segment.args.is_none() {
+            let snapshot = self.clone();
+            self.bump();
+            let lo = self.token.span;
+            match self.parse_angle_args() {
+                Ok(args) => {
+                    let span = lo.to(self.prev_token.span);
+                    // Detect trailing `>` like in `x.collect::Vec<_>>()`.
+                    let mut trailing_span = self.prev_token.span.shrink_to_hi();
+                    while self.token.kind == token::BinOp(token::Shr)
+                        || self.token.kind == token::Gt
+                    {
+                        trailing_span = trailing_span.to(self.token.span);
+                        self.bump();
+                    }
+                    if self.token.kind == token::OpenDelim(token::Paren) {
+                        // Recover from bad turbofish: `foo.collect::Vec<_>()`.
+                        let args = AngleBracketedArgs { args, span }.into();
+                        segment.args = args;
+
+                        self.struct_span_err(
+                            span,
+                            "generic parameters without surrounding angle brackets",
+                        )
+                        .multipart_suggestion(
+                            "surround the type parameters with angle brackets",
+                            vec![
+                                (span.shrink_to_lo(), "<".to_string()),
+                                (trailing_span, ">".to_string()),
+                            ],
+                            Applicability::MachineApplicable,
+                        )
+                        .emit();
+                    } else {
+                        // This doesn't look like an invalid turbofish, can't recover parse state.
+                        *self = snapshot;
+                    }
+                }
+                Err(mut err) => {
+                    // We could't parse generic parameters, unlikely to be a turbofish. Rely on
+                    // generic parse error instead.
+                    err.cancel();
+                    *self = snapshot;
+                }
+            }
+        }
+    }
+
     /// Check to see if a pair of chained operators looks like an attempt at chained comparison,
     /// e.g. `1 < x <= 3`. If so, suggest either splitting the comparison into two, or
     /// parenthesising the leftmost comparison.
index 3926122606e6d851e80e30ae96241e935985b288..d06b172bc148496829d1f0649093a12488a6ac24 100644 (file)
@@ -909,8 +909,9 @@ fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Exp
         }
 
         let fn_span_lo = self.token.span;
-        let segment = self.parse_path_segment(PathStyle::Expr)?;
+        let mut segment = self.parse_path_segment(PathStyle::Expr)?;
         self.check_trailing_angle_brackets(&segment, &[&token::OpenDelim(token::Paren)]);
+        self.check_turbofish_missing_angle_brackets(&mut segment);
 
         if self.check(&token::OpenDelim(token::Paren)) {
             // Method call `expr.f()`
index 67e9b3af4a8cfad21ddb0ba0a9712a73db25f30f..3dcefd362574b420ad082504393edee34b8875f0 100644 (file)
@@ -387,7 +387,7 @@ fn parse_angle_args_with_leading_angle_bracket_recovery(
 
     /// Parses (possibly empty) list of generic arguments / associated item constraints,
     /// possibly including trailing comma.
-    fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
+    pub(super) fn parse_angle_args(&mut self) -> PResult<'a, Vec<AngleBracketedArg>> {
         let mut args = Vec::new();
         while let Some(arg) = self.parse_angle_arg()? {
             args.push(arg);
index 5d972c70d139255f27b137c08895167d1c9f572d..830af8d31e7a6a3b48baa76f6f72ffb05624c9a6 100644 (file)
@@ -59,20 +59,50 @@ fn annotate<F>(
     ) where
         F: FnOnce(&mut Self),
     {
+        debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
+        let mut did_error = false;
         if !self.tcx.features().staged_api {
-            self.forbid_staged_api_attrs(hir_id, attrs, item_sp, kind, visit_children);
-            return;
+            did_error = self.forbid_staged_api_attrs(hir_id, attrs);
         }
 
-        // This crate explicitly wants staged API.
+        let depr = if did_error {
+            None
+        } else {
+            attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp)
+        };
+        let mut is_deprecated = false;
+        if let Some(depr) = &depr {
+            is_deprecated = true;
 
-        debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs);
-        if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) {
-            self.tcx.sess.span_err(
-                item_sp,
-                "`#[deprecated]` cannot be used in staged API; \
-                                             use `#[rustc_deprecated]` instead",
+            if kind == AnnotationKind::Prohibited {
+                self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
+            }
+
+            // `Deprecation` is just two pointers, no need to intern it
+            let depr_entry = DeprecationEntry::local(depr.clone(), hir_id);
+            self.index.depr_map.insert(hir_id, depr_entry);
+        } else if let Some(parent_depr) = self.parent_depr.clone() {
+            is_deprecated = true;
+            info!("tagging child {:?} as deprecated from parent", hir_id);
+            self.index.depr_map.insert(hir_id, parent_depr);
+        }
+
+        if self.tcx.features().staged_api {
+            if let Some(..) = attrs.iter().find(|a| a.check_name(sym::deprecated)) {
+                self.tcx.sess.span_err(
+                    item_sp,
+                    "`#[deprecated]` cannot be used in staged API; \
+                                                use `#[rustc_deprecated]` instead",
+                );
+            }
+        } else {
+            self.recurse_with_stability_attrs(
+                depr.map(|d| DeprecationEntry::local(d, hir_id)),
+                None,
+                None,
+                visit_children,
             );
+            return;
         }
 
         let (stab, const_stab) = attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp);
@@ -92,33 +122,34 @@ fn annotate<F>(
             }
         }
 
-        let stab = stab.map(|mut stab| {
+        if depr.as_ref().map_or(false, |d| d.is_since_rustc_version) {
+            if stab.is_none() {
+                struct_span_err!(
+                    self.tcx.sess,
+                    item_sp,
+                    E0549,
+                    "rustc_deprecated attribute must be paired with \
+                    either stable or unstable attribute"
+                )
+                .emit();
+            }
+        }
+
+        let stab = stab.map(|stab| {
             // Error if prohibited, or can't inherit anything from a container.
             if kind == AnnotationKind::Prohibited
-                || (kind == AnnotationKind::Container
-                    && stab.level.is_stable()
-                    && stab.rustc_depr.is_none())
+                || (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
             {
                 self.tcx.sess.span_err(item_sp, "This stability annotation is useless");
             }
 
             debug!("annotate: found {:?}", stab);
-            // If parent is deprecated and we're not, inherit this by merging
-            // deprecated_since and its reason.
-            if let Some(parent_stab) = self.parent_stab {
-                if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
-                    stab.rustc_depr = parent_stab.rustc_depr
-                }
-            }
-
             let stab = self.tcx.intern_stability(stab);
 
             // Check if deprecated_since < stable_since. If it is,
             // this is *almost surely* an accident.
-            if let (
-                &Some(attr::RustcDeprecation { since: dep_since, .. }),
-                &attr::Stable { since: stab_since },
-            ) = (&stab.rustc_depr, &stab.level)
+            if let (&Some(dep_since), &attr::Stable { since: stab_since }) =
+                (&depr.as_ref().and_then(|d| d.since), &stab.level)
             {
                 // Explicit version of iter::order::lt to handle parse errors properly
                 for (dep_v, stab_v) in
@@ -163,19 +194,29 @@ fn annotate<F>(
             }
         }
 
-        self.recurse_with_stability_attrs(stab, const_stab, visit_children);
+        self.recurse_with_stability_attrs(
+            depr.map(|d| DeprecationEntry::local(d, hir_id)),
+            stab,
+            const_stab,
+            visit_children,
+        );
     }
 
     fn recurse_with_stability_attrs(
         &mut self,
+        depr: Option<DeprecationEntry>,
         stab: Option<&'tcx Stability>,
         const_stab: Option<&'tcx ConstStability>,
         f: impl FnOnce(&mut Self),
     ) {
         // These will be `Some` if this item changes the corresponding stability attribute.
+        let mut replaced_parent_depr = None;
         let mut replaced_parent_stab = None;
         let mut replaced_parent_const_stab = None;
 
+        if let Some(depr) = depr {
+            replaced_parent_depr = Some(replace(&mut self.parent_depr, Some(depr)));
+        }
         if let Some(stab) = stab {
             replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab)));
         }
@@ -186,6 +227,9 @@ fn recurse_with_stability_attrs(
 
         f(self);
 
+        if let Some(orig_parent_depr) = replaced_parent_depr {
+            self.parent_depr = orig_parent_depr;
+        }
         if let Some(orig_parent_stab) = replaced_parent_stab {
             self.parent_stab = orig_parent_stab;
         }
@@ -194,14 +238,8 @@ fn recurse_with_stability_attrs(
         }
     }
 
-    fn forbid_staged_api_attrs(
-        &mut self,
-        hir_id: HirId,
-        attrs: &[Attribute],
-        item_sp: Span,
-        kind: AnnotationKind,
-        visit_children: impl FnOnce(&mut Self),
-    ) {
+    // returns true if an error occurred, used to suppress some spurious errors
+    fn forbid_staged_api_attrs(&mut self, hir_id: HirId, attrs: &[Attribute]) -> bool {
         // Emit errors for non-staged-api crates.
         let unstable_attrs = [
             sym::unstable,
@@ -210,6 +248,7 @@ fn forbid_staged_api_attrs(
             sym::rustc_const_unstable,
             sym::rustc_const_stable,
         ];
+        let mut has_error = false;
         for attr in attrs {
             let name = attr.name_or_empty();
             if unstable_attrs.contains(&name) {
@@ -221,6 +260,7 @@ fn forbid_staged_api_attrs(
                     "stability attributes may not be used outside of the standard library",
                 )
                 .emit();
+                has_error = true;
             }
         }
 
@@ -232,24 +272,7 @@ fn forbid_staged_api_attrs(
             }
         }
 
-        if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) {
-            if kind == AnnotationKind::Prohibited {
-                self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless");
-            }
-
-            // `Deprecation` is just two pointers, no need to intern it
-            let depr_entry = DeprecationEntry::local(depr, hir_id);
-            self.index.depr_map.insert(hir_id, depr_entry.clone());
-
-            let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry));
-            visit_children(self);
-            self.parent_depr = orig_parent_depr;
-        } else if let Some(parent_depr) = self.parent_depr.clone() {
-            self.index.depr_map.insert(hir_id, parent_depr);
-            visit_children(self);
-        } else {
-            visit_children(self);
-        }
+        has_error
     }
 }
 
@@ -454,7 +477,6 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
                     is_soft: false,
                 },
                 feature: sym::rustc_private,
-                rustc_depr: None,
             });
             annotator.parent_stab = Some(stability);
         }
index 45253fc878222affc6e6a60618b63e7f63a85834..737fd13812058bc9ab3aa1373a857a686260947e 100644 (file)
@@ -35,7 +35,7 @@
 use rustc_span::hygiene::{ExpnId, MacroKind};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 
 use log::debug;
 use std::cell::Cell;
@@ -130,8 +130,8 @@ impl<'a> Resolver<'a> {
             parent,
             kind,
             def_id,
-            ExpnId::root(),
-            DUMMY_SP,
+            self.cstore().module_expansion_untracked(def_id, &self.session),
+            self.cstore().get_span_untracked(def_id, &self.session),
         ));
         self.extern_module_map.insert(def_id, module);
         module
@@ -888,7 +888,7 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
     fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
         let parent = self.parent_scope.module;
         let Export { ident, res, vis, span } = child;
-        let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
+        let expansion = self.parent_scope.expansion;
         // Record primary definitions.
         match res {
             Res::Def(kind @ (DefKind::Mod | DefKind::Enum | DefKind::Trait), def_id) => {
index ed88e5496921596a15f783c79c84a648f7a617f8..4b5ab03df4327a9df7af2cf74f851ab000c913f8 100644 (file)
@@ -1500,18 +1500,30 @@ fn resolve_pattern_inner(
         pat_src: PatternSource,
         bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
     ) {
+        let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _));
+
         // Visit all direct subpatterns of this pattern.
         pat.walk(&mut |pat| {
             debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
             match pat.kind {
                 PatKind::Ident(bmode, ident, ref sub) => {
-                    // First try to resolve the identifier as some existing entity,
-                    // then fall back to a fresh binding.
-                    let has_sub = sub.is_some();
-                    let res = self
-                        .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
-                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
-                    self.r.record_partial_res(pat.id, PartialRes::new(res));
+                    if is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some() {
+                        // In tuple struct patterns ignore the invalid `ident @ ...`.
+                        // It will be handled as an error by the AST lowering.
+                        self.r
+                            .session
+                            .delay_span_bug(ident.span, "ident in tuple pattern is invalid");
+                    } else {
+                        // First try to resolve the identifier as some existing entity,
+                        // then fall back to a fresh binding.
+                        let has_sub = sub.is_some();
+                        let res = self
+                            .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
+                            .unwrap_or_else(|| {
+                                self.fresh_binding(ident, pat.id, pat_src, bindings)
+                            });
+                        self.r.record_partial_res(pat.id, PartialRes::new(res));
+                    }
                 }
                 PatKind::TupleStruct(ref path, ..) => {
                     self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct(pat.span));
index 9323c15a94109b9cdb6ad278051bcc451719cb8d..c86b414184759114559e253ac9c4ed78d7b357e3 100644 (file)
@@ -1141,6 +1141,24 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
         err.emit();
     }
 
+    // FIXME(const_generics): This patches over a ICE caused by non-'static lifetimes in const
+    // generics. We are disallowing this until we can decide on how we want to handle non-'static
+    // lifetimes in const generics. See issue #74052 for discussion.
+    crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) {
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            lifetime_ref.span,
+            E0771,
+            "use of non-static lifetime `{}` in const generic",
+            lifetime_ref
+        );
+        err.note(
+            "for more information, see issue #74052 \
+            <https://github.com/rust-lang/rust/issues/74052>",
+        );
+        err.emit();
+    }
+
     crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool {
         if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res {
             if [
index 567db8edec9afe25b550f83e8be1e2df685c28b1..3fbb42ece47a0f904c8060e92ff1baefae69210e 100644 (file)
@@ -173,6 +173,8 @@ struct NamedRegionMap {
     /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
     is_in_fn_syntax: bool,
 
+    is_in_const_generic: bool,
+
     /// List of labels in the function/method currently under analysis.
     labels_in_fn: Vec<Ident>,
 
@@ -333,6 +335,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap {
             scope: ROOT_SCOPE,
             trait_ref_hack: false,
             is_in_fn_syntax: false,
+            is_in_const_generic: false,
             labels_in_fn: vec![],
             xcrate_object_lifetime_defaults: Default::default(),
             lifetime_uses: &mut Default::default(),
@@ -828,6 +831,10 @@ fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
             self.insert_lifetime(lifetime_ref, Region::Static);
             return;
         }
+        if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error {
+            self.emit_non_static_lt_in_const_generic_error(lifetime_ref);
+            return;
+        }
         self.resolve_lifetime_ref(lifetime_ref);
     }
 
@@ -860,8 +867,11 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
                     }
                 }
                 GenericParamKind::Const { ref ty, .. } => {
+                    let was_in_const_generic = self.is_in_const_generic;
+                    self.is_in_const_generic = true;
                     walk_list!(self, visit_param_bound, param.bounds);
                     self.visit_ty(&ty);
+                    self.is_in_const_generic = was_in_const_generic;
                 }
             }
         }
@@ -1288,7 +1298,10 @@ fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>
             }
             GenericParamKind::Const { .. } => {
                 // Generic consts don't impose any constraints.
-                None
+                //
+                // We still store a dummy value here to allow generic parameters
+                // in an arbitrary order.
+                Some(Set1::Empty)
             }
         })
         .collect()
@@ -1317,6 +1330,7 @@ fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
             scope: &wrap_scope,
             trait_ref_hack: self.trait_ref_hack,
             is_in_fn_syntax: self.is_in_fn_syntax,
+            is_in_const_generic: self.is_in_const_generic,
             labels_in_fn,
             xcrate_object_lifetime_defaults,
             lifetime_uses,
index da39f79efcd3bc487d8889a90a4d4bab146e8b29..dfc50a30c121e4965c5f9b1ff8da7bb5102afb42 100644 (file)
@@ -434,7 +434,7 @@ pub fn name(&self) -> Option<Symbol> {
 ///
 /// Multiple bindings in the same module can have the same key (in a valid
 /// program) if all but one of them come from glob imports.
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 struct BindingKey {
     /// The identifier for the binding, aways the `normalize_to_macros_2_0` version of the
     /// identifier.
@@ -1988,6 +1988,7 @@ fn resolve_ident_in_module_ext(
     }
 
     fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
+        debug!("resolve_crate_root({:?})", ident);
         let mut ctxt = ident.span.ctxt();
         let mark = if ident.name == kw::DollarCrate {
             // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
@@ -1997,6 +1998,10 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
             // definitions actually produced by `macro` and `macro` definitions produced by
             // `macro_rules!`, but at least such configurations are not stable yet.
             ctxt = ctxt.normalize_to_macro_rules();
+            debug!(
+                "resolve_crate_root: marks={:?}",
+                ctxt.marks().into_iter().map(|(i, t)| (i.expn_data(), t)).collect::<Vec<_>>()
+            );
             let mut iter = ctxt.marks().into_iter().rev().peekable();
             let mut result = None;
             // Find the last opaque mark from the end if it exists.
@@ -2008,6 +2013,11 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
                     break;
                 }
             }
+            debug!(
+                "resolve_crate_root: found opaque mark {:?} {:?}",
+                result,
+                result.map(|r| r.expn_data())
+            );
             // Then find the last semi-transparent mark from the end if it exists.
             for (mark, transparency) in iter {
                 if transparency == Transparency::SemiTransparent {
@@ -2016,16 +2026,36 @@ fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> {
                     break;
                 }
             }
+            debug!(
+                "resolve_crate_root: found semi-transparent mark {:?} {:?}",
+                result,
+                result.map(|r| r.expn_data())
+            );
             result
         } else {
+            debug!("resolve_crate_root: not DollarCrate");
             ctxt = ctxt.normalize_to_macros_2_0();
             ctxt.adjust(ExpnId::root())
         };
         let module = match mark {
             Some(def) => self.macro_def_scope(def),
-            None => return self.graph_root,
+            None => {
+                debug!(
+                    "resolve_crate_root({:?}): found no mark (ident.span = {:?})",
+                    ident, ident.span
+                );
+                return self.graph_root;
+            }
         };
-        self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id })
+        let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id });
+        debug!(
+            "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})",
+            ident,
+            module,
+            module.kind.name(),
+            ident.span
+        );
+        module
     }
 
     fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
index 3976e501c169feb0f46574bf1b19c53f70d5f1df..fee7cb4836e3d6a61e11901540979b02f4e33b23 100644 (file)
@@ -1017,22 +1017,17 @@ fn check_stability_and_deprecation(
                     );
                 }
             }
-            if let Some(depr) = &stability.rustc_depr {
-                let path = pprust::path_to_string(path);
-                let (message, lint) = stability::rustc_deprecation_message(depr, &path);
-                stability::early_report_deprecation(
-                    &mut self.lint_buffer,
-                    &message,
-                    depr.suggestion,
-                    lint,
-                    span,
-                );
-            }
         }
         if let Some(depr) = &ext.deprecation {
             let path = pprust::path_to_string(&path);
             let (message, lint) = stability::deprecation_message(depr, &path);
-            stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span);
+            stability::early_report_deprecation(
+                &mut self.lint_buffer,
+                &message,
+                depr.suggestion,
+                lint,
+                span,
+            );
         }
     }
 
index 22526fc61e6e0d7a6a0f4657a9d4b86c560f849c..0751dbb027ae2045cf522519dbd0474a0559456b 100644 (file)
@@ -789,7 +789,7 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
         let callee = span.source_callee()?;
 
         let mac_name = match callee.kind {
-            ExpnKind::Macro(mac_kind, name) => match mac_kind {
+            ExpnKind::Macro(kind, name) => match kind {
                 MacroKind::Bang => name,
 
                 // Ignore attribute macros, their spans are usually mangled
index 839ffa5785adacb372b7068475b3998ebe25e49f..620a04b45b0e4c457823af78a21d1bc9abf2b38b 100644 (file)
@@ -103,7 +103,7 @@ pub enum Strip {
     Symbols,
 }
 
-/// The different settings that the `-Z control-flow-guard` flag can have.
+/// The different settings that the `-C control-flow-guard` flag can have.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum CFGuard {
     /// Do not emit Control Flow Guard metadata or checks.
index 8c1f6a77497407fe269b5ada524926ce56f37d0e..502102fa1787647139a57ffa11dc4b14868bc736 100644 (file)
@@ -692,6 +692,8 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "choose the code model to use (`rustc --print code-models` for details)"),
     codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
         "divide crate into N units to optimize in parallel"),
+    control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
+        "use Windows Control Flow Guard (default: no)"),
     debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "explicitly enable the `cfg(debug_assertions)` directive"),
     debuginfo: usize = (0, parse_uint, [TRACKED],
@@ -809,8 +811,6 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         "enable the experimental Chalk-based trait solving engine"),
     codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
         "the backend to use"),
-    control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED],
-        "use Windows Control Flow Guard (default: no)"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
         "inject the given attribute in the crate"),
     debug_macros: bool = (false, parse_bool, [TRACKED],
@@ -949,6 +949,8 @@ fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool {
         (default: PLT is disabled if full relro is enabled)"),
     polonius: bool = (false, parse_bool, [UNTRACKED],
         "enable polonius-based borrow-checker (default: no)"),
+    polymorphize: bool = (false, parse_bool, [TRACKED],
+          "perform polymorphization analysis"),
     pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED],
         "a single extra argument to prepend the linker invocation (can be used several times)"),
     pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
index 4ad95e95e9a86a68fe5e30eebf489878e3067909..1b8f6cdd8bebcc7a2d8bd328a4dd14d25a7c27be 100644 (file)
@@ -548,7 +548,7 @@ pub fn asm_comments(&self) -> bool {
         self.opts.debugging_opts.asm_comments
     }
     pub fn verify_llvm_ir(&self) -> bool {
-        self.opts.debugging_opts.verify_llvm_ir || cfg!(always_verify_llvm_ir)
+        self.opts.debugging_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some()
     }
     pub fn borrowck_stats(&self) -> bool {
         self.opts.debugging_opts.borrowck_stats
index 0a70be1f152e9120bebb83a92f310b26e5261634..a874f81868f153ab6f373101b30136841687b10e 100644 (file)
@@ -247,3 +247,9 @@ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
         hcx.hash_def_id(*self, hasher)
     }
 }
+
+impl<CTX: HashStableContext> HashStable<CTX> for CrateNum {
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        hcx.hash_crate_num(*self, hasher)
+    }
+}
index 7249894ba28be785b99485cb7ce07fafee762873..13bc1751831b977cabe33711938f791b3a93e2a5 100644 (file)
 // because getting it wrong can lead to nested `HygieneData::with` calls that
 // trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
 
-use crate::def_id::{DefId, CRATE_DEF_INDEX};
 use crate::edition::Edition;
 use crate::symbol::{kw, sym, Symbol};
 use crate::SESSION_GLOBALS;
 use crate::{Span, DUMMY_SP};
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
+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};
+use rustc_serialize::{
+    Decodable, Decoder, Encodable, Encoder, UseSpecializedDecodable, UseSpecializedEncodable,
+};
 use std::fmt;
 
 /// 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)]
-struct SyntaxContextData {
+#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
+pub struct SyntaxContextData {
     outer_expn: ExpnId,
     outer_transparency: Transparency,
     parent: SyntaxContext,
@@ -77,6 +80,8 @@ pub enum Transparency {
     Opaque,
 }
 
+pub(crate) const NUM_TRANSPARENCIES: usize = 3;
+
 impl ExpnId {
     pub fn fresh(expn_data: Option<ExpnData>) -> Self {
         HygieneData::with(|data| data.fresh_expn(expn_data))
@@ -104,10 +109,11 @@ pub fn expn_data(self) -> ExpnData {
     }
 
     #[inline]
-    pub fn set_expn_data(self, expn_data: ExpnData) {
+    pub fn set_expn_data(self, mut expn_data: ExpnData) {
         HygieneData::with(|data| {
             let old_expn_data = &mut data.expn_data[self.0 as usize];
             assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID");
+            expn_data.orig_id.replace(self.as_u32()).expect_none("orig_id should be None");
             *old_expn_data = Some(expn_data);
         })
     }
@@ -143,7 +149,7 @@ pub fn expansion_cause(mut self) -> Option<Span> {
 }
 
 #[derive(Debug)]
-crate struct HygieneData {
+pub struct HygieneData {
     /// Each expansion should have an associated expansion data, but sometimes there's a delay
     /// between creation of an expansion ID and obtaining its data (e.g. macros are collected
     /// first and then resolved later), so we use an `Option` here.
@@ -154,13 +160,16 @@ pub fn expansion_cause(mut self) -> Option<Span> {
 
 impl HygieneData {
     crate fn new(edition: Edition) -> Self {
+        let mut root_data = ExpnData::default(
+            ExpnKind::Root,
+            DUMMY_SP,
+            edition,
+            Some(DefId::local(CRATE_DEF_INDEX)),
+        );
+        root_data.orig_id = Some(0);
+
         HygieneData {
-            expn_data: vec![Some(ExpnData::default(
-                ExpnKind::Root,
-                DUMMY_SP,
-                edition,
-                Some(DefId::local(CRATE_DEF_INDEX)),
-            ))],
+            expn_data: vec![Some(root_data)],
             syntax_context_data: vec![SyntaxContextData {
                 outer_expn: ExpnId::root(),
                 outer_transparency: Transparency::Opaque,
@@ -173,13 +182,17 @@ impl HygieneData {
         }
     }
 
-    fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
+    pub fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
         SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.hygiene_data.borrow_mut()))
     }
 
-    fn fresh_expn(&mut self, expn_data: Option<ExpnData>) -> ExpnId {
+    fn fresh_expn(&mut self, mut expn_data: Option<ExpnData>) -> ExpnId {
+        let raw_id = self.expn_data.len() as u32;
+        if let Some(data) = expn_data.as_mut() {
+            data.orig_id.replace(raw_id).expect_none("orig_id should be None");
+        }
         self.expn_data.push(expn_data);
-        ExpnId(self.expn_data.len() as u32 - 1)
+        ExpnId(raw_id)
     }
 
     fn expn_data(&self, expn_id: ExpnId) -> &ExpnData {
@@ -226,6 +239,7 @@ fn remove_mark(&self, ctxt: &mut SyntaxContext) -> (ExpnId, Transparency) {
     fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
         let mut marks = Vec::new();
         while ctxt != SyntaxContext::root() {
+            debug!("marks: getting parent of {:?}", ctxt);
             marks.push(self.outer_mark(ctxt));
             ctxt = self.parent_ctxt(ctxt);
         }
@@ -234,8 +248,14 @@ fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> {
     }
 
     fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
+        debug!("walk_chain({:?}, {:?})", span, to);
+        debug!("walk_chain: span ctxt = {:?}", span.ctxt());
         while span.from_expansion() && span.ctxt() != to {
-            span = self.expn_data(self.outer_expn(span.ctxt())).call_site;
+            let outer_expn = self.outer_expn(span.ctxt());
+            debug!("walk_chain({:?}): outer_expn={:?}", span, outer_expn);
+            let expn_data = self.expn_data(outer_expn);
+            debug!("walk_chain({:?}): expn_data={:?}", span, expn_data);
+            span = expn_data.call_site;
         }
         span
     }
@@ -682,8 +702,25 @@ pub struct ExpnData {
     /// The `DefId` of the macro being invoked,
     /// if this `ExpnData` corresponds to a macro invocation
     pub macro_def_id: Option<DefId>,
+    /// The crate that originally created this `ExpnData. During
+    /// metadata serialization, we only encode `ExpnData`s that were
+    /// created locally - when our serialized metadata is decoded,
+    /// foreign `ExpnId`s will have their `ExpnData` looked up
+    /// from the crate specified by `Crate
+    pub krate: CrateNum,
+    /// The raw that this `ExpnData` had in its original crate.
+    /// An `ExpnData` can be created before being assigned an `ExpnId`,
+    /// so this might be `None` until `set_expn_data` is called
+    // This is used only for serialization/deserialization purposes:
+    // two `ExpnData`s that differ only in their `orig_id` should
+    // be considered equivalent.
+    #[stable_hasher(ignore)]
+    pub orig_id: Option<u32>,
 }
 
+// This would require special handling of `orig_id` and `parent`
+impl !PartialEq for ExpnData {}
+
 impl ExpnData {
     /// Constructs expansion data with default properties.
     pub fn default(
@@ -702,6 +739,8 @@ pub fn default(
             local_inner_macros: false,
             edition,
             macro_def_id,
+            krate: LOCAL_CRATE,
+            orig_id: None,
         }
     }
 
@@ -789,7 +828,7 @@ pub fn article(self) -> &'static str {
 }
 
 /// The kind of AST transform.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
 pub enum AstPass {
     StdImports,
     TestHarness,
@@ -847,14 +886,318 @@ fn descr(self) -> &'static str {
     }
 }
 
-impl Encodable for ExpnId {
-    fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
-        Ok(()) // FIXME(jseyfried) intercrate hygiene
+impl UseSpecializedEncodable for ExpnId {}
+impl UseSpecializedDecodable for ExpnId {}
+
+#[derive(Default)]
+pub struct HygieneEncodeContext {
+    /// All `SyntaxContexts` for which we have writen `SyntaxContextData` into crate metadata.
+    /// This is `None` after we finish encoding `SyntaxContexts`, to ensure
+    /// that we don't accidentally try to encode any more `SyntaxContexts`
+    serialized_ctxts: Lock<FxHashSet<SyntaxContext>>,
+    /// The `SyntaxContexts` that we have serialized (e.g. as a result of encoding `Spans`)
+    /// in the most recent 'round' of serializnig. Serializing `SyntaxContextData`
+    /// may cause us to serialize more `SyntaxContext`s, so serialize in a loop
+    /// until we reach a fixed point.
+    latest_ctxts: Lock<FxHashSet<SyntaxContext>>,
+
+    serialized_expns: Lock<FxHashSet<ExpnId>>,
+
+    latest_expns: Lock<FxHashSet<ExpnId>>,
+}
+
+impl HygieneEncodeContext {
+    pub fn encode<
+        T,
+        R,
+        F: FnMut(&mut T, u32, &SyntaxContextData) -> Result<(), R>,
+        G: FnMut(&mut T, u32, &ExpnData) -> Result<(), R>,
+    >(
+        &self,
+        encoder: &mut T,
+        mut encode_ctxt: F,
+        mut encode_expn: G,
+    ) -> Result<(), R> {
+        // When we serialize a `SyntaxContextData`, we may end up serializing
+        // a `SyntaxContext` that we haven't seen before
+        while !self.latest_ctxts.lock().is_empty() || !self.latest_expns.lock().is_empty() {
+            debug!(
+                "encode_hygiene: Serializing a round of {:?} SyntaxContextDatas: {:?}",
+                self.latest_ctxts.lock().len(),
+                self.latest_ctxts
+            );
+
+            // Consume the current round of SyntaxContexts.
+            // Drop the lock() temporary early
+            let latest_ctxts = { std::mem::take(&mut *self.latest_ctxts.lock()) };
+
+            // It's fine to iterate over a HashMap, because the serialization
+            // of the table that we insert data into doesn't depend on insertion
+            // order
+            for_all_ctxts_in(latest_ctxts.into_iter(), |(index, ctxt, data)| {
+                if self.serialized_ctxts.lock().insert(ctxt) {
+                    encode_ctxt(encoder, index, data)?;
+                }
+                Ok(())
+            })?;
+
+            let latest_expns = { std::mem::take(&mut *self.latest_expns.lock()) };
+
+            for_all_expns_in(latest_expns.into_iter(), |index, expn, data| {
+                if self.serialized_expns.lock().insert(expn) {
+                    encode_expn(encoder, index, data)?;
+                }
+                Ok(())
+            })?;
+        }
+        debug!("encode_hygiene: Done serializing SyntaxContextData");
+        Ok(())
+    }
+}
+
+#[derive(Default)]
+/// Additional information used to assist in decoding hygiene data
+pub struct HygieneDecodeContext {
+    // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current
+    // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
+    // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
+    // so that multiple occurences of the same serialized id are decoded to the same
+    // `SyntaxContext`
+    remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
+    // The same as `remapepd_ctxts`, but for `ExpnId`s
+    remapped_expns: Lock<Vec<Option<ExpnId>>>,
+}
+
+pub fn decode_expn_id<
+    'a,
+    D: Decoder,
+    F: FnOnce(&mut D, u32) -> Result<ExpnData, D::Error>,
+    G: FnOnce(CrateNum) -> &'a HygieneDecodeContext,
+>(
+    d: &mut D,
+    mode: ExpnDataDecodeMode<'a, G>,
+    decode_data: F,
+) -> Result<ExpnId, D::Error> {
+    let index = u32::decode(d)?;
+    let context = match mode {
+        ExpnDataDecodeMode::IncrComp(context) => context,
+        ExpnDataDecodeMode::Metadata(get_context) => {
+            let krate = CrateNum::decode(d)?;
+            get_context(krate)
+        }
+    };
+
+    // Do this after decoding, so that we decode a `CrateNum`
+    // if necessary
+    if index == ExpnId::root().as_u32() {
+        debug!("decode_expn_id: deserialized root");
+        return Ok(ExpnId::root());
+    }
+
+    let outer_expns = &context.remapped_expns;
+
+    // Ensure that the lock() temporary is dropped early
+    {
+        if let Some(expn_id) = outer_expns.lock().get(index as usize).copied().flatten() {
+            return Ok(expn_id);
+        }
+    }
+
+    // Don't decode the data inside `HygieneData::with`, since we need to recursively decode
+    // other ExpnIds
+    let mut expn_data = decode_data(d, index)?;
+
+    let expn_id = HygieneData::with(|hygiene_data| {
+        let expn_id = ExpnId(hygiene_data.expn_data.len() as u32);
+
+        // If we just deserialized an `ExpnData` owned by
+        // the local crate, its `orig_id` will be stale,
+        // so we need to update it to its own value.
+        // This only happens when we deserialize the incremental cache,
+        // since a crate will never decode its own metadata.
+        if expn_data.krate == LOCAL_CRATE {
+            expn_data.orig_id = Some(expn_id.0);
+        }
+
+        hygiene_data.expn_data.push(Some(expn_data));
+
+        let mut expns = outer_expns.lock();
+        let new_len = index as usize + 1;
+        if expns.len() < new_len {
+            expns.resize(new_len, None);
+        }
+        expns[index as usize] = Some(expn_id);
+        drop(expns);
+        expn_id
+    });
+    return Ok(expn_id);
+}
+
+// Decodes `SyntaxContext`, using the provided `HygieneDecodeContext`
+// to track which `SyntaxContext`s we have already decoded.
+// The provided closure will be invoked to deserialize a `SyntaxContextData`
+// if we haven't already seen the id of the `SyntaxContext` we are deserializing.
+pub fn decode_syntax_context<
+    D: Decoder,
+    F: FnOnce(&mut D, u32) -> Result<SyntaxContextData, D::Error>,
+>(
+    d: &mut D,
+    context: &HygieneDecodeContext,
+    decode_data: F,
+) -> Result<SyntaxContext, D::Error> {
+    let raw_id: u32 = Decodable::decode(d)?;
+    if raw_id == 0 {
+        debug!("decode_syntax_context: deserialized root");
+        // The root is special
+        return Ok(SyntaxContext::root());
+    }
+
+    let outer_ctxts = &context.remapped_ctxts;
+
+    // Ensure that the lock() temporary is dropped early
+    {
+        if let Some(ctxt) = outer_ctxts.lock().get(raw_id as usize).copied().flatten() {
+            return Ok(ctxt);
+        }
+    }
+
+    // Allocate and store SyntaxContext id *before* calling the decoder function,
+    // as the SyntaxContextData may reference itself.
+    let new_ctxt = HygieneData::with(|hygiene_data| {
+        let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
+        // Push a dummy SyntaxContextData to ensure that nobody else can get the
+        // same ID as us. This will be overwritten after call `decode_Data`
+        hygiene_data.syntax_context_data.push(SyntaxContextData {
+            outer_expn: ExpnId::root(),
+            outer_transparency: Transparency::Transparent,
+            parent: SyntaxContext::root(),
+            opaque: SyntaxContext::root(),
+            opaque_and_semitransparent: SyntaxContext::root(),
+            dollar_crate_name: kw::Invalid,
+        });
+        let mut ctxts = outer_ctxts.lock();
+        let new_len = raw_id as usize + 1;
+        if ctxts.len() < new_len {
+            ctxts.resize(new_len, None);
+        }
+        ctxts[raw_id as usize] = Some(new_ctxt);
+        drop(ctxts);
+        new_ctxt
+    });
+
+    // Don't try to decode data while holding the lock, since we need to
+    // be able to recursively decode a SyntaxContext
+    let mut ctxt_data = decode_data(d, raw_id)?;
+    // Reset `dollar_crate_name` so that it will be updated by `update_dollar_crate_names`
+    // We don't care what the encoding crate set this to - we want to resolve it
+    // from the perspective of the current compilation session
+    ctxt_data.dollar_crate_name = kw::DollarCrate;
+
+    // Overwrite the dummy data with our decoded SyntaxContextData
+    HygieneData::with(|hygiene_data| {
+        let dummy = std::mem::replace(
+            &mut hygiene_data.syntax_context_data[new_ctxt.as_u32() as usize],
+            ctxt_data,
+        );
+        // Make sure nothing weird happening while `decode_data` was running
+        assert_eq!(dummy.dollar_crate_name, kw::Invalid);
+    });
+
+    return Ok(new_ctxt);
+}
+
+pub fn num_syntax_ctxts() -> usize {
+    HygieneData::with(|data| data.syntax_context_data.len())
+}
+
+pub fn for_all_ctxts_in<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Result<(), E>>(
+    ctxts: impl Iterator<Item = SyntaxContext>,
+    mut f: F,
+) -> Result<(), E> {
+    let all_data: Vec<_> = HygieneData::with(|data| {
+        ctxts.map(|ctxt| (ctxt, data.syntax_context_data[ctxt.0 as usize].clone())).collect()
+    });
+    for (ctxt, data) in all_data.into_iter() {
+        f((ctxt.0, ctxt, &data))?;
     }
+    Ok(())
 }
 
-impl Decodable for ExpnId {
-    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
-        Ok(ExpnId::root()) // FIXME(jseyfried) intercrate hygiene
+pub fn for_all_expns_in<E, F: FnMut(u32, ExpnId, &ExpnData) -> Result<(), E>>(
+    expns: impl Iterator<Item = ExpnId>,
+    mut f: F,
+) -> Result<(), E> {
+    let all_data: Vec<_> = HygieneData::with(|data| {
+        expns.map(|expn| (expn, data.expn_data[expn.0 as usize].clone())).collect()
+    });
+    for (expn, data) in all_data.into_iter() {
+        f(expn.0, expn, &data.unwrap_or_else(|| panic!("Missing data for {:?}", expn)))?;
+    }
+    Ok(())
+}
+pub fn for_all_data<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Result<(), E>>(
+    mut f: F,
+) -> Result<(), E> {
+    let all_data = HygieneData::with(|data| data.syntax_context_data.clone());
+    for (i, data) in all_data.into_iter().enumerate() {
+        f((i as u32, SyntaxContext(i as u32), &data))?;
     }
+    Ok(())
 }
+
+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() {
+        f(i as u32, &data.unwrap_or_else(|| panic!("Missing ExpnData!")))?;
+    }
+    Ok(())
+}
+
+pub fn raw_encode_syntax_context<E: Encoder>(
+    ctxt: SyntaxContext,
+    context: &HygieneEncodeContext,
+    e: &mut E,
+) -> Result<(), E::Error> {
+    if !context.serialized_ctxts.lock().contains(&ctxt) {
+        context.latest_ctxts.lock().insert(ctxt);
+    }
+    ctxt.0.encode(e)
+}
+
+pub fn raw_encode_expn_id<E: Encoder>(
+    expn: ExpnId,
+    context: &HygieneEncodeContext,
+    mode: ExpnDataEncodeMode,
+    e: &mut E,
+) -> Result<(), E::Error> {
+    if !context.serialized_expns.lock().contains(&expn) {
+        context.latest_expns.lock().insert(expn);
+    }
+    match mode {
+        ExpnDataEncodeMode::IncrComp => expn.0.encode(e),
+        ExpnDataEncodeMode::Metadata => {
+            let data = expn.expn_data();
+            data.orig_id.expect("Missing orig_id").encode(e)?;
+            data.krate.encode(e)
+        }
+    }
+}
+
+pub enum ExpnDataEncodeMode {
+    IncrComp,
+    Metadata,
+}
+
+pub enum ExpnDataDecodeMode<'a, F: FnOnce(CrateNum) -> &'a HygieneDecodeContext> {
+    IncrComp(&'a HygieneDecodeContext),
+    Metadata(F),
+}
+
+impl<'a> ExpnDataDecodeMode<'a, Box<dyn FnOnce(CrateNum) -> &'a HygieneDecodeContext>> {
+    pub fn incr_comp(ctxt: &'a HygieneDecodeContext) -> Self {
+        ExpnDataDecodeMode::IncrComp(ctxt)
+    }
+}
+
+impl UseSpecializedEncodable for SyntaxContext {}
+impl UseSpecializedDecodable for SyntaxContext {}
index 666080028c10cfc0ab9c69b9d817eefc7e21cf1b..7087dc80b1daf5a88298301d4106d6af6c4ff1f6 100644 (file)
@@ -12,6 +12,8 @@
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
 #![feature(min_specialization)]
+#![feature(option_expect_none)]
+#![feature(refcell_take)]
 
 // FIXME(#56935): Work around ICEs during cross-compilation.
 #[allow(unused)]
@@ -30,8 +32,8 @@
 use edition::Edition;
 pub mod hygiene;
 pub use hygiene::SyntaxContext;
-use hygiene::Transparency;
 pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind};
+use hygiene::{Transparency, NUM_TRANSPARENCIES};
 pub mod def_id;
 use def_id::{CrateNum, DefId, LOCAL_CRATE};
 mod span_encoding;
@@ -44,7 +46,6 @@
 pub mod fatal_error;
 
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{Lock, Lrc};
 
@@ -86,6 +87,9 @@ pub fn new(edition: Edition) -> SessionGlobals {
     }
 }
 
+// If this ever becomes non thread-local, `decode_syntax_context`
+// and `decode_expn_id` will need to be updated to handle concurrent
+// deserialization.
 scoped_tls::scoped_thread_local!(pub static SESSION_GLOBALS: SessionGlobals);
 
 // FIXME: Perhaps this should not implement Rustc{Decodable, Encodable}
@@ -1733,8 +1737,9 @@ fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize {
 /// This is a hack to allow using the `HashStable_Generic` derive macro
 /// instead of implementing everything in librustc_middle.
 pub trait HashStableContext {
-    fn hash_spans(&self) -> bool;
     fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher);
+    fn hash_crate_num(&mut self, _: CrateNum, hasher: &mut StableHasher);
+    fn hash_spans(&self) -> bool;
     fn byte_pos_to_line_and_col(
         &mut self,
         byte: BytePos,
@@ -1757,15 +1762,14 @@ impl<CTX> HashStable<CTX> for Span
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         const TAG_VALID_SPAN: u8 = 0;
         const TAG_INVALID_SPAN: u8 = 1;
-        const TAG_EXPANSION: u8 = 0;
-        const TAG_NO_EXPANSION: u8 = 1;
 
         if !ctx.hash_spans() {
             return;
         }
 
         if *self == DUMMY_SP {
-            return std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+            std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+            return;
         }
 
         // If this is not an empty or invalid span, we want to hash the last
@@ -1775,12 +1779,16 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         let (file_lo, line_lo, col_lo) = match ctx.byte_pos_to_line_and_col(span.lo) {
             Some(pos) => pos,
             None => {
-                return std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+                std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+                span.ctxt.hash_stable(ctx, hasher);
+                return;
             }
         };
 
         if !file_lo.contains(span.hi) {
-            return std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+            std::hash::Hash::hash(&TAG_INVALID_SPAN, hasher);
+            span.ctxt.hash_stable(ctx, hasher);
+            return;
         }
 
         std::hash::Hash::hash(&TAG_VALID_SPAN, hasher);
@@ -1793,8 +1801,16 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         let len = ((span.hi - span.lo).0 as u64) << 32;
         let line_col_len = col | line | len;
         std::hash::Hash::hash(&line_col_len, hasher);
+        span.ctxt.hash_stable(ctx, hasher);
+    }
+}
 
-        if span.ctxt == SyntaxContext::root() {
+impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        const TAG_EXPANSION: u8 = 0;
+        const TAG_NO_EXPANSION: u8 = 1;
+
+        if *self == SyntaxContext::root() {
             TAG_NO_EXPANSION.hash_stable(ctx, hasher);
         } else {
             TAG_EXPANSION.hash_stable(ctx, hasher);
@@ -1803,21 +1819,39 @@ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
             // times, we cache a stable hash of it and hash that instead of
             // recursing every time.
             thread_local! {
-                static CACHE: RefCell<FxHashMap<hygiene::ExpnId, u64>> = Default::default();
+                static CACHE: RefCell<Vec<Option<[Option<u64>; NUM_TRANSPARENCIES]>>> = Default::default();
             }
 
             let sub_hash: u64 = CACHE.with(|cache| {
-                let expn_id = span.ctxt.outer_expn();
+                let (expn_id, transparency, _) = self.outer_mark_with_data();
+                let index = expn_id.as_u32() as usize;
 
-                if let Some(&sub_hash) = cache.borrow().get(&expn_id) {
-                    return sub_hash;
+                if let Some(sub_hash_cache) = cache.borrow().get(index).copied().flatten() {
+                    if let Some(sub_hash) = sub_hash_cache[transparency as usize] {
+                        return sub_hash;
+                    }
                 }
 
+                let new_len = index + 1;
+
                 let mut hasher = StableHasher::new();
                 expn_id.expn_data().hash_stable(ctx, &mut hasher);
+                transparency.hash_stable(ctx, &mut hasher);
+
                 let sub_hash: Fingerprint = hasher.finish();
                 let sub_hash = sub_hash.to_smaller_hash();
-                cache.borrow_mut().insert(expn_id, sub_hash);
+
+                let mut cache = cache.borrow_mut();
+                if cache.len() < new_len {
+                    cache.resize(new_len, None);
+                }
+                if let Some(mut sub_hash_cache) = cache[index] {
+                    sub_hash_cache[transparency as usize] = Some(sub_hash);
+                } else {
+                    let mut sub_hash_cache = [None; NUM_TRANSPARENCIES];
+                    sub_hash_cache[transparency as usize] = Some(sub_hash);
+                    cache[index] = Some(sub_hash_cache);
+                }
                 sub_hash
             });
 
index 5d332ddf5f3df1ccecf1165219bd67d875fdd1b9..dadf040304d4683b81d22cad0295ae3650dc12f6 100644 (file)
         minnumf32,
         minnumf64,
         mips_target_feature,
-        miri_start_panic,
         mmx_target_feature,
         module,
         module_path,
         rustc_peek_liveness,
         rustc_peek_maybe_init,
         rustc_peek_maybe_uninit,
+        rustc_polymorphize_error,
         rustc_private,
         rustc_proc_macro_decls,
         rustc_promotable,
index 3038b0c6bd7eb26062d824e718fc07b16381f881..90c89ea6b0a86243b8be7e564c50abb1a5c139a8 100644 (file)
@@ -116,7 +116,6 @@ fn get_symbol_hash<'tcx>(
 
         // also include any type parameters (for generic items)
         assert!(!substs.has_erasable_regions());
-        assert!(!substs.needs_subst());
         substs.hash_stable(&mut hcx, &mut hasher);
 
         if let Some(instantiating_crate) = instantiating_crate {
index c79e9bb28900882ed0a41860f628a477d56b16a8..b3e5f5c0c74b163e90d55d521ac17a93e1050059 100644 (file)
@@ -32,7 +32,7 @@ pub struct TargetDataLayout {
     /// Alignments for vector types.
     pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
 
-    pub instruction_address_space: u32,
+    pub instruction_address_space: AddressSpace,
 }
 
 impl Default for TargetDataLayout {
@@ -56,7 +56,7 @@ fn default() -> TargetDataLayout {
                 (Size::from_bits(64), AbiAndPrefAlign::new(align(64))),
                 (Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
             ],
-            instruction_address_space: 0,
+            instruction_address_space: AddressSpace::DATA,
         }
     }
 }
@@ -65,7 +65,7 @@ impl TargetDataLayout {
     pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
         // Parse an address space index from a string.
         let parse_address_space = |s: &str, cause: &str| {
-            s.parse::<u32>().map_err(|err| {
+            s.parse::<u32>().map(AddressSpace).map_err(|err| {
                 format!("invalid address space `{}` for `{}` in \"data-layout\": {}", s, cause, err)
             })
         };
@@ -744,6 +744,17 @@ pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item = usize> +
     }
 }
 
+/// An identifier that specifies the address space that some operation
+/// should operate on. Special address spaces have an effect on code generation,
+/// depending on the target and the address spaces it implements.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct AddressSpace(pub u32);
+
+impl AddressSpace {
+    /// The default address space, corresponding to data space.
+    pub const DATA: Self = AddressSpace(0);
+}
+
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
 #[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
@@ -1013,7 +1024,7 @@ fn to_result(self) -> Result<T, Self::Error> {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
     /// Most general case, we know no restrictions to tell LLVM.
     Shared,
@@ -1028,11 +1039,12 @@ pub enum PointerKind {
     UniqueOwned,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub struct PointeeInfo {
     pub size: Size,
     pub align: Align,
     pub safe: Option<PointerKind>,
+    pub address_space: AddressSpace,
 }
 
 pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
diff --git a/src/librustc_target/build.rs b/src/librustc_target/build.rs
deleted file mode 100644 (file)
index 368200b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-env-changed=CFG_DEFAULT_LINKER");
-}
diff --git a/src/librustc_target/spec/aarch64_apple_darwin.rs b/src/librustc_target/spec/aarch64_apple_darwin.rs
new file mode 100644 (file)
index 0000000..60daf10
--- /dev/null
@@ -0,0 +1,30 @@
+use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::apple_base::opts();
+    base.cpu = "apple-a12".to_string();
+    base.max_atomic_width = Some(128);
+    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
+
+    base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
+
+    // Clang automatically chooses a more specific target based on
+    // MACOSX_DEPLOYMENT_TARGET.  To enable cross-language LTO to work
+    // correctly, we do too.
+    let arch = "aarch64";
+    let llvm_target = super::apple_base::macos_llvm_target(&arch);
+
+    Ok(Target {
+        llvm_target,
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: arch.to_string(),
+        target_os: "macos".to_string(),
+        target_env: String::new(),
+        target_vendor: "apple".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: TargetOptions { target_mcount: "\u{1}mcount".to_string(), ..base },
+    })
+}
index bdd5a893d34e2c19c1a300b986010ceb32fd2736..e7b565ae9cad979a7741b6509713db4ae8157d9f 100644 (file)
@@ -31,6 +31,7 @@ pub fn opts() -> TargetOptions {
         has_elf_tls: version >= (10, 7),
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
+        eh_frame_header: false,
 
         // This environment variable is pretty magical but is intended for
         // producing deterministic builds. This was first discovered to be used
index 5402ea074fae1ee891c64a17560783761408ff6e..c338856228dc66b607304672531fe61243f4b3ce 100644 (file)
@@ -25,6 +25,7 @@ pub fn opts() -> TargetOptions {
         has_rpath: false,
         pre_link_args: args,
         position_independent_executables: false,
+        eh_frame_header: false,
         ..Default::default()
     }
 }
index 35ac346fb3f6f1586d6f32167aa00b04a9c1be41..214142b88fc2c7721f6617ba6e999abdbb6d0c25 100644 (file)
@@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
         is_like_solaris: true,
         limit_rdylib_exports: false, // Linker doesn't support this
         eliminate_frame_pointer: false,
+        eh_frame_header: false,
         late_link_args,
 
         // While we support ELF TLS, rust requires a way to register
index d53033ba3ba2043d79e4330df412e17455f5f782..961a438fd233cc175c5019a5d984ab5a0eb2de58 100644 (file)
@@ -574,6 +574,7 @@ fn $module() {
     ("i686-unknown-haiku", i686_unknown_haiku),
     ("x86_64-unknown-haiku", x86_64_unknown_haiku),
 
+    ("aarch64-apple-darwin", aarch64_apple_darwin),
     ("x86_64-apple-darwin", x86_64_apple_darwin),
     ("i686-apple-darwin", i686_apple_darwin),
 
@@ -987,6 +988,11 @@ pub struct TargetOptions {
     /// Whether to use legacy .ctors initialization hooks rather than .init_array. Defaults
     /// to false (uses .init_array).
     pub use_ctors_section: bool,
+
+    /// Whether the linker is instructed to add a `GNU_EH_FRAME` ELF header
+    /// used to locate unwinding information is passed
+    /// (only has effect if the linker is `ld`-like).
+    pub eh_frame_header: bool,
 }
 
 impl Default for TargetOptions {
@@ -1078,6 +1084,7 @@ fn default() -> TargetOptions {
             relax_elf_relocations: false,
             llvm_args: vec![],
             use_ctors_section: false,
+            eh_frame_header: true,
         }
     }
 }
@@ -1470,6 +1477,7 @@ macro_rules! key {
         key!(relax_elf_relocations, bool);
         key!(llvm_args, list);
         key!(use_ctors_section, bool);
+        key!(eh_frame_header, bool);
 
         // NB: The old name is deprecated, but support for it is retained for
         // compatibility.
@@ -1707,6 +1715,7 @@ macro_rules! target_option_val {
         target_option_val!(relax_elf_relocations);
         target_option_val!(llvm_args);
         target_option_val!(use_ctors_section);
+        target_option_val!(eh_frame_header);
 
         if default.unsupported_abis != self.options.unsupported_abis {
             d.insert(
index c6d0308f8f82feec5ef3022e3dab8b44a304cb12..f75697996ac7863870e02b78052bc5a09c613945 100644 (file)
@@ -56,6 +56,8 @@ pub fn target() -> TargetResult {
             // See the thumb_base.rs file for an explanation of this value
             emit_debug_gdb_scripts: false,
 
+            eh_frame_header: false,
+
             ..Default::default()
         },
     })
index 977aa896f2520573df84a8c8b7eea9b708f7d078..5b5e342000b55d70d486a0bc508215ef983e3785 100644 (file)
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             unsupported_abis: super::riscv_base::unsupported_abis(),
+            eh_frame_header: false,
             ..Default::default()
         },
     })
index 1a85cdff1315ca0f41a4fc2b1b2a89fd3ad606df..4cef5c42d8ddfc8c54d5036280a3fcd38402c563 100644 (file)
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             unsupported_abis: super::riscv_base::unsupported_abis(),
+            eh_frame_header: false,
             ..Default::default()
         },
     })
index e3c1c6908a23af24a13cba44b2bf421fe0bf3a0c..8ad563e441de3183345e829804e9c2befbdf814a 100644 (file)
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
             relocation_model: RelocModel::Static,
             emit_debug_gdb_scripts: false,
             unsupported_abis: super::riscv_base::unsupported_abis(),
+            eh_frame_header: false,
             ..Default::default()
         },
     })
index 857af4ceb0d9f1635a8e3cfbd9af18b07720372a..3aeb3f3ca72b2beef3b33f89641cc4a398105bcf 100644 (file)
@@ -26,6 +26,7 @@ pub fn target() -> TargetResult {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             unsupported_abis: super::riscv_base::unsupported_abis(),
+            eh_frame_header: false,
             ..Default::default()
         },
     })
index 36fe7730f95bfcaea3837c556d2a93683ea804e5..d8144964dc913277ea849a163e7dd68a55c51baf 100644 (file)
@@ -26,6 +26,7 @@ pub fn target() -> TargetResult {
             code_model: Some(CodeModel::Medium),
             emit_debug_gdb_scripts: false,
             unsupported_abis: super::riscv_base::unsupported_abis(),
+            eh_frame_header: false,
             ..Default::default()
         },
     })
index 8d3a3563f4164a87fc6de8803e52be11da28a16f..3d7f0034b8b10dd128f5311102e431d93dcc9f2b 100644 (file)
@@ -8,6 +8,7 @@ pub fn opts() -> TargetOptions {
         target_family: Some("unix".to_string()),
         is_like_solaris: true,
         limit_rdylib_exports: false, // Linker doesn't support this
+        eh_frame_header: false,
 
         ..Default::default()
     }
index 680dbbad4b0a02e91f0bc76ef1570f0f82d7b156..69236e98e58d7890befe267b1076a2cfd6268f23 100644 (file)
@@ -91,6 +91,7 @@ pub fn opts() -> TargetOptions {
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         requires_uwtable: true,
+        eh_frame_header: false,
 
         ..Default::default()
     }
index 31011e847495838d3a1083b6449c88942052b0f9..909aebec70b58766a1f26d55b7f6b2828903049e 100644 (file)
@@ -5,7 +5,10 @@ pub fn target() -> TargetResult {
     base.cpu = "core2".to_string();
     base.max_atomic_width = Some(128); // core2 support cmpxchg16b
     base.eliminate_frame_pointer = false;
-    base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
+    base.pre_link_args.insert(
+        LinkerFlavor::Gcc,
+        vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
+    );
     base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
     base.stack_probes = true;
 
index cf575d3eca9c226853e7481af7b0b728f180a0ae..dd7ea55cc1043693be0a1e0e96399a602c21c32e 100644 (file)
@@ -6,6 +6,7 @@
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::{
     FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
+    Unimplemented,
 };
 use rustc_errors::ErrorReported;
 use rustc_middle::ty::fold::TypeFoldable;
@@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>(
                 );
                 return Err(ErrorReported);
             }
+            Err(Unimplemented) => {
+                // This can trigger when we probe for the source of a `'static` lifetime requirement
+                // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
+                infcx.tcx.sess.delay_span_bug(
+                    rustc_span::DUMMY_SP,
+                    &format!(
+                        "Encountered error `Unimplemented` selecting `{:?}` during codegen",
+                        trait_ref
+                    ),
+                );
+                return Err(ErrorReported);
+            }
             Err(e) => {
                 bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
             }
index 3ec7fe2bf25c68f2635fb64f117a8487ee374bde..b06cf4411d053188e80f90188b4ea1c5125a526f 100644 (file)
@@ -289,11 +289,11 @@ pub fn orphan_check(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Result<(), OrphanChe
 ///     - but (knowing that `Vec<T>` is non-fundamental, and assuming it's
 ///       not local), `Vec<LocalType>` is bad, because `Vec<->` is between
 ///       the local type and the type parameter.
-/// 3. Every type parameter before the local key parameter is fully known in C.
-///     - e.g., `impl<T> T: Trait<LocalType>` is bad, because `T` might be
-///       an unknown type.
-///     - but `impl<T> LocalType: Trait<T>` is OK, because `LocalType`
-///       occurs before `T`.
+/// 3. Before this local type, no generic type parameter of the impl must
+///    be reachable through fundamental types.
+///     - e.g. `impl<T> Trait<LocalType> for Vec<T>` is fine, as `Vec` is not fundamental.
+///     - while `impl<T> Trait<LocalType for Box<T>` results in an error, as `T` is
+///       reachable through the fundamental type `Box`.
 /// 4. Every type in the local key parameter not known in C, going
 ///    through the parameter's type tree, must appear only as a subtree of
 ///    a type local to C, with only fundamental types between the type
@@ -387,9 +387,9 @@ fn uncover_fundamental_ty<'tcx>(
         ty: Ty<'tcx>,
         in_crate: InCrate,
     ) -> Vec<Ty<'tcx>> {
-        // FIXME(eddyb) figure out if this is redundant with `ty_is_non_local`,
-        // or maybe if this should be calling `ty_is_non_local_constructor`.
-        if ty_is_non_local(tcx, ty, in_crate).is_some() {
+        // FIXME: this is currently somewhat overly complicated,
+        // but fixing this requires a more complicated refactor.
+        if !contained_non_local_types(tcx, ty, in_crate).is_empty() {
             if let Some(inner_tys) = fundamental_ty_inner_tys(tcx, ty) {
                 return inner_tys
                     .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
@@ -408,8 +408,8 @@ fn uncover_fundamental_ty<'tcx>(
         .enumerate()
     {
         debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
-        let non_local_tys = ty_is_non_local(tcx, input_ty, in_crate);
-        if non_local_tys.is_none() {
+        let non_local_tys = contained_non_local_types(tcx, input_ty, in_crate);
+        if non_local_tys.is_empty() {
             debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
             return Ok(());
         } else if let ty::Param(_) = input_ty.kind {
@@ -418,16 +418,15 @@ fn uncover_fundamental_ty<'tcx>(
                 .substs
                 .types()
                 .flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
-                .find(|ty| ty_is_non_local_constructor(ty, in_crate).is_none());
+                .find(|ty| ty_is_local_constructor(ty, in_crate));
 
             debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
 
             return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type));
         }
-        if let Some(non_local_tys) = non_local_tys {
-            for input_ty in non_local_tys {
-                non_local_spans.push((input_ty, i == 0));
-            }
+
+        for input_ty in non_local_tys {
+            non_local_spans.push((input_ty, i == 0));
         }
     }
     // If we exit above loop, never found a local type.
@@ -435,20 +434,29 @@ fn uncover_fundamental_ty<'tcx>(
     Err(OrphanCheckErr::NonLocalInputType(non_local_spans))
 }
 
-fn ty_is_non_local(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) -> Option<Vec<Ty<'tcx>>> {
-    match ty_is_non_local_constructor(ty, in_crate) {
-        Some(ty) => {
-            if let Some(inner_tys) = fundamental_ty_inner_tys(tcx, ty) {
-                let tys: Vec<_> = inner_tys
-                    .filter_map(|ty| ty_is_non_local(tcx, ty, in_crate))
-                    .flatten()
-                    .collect();
-                if tys.is_empty() { None } else { Some(tys) }
-            } else {
-                Some(vec![ty])
+/// Returns a list of relevant non-local types for `ty`.
+///
+/// This is just `ty` itself unless `ty` is `#[fundamental]`,
+/// in which case we recursively look into this type.
+///
+/// If `ty` is local itself, this method returns an empty `Vec`.
+///
+/// # Examples
+///
+/// - `u32` is not local, so this returns `[u32]`.
+/// - for `Foo<u32>`, where `Foo` is a local type, this returns `[]`.
+/// - `&mut u32` returns `[u32]`, as `&mut` is a fundamental type, similar to `Box`.
+/// - `Box<Foo<u32>>` returns `[]`, as `Box` is a fundamental type and `Foo` is local.
+fn contained_non_local_types(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec<Ty<'tcx>> {
+    if ty_is_local_constructor(ty, in_crate) {
+        Vec::new()
+    } else {
+        match fundamental_ty_inner_tys(tcx, ty) {
+            Some(inner_tys) => {
+                inner_tys.flat_map(|ty| contained_non_local_types(tcx, ty, in_crate)).collect()
             }
+            None => vec![ty],
         }
-        None => None,
     }
 }
 
@@ -493,9 +501,8 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
     }
 }
 
-// FIXME(eddyb) this can just return `bool` as it always returns `Some(ty)` or `None`.
-fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>> {
-    debug!("ty_is_non_local_constructor({:?})", ty);
+fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
+    debug!("ty_is_local_constructor({:?})", ty);
 
     match ty.kind {
         ty::Bool
@@ -513,29 +520,17 @@ fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>>
         | ty::Never
         | ty::Tuple(..)
         | ty::Param(..)
-        | ty::Projection(..) => Some(ty),
+        | ty::Projection(..) => false,
 
         ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
-            InCrate::Local => Some(ty),
+            InCrate::Local => false,
             // The inference variable might be unified with a local
             // type in that remote crate.
-            InCrate::Remote => None,
+            InCrate::Remote => true,
         },
 
-        ty::Adt(def, _) => {
-            if def_id_is_local(def.did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
-        ty::Foreign(did) => {
-            if def_id_is_local(did, in_crate) {
-                None
-            } else {
-                Some(ty)
-            }
-        }
+        ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
+        ty::Foreign(did) => def_id_is_local(did, in_crate),
         ty::Opaque(..) => {
             // This merits some explanation.
             // Normally, opaque types are not involed when performing
@@ -553,7 +548,7 @@ fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>>
             // the underlying type *within the same crate*. When an
             // opaque type is used from outside the module
             // where it is declared, it should be impossible to observe
-            // anyything about it other than the traits that it implements.
+            // anything about it other than the traits that it implements.
             //
             // The alternative would be to look at the underlying type
             // to determine whether or not the opaque type itself should
@@ -562,18 +557,18 @@ fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option<Ty<'_>>
             // to a remote type. This would violate the rule that opaque
             // types should be completely opaque apart from the traits
             // that they implement, so we don't use this behavior.
-            Some(ty)
+            false
         }
 
         ty::Dynamic(ref tt, ..) => {
             if let Some(principal) = tt.principal() {
-                if def_id_is_local(principal.def_id(), in_crate) { None } else { Some(ty) }
+                def_id_is_local(principal.def_id(), in_crate)
             } else {
-                Some(ty)
+                false
             }
         }
 
-        ty::Error(_) => None,
+        ty::Error(_) => true,
 
         ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
index 0a6fb72ca51eae890af70698ac34d8b50d788cf9..0632ce2319aeef1d462898e2537243cbcd7f0d42 100644 (file)
@@ -1706,6 +1706,7 @@ fn note_obligation_cause_code<T>(
             | ObligationCauseCode::IntrinsicType
             | ObligationCauseCode::MethodReceiver
             | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::UnifyReceiver(..)
             | ObligationCauseCode::MiscObligation => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
index e8006129e3ef8666f8148c34c7f185a97cbe282e..1c3755222495e28585dbb4d83efb2d57de7b8ee9 100644 (file)
@@ -418,15 +418,14 @@ pub fn fully_normalize<'a, 'tcx, T>(
     Ok(resolved_value)
 }
 
-/// Normalizes the predicates and checks whether they hold in an empty
-/// environment. If this returns false, then either normalize
-/// encountered an error or one of the predicates did not hold. Used
-/// when creating vtables to check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'tcx>(
+/// Normalizes the predicates and checks whether they hold in an empty environment. If this
+/// returns true, then either normalize encountered an error or one of the predicates did not
+/// hold. Used when creating vtables to check for unsatisfiable methods.
+pub fn impossible_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     predicates: Vec<ty::Predicate<'tcx>>,
 ) -> bool {
-    debug!("normalize_and_test_predicates(predicates={:?})", predicates);
+    debug!("impossible_predicates(predicates={:?})", predicates);
 
     let result = tcx.infer_ctxt().enter(|infcx| {
         let param_env = ty::ParamEnv::reveal_all();
@@ -443,22 +442,23 @@ pub fn normalize_and_test_predicates<'tcx>(
             fulfill_cx.register_predicate_obligation(&infcx, obligation);
         }
 
-        fulfill_cx.select_all_or_error(&infcx).is_ok()
+        fulfill_cx.select_all_or_error(&infcx).is_err()
     });
-    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}", predicates, result);
+    debug!("impossible_predicates(predicates={:?}) = {:?}", predicates, result);
     result
 }
 
-fn substitute_normalize_and_test_predicates<'tcx>(
+fn subst_and_check_impossible_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: (DefId, SubstsRef<'tcx>),
 ) -> bool {
-    debug!("substitute_normalize_and_test_predicates(key={:?})", key);
+    debug!("subst_and_check_impossible_predicates(key={:?})", key);
 
-    let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    let result = normalize_and_test_predicates(tcx, predicates);
+    let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
+    predicates.retain(|predicate| !predicate.needs_subst());
+    let result = impossible_predicates(tcx, predicates);
 
-    debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
+    debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
     result
 }
 
@@ -510,7 +510,7 @@ fn vtable_methods<'tcx>(
             // Note that this method could then never be called, so we
             // do not want to try and codegen it, in that case (see #23435).
             let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-            if !normalize_and_test_predicates(tcx, predicates.predicates) {
+            if impossible_predicates(tcx, predicates.predicates) {
                 debug!("vtable_methods: predicates do not hold");
                 return None;
             }
@@ -558,8 +558,8 @@ pub fn provide(providers: &mut ty::query::Providers) {
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
         vtable_methods,
-        substitute_normalize_and_test_predicates,
         type_implements_trait,
+        subst_and_check_impossible_predicates,
         ..*providers
     };
 }
index b8446fa0012abc9a05ec9c2c87c7c0008e906e61..0e445e1e53bba36d23cca707c7a239e0bc2ccbbe 100644 (file)
@@ -300,13 +300,21 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
             trait_ref
                 .substs
                 .iter()
-                .filter(|arg| {
+                .enumerate()
+                .filter(|(_, arg)| {
                     matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
                 })
-                .filter(|arg| !arg.has_escaping_bound_vars())
-                .map(|arg| {
+                .filter(|(_, arg)| !arg.has_escaping_bound_vars())
+                .map(|(i, arg)| {
+                    let mut new_cause = cause.clone();
+                    // The first subst is the self ty - use the correct span for it.
+                    if i == 0 {
+                        if let Some(hir::ItemKind::Impl { self_ty, .. }) = item.map(|i| &i.kind) {
+                            new_cause.make_mut().span = self_ty.span;
+                        }
+                    }
                     traits::Obligation::new(
-                        cause.clone(),
+                        new_cause,
                         param_env,
                         ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
                     )
index 0bc6c4709786833e4b0ac3eeead6554635e9a579..324ae4ec29e9b9cd7eb75a243e0069b15495bb16 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
-use rustc_span::sym;
+use rustc_span::{sym, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
@@ -67,12 +67,19 @@ fn inner_resolve_instance<'tcx>(
                 let ty = substs.type_at(0);
 
                 if ty.needs_drop(tcx, param_env) {
-                    // `DropGlue` requires a monomorphic aka concrete type.
-                    if ty.needs_subst() {
-                        return Ok(None);
+                    debug!(" => nontrivial drop glue");
+                    match ty.kind {
+                        ty::Closure(..)
+                        | ty::Generator(..)
+                        | ty::Tuple(..)
+                        | ty::Adt(..)
+                        | ty::Dynamic(..)
+                        | ty::Array(..)
+                        | ty::Slice(..) => {}
+                        // Drop shims can only be built from ADTs.
+                        _ => return Ok(None),
                     }
 
-                    debug!(" => nontrivial drop glue");
                     ty::InstanceDef::DropGlue(def_id, Some(ty))
                 } else {
                     debug!(" => trivial drop glue");
@@ -224,17 +231,13 @@ fn resolve_associated_item<'tcx>(
                 trait_closure_kind,
             ))
         }
-        traits::ImplSourceFnPointer(ref data) => {
-            // `FnPtrShim` requires a monomorphic aka concrete type.
-            if data.fn_ty.needs_subst() {
-                return Ok(None);
-            }
-
-            Some(Instance {
+        traits::ImplSourceFnPointer(ref data) => match data.fn_ty.kind {
+            ty::FnDef(..) | ty::FnPtr(..) => Some(Instance {
                 def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
                 substs: rcvr_substs,
-            })
-        }
+            }),
+            _ => None,
+        },
         traits::ImplSourceObject(ref data) => {
             let index = traits::get_vtable_index_of_object_method(tcx, data, def_id);
             Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs })
@@ -246,10 +249,12 @@ fn resolve_associated_item<'tcx>(
                 if name == sym::clone {
                     let self_ty = trait_ref.self_ty();
 
-                    // `CloneShim` requires a monomorphic aka concrete type.
-                    if self_ty.needs_subst() {
-                        return Ok(None);
-                    }
+                    let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
+                    match self_ty.kind {
+                        _ if is_copy => (),
+                        ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {}
+                        _ => return Ok(None),
+                    };
 
                     Some(Instance {
                         def: ty::InstanceDef::CloneShim(def_id, self_ty),
index 37f48f82ea6746176b0745a8f2691720caa34331..e6d59d30e2f585331ba3bff358cf7e50acd16602 100644 (file)
@@ -1485,28 +1485,33 @@ fn add_predicates_for_ast_type_binding(
                 debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
                 for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) {
                     let br_name = match *br {
-                        ty::BrNamed(_, name) => name,
-                        _ => {
-                            span_bug!(
-                                binding.span,
-                                "anonymous bound region {:?} in binding but not trait ref",
-                                br
-                            );
-                        }
+                        ty::BrNamed(_, name) => format!("lifetime `{}`", name),
+                        _ => "an anonymous lifetime".to_string(),
                     };
                     // FIXME: point at the type params that don't have appropriate lifetimes:
                     // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
                     //                         ----  ----     ^^^^^^^
-                    struct_span_err!(
+                    let mut err = struct_span_err!(
                         tcx.sess,
                         binding.span,
                         E0582,
-                        "binding for associated type `{}` references lifetime `{}`, \
+                        "binding for associated type `{}` references {}, \
                          which does not appear in the trait input types",
                         binding.item_name,
                         br_name
-                    )
-                    .emit();
+                    );
+
+                    if let ty::BrAnon(_) = *br {
+                        // The only way for an anonymous lifetime to wind up
+                        // in the return type but **also** be unconstrained is
+                        // if it only appears in "associated types" in the
+                        // input. See #62200 for an example. In this case,
+                        // though we can easily give a hint that ought to be
+                        // relevant.
+                        err.note("lifetimes appearing in an associated type are not considered constrained");
+                    }
+
+                    err.emit();
                 }
             }
         }
index a90ed455d048b722f4ae533df8205254be2f9a05..b739e2fe1fbc4ffecb0aed169e2a8064bf34526d 100644 (file)
@@ -6,15 +6,14 @@
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::util::ExplicitSelf;
-use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt, WithConstness};
+use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
-use std::iter;
 
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
@@ -1196,8 +1195,6 @@ fn compare_projection_bounds<'tcx>(
         return Ok(());
     }
 
-    let param_env = tcx.param_env(impl_ty.def_id);
-
     // Given
     //
     // impl<A, B> Foo<u32> for (A, B) {
@@ -1212,20 +1209,30 @@ fn compare_projection_bounds<'tcx>(
         impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
     let impl_ty_value = tcx.type_of(impl_ty.def_id);
 
-    // Map the predicate from the trait to the corresponding one for the impl.
-    // For example:
+    let param_env = tcx.param_env(impl_ty.def_id);
+
+    // When checking something like
     //
-    // trait X<A> { type Y<'a>: PartialEq<A> } impl X for T { type Y<'a> = &'a S; }
-    // impl<'x> X<&'x u32> for () { type Y<'c> = &'c u32; }
+    // trait X { type Y: PartialEq<<Self as X>::Y> }
+    // impl X for T { default type Y = S; }
     //
-    // For the `for<'a> <<Self as X<A>>::Y<'a>: PartialEq<A>` bound, this
-    // function would translate and partially normalize
-    // `[<Self as X<A>>::Y<'a>, A]` to `[&'a u32, &'x u32]`.
-    let translate_predicate_substs = move |predicate_substs: SubstsRef<'tcx>| {
-        tcx.mk_substs(
-            iter::once(impl_ty_value.into())
-                .chain(predicate_substs[1..].iter().map(|s| s.subst(tcx, rebased_substs))),
-        )
+    // We will have to prove the bound S: PartialEq<<T as X>::Y>. In this case
+    // we want <T as X>::Y to normalize to S. This is valid because we are
+    // checking the default value specifically here. Add this equality to the
+    // ParamEnv for normalization specifically.
+    let normalize_param_env = {
+        let mut predicates = param_env.caller_bounds().iter().collect::<Vec<_>>();
+        predicates.push(
+            ty::Binder::dummy(ty::ProjectionPredicate {
+                projection_ty: ty::ProjectionTy {
+                    item_def_id: trait_ty.def_id,
+                    substs: rebased_substs,
+                },
+                ty: impl_ty_value,
+            })
+            .to_predicate(tcx),
+        );
+        ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing, None)
     };
 
     tcx.infer_ctxt().enter(move |infcx| {
@@ -1242,46 +1249,18 @@ fn compare_projection_bounds<'tcx>(
         );
 
         let predicates = tcx.projection_predicates(trait_ty.def_id);
-
         debug!("compare_projection_bounds: projection_predicates={:?}", predicates);
 
         for predicate in predicates {
-            let concrete_ty_predicate = match predicate.kind() {
-                ty::PredicateKind::Trait(poly_tr, c) => poly_tr
-                    .map_bound(|tr| {
-                        let trait_substs = translate_predicate_substs(tr.trait_ref.substs);
-                        ty::TraitRef { def_id: tr.def_id(), substs: trait_substs }
-                    })
-                    .with_constness(*c)
-                    .to_predicate(tcx),
-                ty::PredicateKind::Projection(poly_projection) => poly_projection
-                    .map_bound(|projection| {
-                        let projection_substs =
-                            translate_predicate_substs(projection.projection_ty.substs);
-                        ty::ProjectionPredicate {
-                            projection_ty: ty::ProjectionTy {
-                                substs: projection_substs,
-                                item_def_id: projection.projection_ty.item_def_id,
-                            },
-                            ty: projection.ty.subst(tcx, rebased_substs),
-                        }
-                    })
-                    .to_predicate(tcx),
-                ty::PredicateKind::TypeOutlives(poly_outlives) => poly_outlives
-                    .map_bound(|outlives| {
-                        ty::OutlivesPredicate(impl_ty_value, outlives.1.subst(tcx, rebased_substs))
-                    })
-                    .to_predicate(tcx),
-                _ => bug!("unexepected projection predicate kind: `{:?}`", predicate),
-            };
+            let concrete_ty_predicate = predicate.subst(tcx, rebased_substs);
+            debug!("compare_projection_bounds: concrete predicate = {:?}", concrete_ty_predicate);
 
             let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
                 &mut selcx,
-                param_env,
+                normalize_param_env,
                 normalize_cause.clone(),
                 &concrete_ty_predicate,
             );
-
             debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
 
             inh.register_predicates(obligations);
index 63c100d5fad4f17bd399cdea8c571f6459621275..e7eaca62bdd8e31c6fcf5e1fdb861ab221cde7c2 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_ast::ast;
 use rustc_ast::util::lev_distance::find_best_match_for_name;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
@@ -177,7 +178,7 @@ pub(super) fn check_expr_with_expectation(
         let old_diverges = self.diverges.replace(Diverges::Maybe);
         let old_has_errors = self.has_errors.replace(false);
 
-        let ty = self.check_expr_kind(expr, expected);
+        let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected));
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
index a09edf575c8072b17370bd3461048b8eb58b1e99..dc2172650e574d298b1196f0eecdf2999f64f4fb 100644 (file)
@@ -379,12 +379,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
 
             sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
-            sym::miri_start_panic => {
-                // FIXME - the relevant types aren't lang items,
-                // so it's not trivial to check this
-                return;
-            }
-
             sym::count_code_region => {
                 (0, vec![tcx.types.u64, tcx.types.u32, tcx.types.u32, tcx.types.u32], tcx.mk_unit())
             }
index 96248e18aaf87a44fb6b9be380a14c112dfbd38d..ed84095ae6b0cbc4a5a6d7094edb3eea07cd9509 100644 (file)
@@ -6,6 +6,7 @@
 use crate::hir::GenericArg;
 use rustc_hir as hir;
 use rustc_infer::infer::{self, InferOk};
+use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::fold::TypeFoldable;
@@ -91,7 +92,11 @@ fn confirm(
         // signature (which is also done during probing).
         let method_sig_rcvr =
             self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
-        self.unify_receivers(self_ty, method_sig_rcvr);
+        debug!(
+            "confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
+            self_ty, method_sig_rcvr, method_sig, method_predicates
+        );
+        self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);
 
         let (method_sig, method_predicates) =
             self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
@@ -150,7 +155,7 @@ fn adjust_self_ty(
             self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
 
         if let Some(mutbl) = pick.autoref {
-            let region = self.next_region_var(infer::Autoref(self.span));
+            let region = self.next_region_var(infer::Autoref(self.span, pick.item));
             target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
             let mutbl = match mutbl {
                 hir::Mutability::Not => AutoBorrowMutability::Not,
@@ -334,8 +339,26 @@ fn instantiate_method_substs(
         )
     }
 
-    fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
-        match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) {
+    fn unify_receivers(
+        &mut self,
+        self_ty: Ty<'tcx>,
+        method_self_ty: Ty<'tcx>,
+        pick: &probe::Pick<'tcx>,
+        substs: SubstsRef<'tcx>,
+    ) {
+        debug!(
+            "unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
+            self_ty, method_self_ty, self.span, pick
+        );
+        let cause = self.cause(
+            self.span,
+            ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
+                assoc_item: pick.item,
+                param_env: self.param_env,
+                substs,
+            })),
+        );
+        match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
index 04e02704296defd79c3b2a8cbfc98eaee84c2eaf..6e77aba30506a5ba89c946207752d7be27d7745a 100644 (file)
@@ -256,14 +256,6 @@ pub struct Inherited<'a, 'tcx> {
     /// opaque type.
     opaque_types_vars: RefCell<FxHashMap<Ty<'tcx>, Ty<'tcx>>>,
 
-    /// Each type parameter has an implicit region bound that
-    /// indicates it must outlive at least the function body (the user
-    /// may specify stronger requirements). This field indicates the
-    /// region of the callee. If it is `None`, then the parameter
-    /// environment is for an item or something where the "callee" is
-    /// not clear.
-    implicit_region_bound: Option<ty::Region<'tcx>>,
-
     body_id: Option<hir::BodyId>,
 }
 
@@ -684,7 +676,6 @@ fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
             deferred_generator_interiors: RefCell::new(Vec::new()),
             opaque_types: RefCell::new(Default::default()),
             opaque_types_vars: RefCell::new(Default::default()),
-            implicit_region_bound: None,
             body_id,
         }
     }
index b72152d1911f7dc5851f627149f7d5d1205335aa..221e5f72dc977b135d5a263212ecf5094d187285 100644 (file)
@@ -309,7 +309,7 @@ fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
     fn resolve_regions_and_report_errors(&self, mode: RegionckMode) {
         self.infcx.process_registered_region_obligations(
             self.outlives_environment.region_bound_pairs_map(),
-            self.implicit_region_bound,
+            Some(self.tcx.lifetimes.re_root_empty),
             self.param_env,
         );
 
index 845a4fcafc2241e31b0c4ab308eff591be9e1edc..dabae6cbc41377a3fdf75e55101086b8c8da6dd8 100644 (file)
@@ -15,7 +15,7 @@
     self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
 };
 use rustc_session::parse::feature_err;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::may_define_opaque_type;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
@@ -142,8 +142,8 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 _ => unreachable!(),
             }
         }
-        hir::ItemKind::Fn(..) => {
-            check_item_fn(tcx, item);
+        hir::ItemKind::Fn(ref sig, ..) => {
+            check_item_fn(tcx, item.hir_id, item.ident, item.span, sig.decl);
         }
         hir::ItemKind::Static(ref ty, ..) => {
             check_item_type(tcx, item.hir_id, ty.span, false);
@@ -153,8 +153,14 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         }
         hir::ItemKind::ForeignMod(ref module) => {
             for it in module.items.iter() {
-                if let hir::ForeignItemKind::Static(ref ty, ..) = it.kind {
-                    check_item_type(tcx, it.hir_id, ty.span, true);
+                match it.kind {
+                    hir::ForeignItemKind::Fn(ref decl, ..) => {
+                        check_item_fn(tcx, it.hir_id, it.ident, it.span, decl)
+                    }
+                    hir::ForeignItemKind::Static(ref ty, ..) => {
+                        check_item_type(tcx, it.hir_id, ty.span, true)
+                    }
+                    hir::ForeignItemKind::Type => (),
                 }
             }
         }
@@ -303,7 +309,7 @@ fn check_associated_item(
                     fcx,
                     item.ident.span,
                     sig,
-                    hir_sig,
+                    hir_sig.decl,
                     item.def_id,
                     &mut implied_bounds,
                 );
@@ -564,22 +570,24 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
     }
 }
 
-fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
-    for_item(tcx, item).with_fcx(|fcx, tcx| {
-        let def_id = fcx.tcx.hir().local_def_id(item.hir_id);
+fn check_item_fn(
+    tcx: TyCtxt<'_>,
+    item_id: hir::HirId,
+    ident: Ident,
+    span: Span,
+    decl: &hir::FnDecl<'_>,
+) {
+    for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
+        let def_id = fcx.tcx.hir().local_def_id(item_id);
         let sig = fcx.tcx.fn_sig(def_id);
-        let sig = fcx.normalize_associated_types_in(item.span, &sig);
+        let sig = fcx.normalize_associated_types_in(span, &sig);
         let mut implied_bounds = vec![];
-        let hir_sig = match &item.kind {
-            ItemKind::Fn(sig, ..) => sig,
-            _ => bug!("expected `ItemKind::Fn`, found `{:?}`", item.kind),
-        };
         check_fn_or_method(
             tcx,
             fcx,
-            item.ident.span,
+            ident.span,
             sig,
-            hir_sig,
+            decl,
             def_id.to_def_id(),
             &mut implied_bounds,
         );
@@ -835,28 +843,28 @@ fn check_fn_or_method<'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
     sig: ty::PolyFnSig<'tcx>,
-    hir_sig: &hir::FnSig<'_>,
+    hir_decl: &hir::FnDecl<'_>,
     def_id: DefId,
     implied_bounds: &mut Vec<Ty<'tcx>>,
 ) {
     let sig = fcx.normalize_associated_types_in(span, &sig);
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
 
-    for (&input_ty, span) in sig.inputs().iter().zip(hir_sig.decl.inputs.iter().map(|t| t.span)) {
+    for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) {
         fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation);
     }
     implied_bounds.extend(sig.inputs());
 
     fcx.register_wf_obligation(
         sig.output().into(),
-        hir_sig.decl.output.span(),
+        hir_decl.output.span(),
         ObligationCauseCode::ReturnType,
     );
 
     // FIXME(#25759) return types should not be implied bounds
     implied_bounds.push(sig.output());
 
-    check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_sig.decl.output.span())));
+    check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
 }
 
 /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
index ec534aa925d4f2b58fd12463e33022440bff6de4..acf68be1176ddbf0df08563401f8f948359067e8 100644 (file)
@@ -730,7 +730,13 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) {
             placeholder_type_error(tcx, None, &[], visitor.0, false);
         }
 
-        hir::TraitItemKind::Type(_, None) => {}
+        hir::TraitItemKind::Type(_, None) => {
+            // #74612: Visit and try to find bad placeholders
+            // even if there is no concrete type.
+            let mut visitor = PlaceholderHirTyCollector::default();
+            visitor.visit_trait_item(trait_item);
+            placeholder_type_error(tcx, None, &[], visitor.0, false);
+        }
     };
 
     tcx.ensure().predicates_of(def_id);
@@ -1356,13 +1362,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
 
-    // FIXME(const_generics): a few places in the compiler expect generic params
-    // to be in the order lifetimes, then type params, then const params.
-    //
-    // To prevent internal errors in case const parameters are supplied before
-    // type parameters we first add all type params, then all const params.
-    params.extend(ast_generics.params.iter().filter_map(|param| {
-        if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind {
+    params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
+        GenericParamKind::Lifetime { .. } => None,
+        GenericParamKind::Type { ref default, synthetic, .. } => {
             if !allow_defaults && default.is_some() {
                 if !tcx.features().default_type_parameter_fallback {
                     tcx.struct_span_lint_hir(
@@ -1372,7 +1374,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                         |lint| {
                             lint.build(
                                 "defaults for type parameters are only allowed in \
-                                        `struct`, `enum`, `type`, or `trait` definitions.",
+                                 `struct`, `enum`, `type`, or `trait` definitions.",
                             )
                             .emit();
                         },
@@ -1397,13 +1399,8 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             };
             i += 1;
             Some(param_def)
-        } else {
-            None
         }
-    }));
-
-    params.extend(ast_generics.params.iter().filter_map(|param| {
-        if let GenericParamKind::Const { .. } = param.kind {
+        GenericParamKind::Const { .. } => {
             let param_def = ty::GenericParamDef {
                 index: type_start + i as u32,
                 name: param.name.ident().name,
@@ -1413,8 +1410,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             };
             i += 1;
             Some(param_def)
-        } else {
-            None
         }
     }));
 
@@ -1893,14 +1888,24 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
     // Collect the predicates that were written inline by the user on each
     // type parameter (e.g., `<T: Foo>`).
     for param in ast_generics.params {
-        if let GenericParamKind::Type { .. } = param.kind {
-            let name = param.name.ident().name;
-            let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
-            index += 1;
-
-            let sized = SizedByDefault::Yes;
-            let bounds = AstConv::compute_bounds(&icx, param_ty, &param.bounds, sized, param.span);
-            predicates.extend(bounds.predicates(tcx, param_ty));
+        match param.kind {
+            // We already dealt with early bound lifetimes above.
+            GenericParamKind::Lifetime { .. } => (),
+            GenericParamKind::Type { .. } => {
+                let name = param.name.ident().name;
+                let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
+                index += 1;
+
+                let sized = SizedByDefault::Yes;
+                let bounds =
+                    AstConv::compute_bounds(&icx, param_ty, &param.bounds, sized, param.span);
+                predicates.extend(bounds.predicates(tcx, param_ty));
+            }
+            GenericParamKind::Const { .. } => {
+                // Bounds on const parameters are currently not possible.
+                debug_assert!(param.bounds.is_empty());
+                index += 1;
+            }
         }
     }
 
@@ -1927,7 +1932,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
                         let re_root_empty = tcx.lifetimes.re_root_empty;
                         let predicate = ty::OutlivesPredicate(ty, re_root_empty);
                         predicates.push((
-                            ty::PredicateKind::TypeOutlives(ty::Binder::dummy(predicate))
+                            ty::PredicateKind::TypeOutlives(ty::Binder::bind(predicate))
                                 .to_predicate(tcx),
                             span,
                         ));
index 491daa80e5c859ddd0f8692fe4cf0e99c85f9a11..1f576a17dd9d665cfe1d147e1ec0b7108b41773c 100644 (file)
@@ -346,9 +346,11 @@ pub fn build_impl(
         // such. This helps prevent dependencies of the standard library, for
         // example, from getting documented as "traits `u32` implements" which
         // isn't really too helpful.
-        if let Some(stab) = cx.tcx.lookup_stability(did) {
-            if stab.level.is_unstable() {
-                return;
+        if let Some(trait_did) = associated_trait {
+            if let Some(stab) = cx.tcx.lookup_stability(trait_did.def_id) {
+                if stab.level.is_unstable() {
+                    return;
+                }
             }
         }
     }
index 8a4ee91df405fcb8b033ec6911e8916b71154aaf..94d95115dcdbcaed7bfd447b6cc22331da063d87 100644 (file)
@@ -2353,10 +2353,6 @@ fn clean(&self, _: &DocContext<'_>) -> Stability {
                 attr::Stable { ref since } => since.to_string(),
                 _ => String::new(),
             },
-            deprecation: self.rustc_depr.as_ref().map(|d| Deprecation {
-                note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
-                since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
-            }),
             unstable_reason: match self.level {
                 attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
                 _ => None,
@@ -2374,6 +2370,7 @@ fn clean(&self, _: &DocContext<'_>) -> Deprecation {
         Deprecation {
             since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
             note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
+            is_since_rustc_version: self.is_since_rustc_version,
         }
     }
 }
index 6a03722cd0802786f31710bb146e981c3fecf13e..071834c59d65ec749aafa5f8b4a72113638b74d7 100644 (file)
@@ -195,7 +195,8 @@ pub fn stability_class(&self) -> Option<String> {
                 classes.push("unstable");
             }
 
-            if s.deprecation.is_some() {
+            // FIXME: what about non-staged API items that are deprecated?
+            if self.deprecation.is_some() {
                 classes.push("deprecated");
             }
 
@@ -216,14 +217,6 @@ pub fn type_(&self) -> ItemType {
         ItemType::from(self)
     }
 
-    /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes.
-    ///
-    /// If the item is not deprecated, returns `None`.
-    pub fn deprecation(&self) -> Option<&Deprecation> {
-        self.deprecation
-            .as_ref()
-            .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref()))
-    }
     pub fn is_default(&self) -> bool {
         match self.inner {
             ItemEnum::MethodItem(ref meth) => {
@@ -1528,7 +1521,6 @@ pub struct Stability {
     pub level: stability::StabilityLevel,
     pub feature: Option<String>,
     pub since: String,
-    pub deprecation: Option<Deprecation>,
     pub unstable_reason: Option<String>,
     pub issue: Option<NonZeroU32>,
 }
@@ -1537,6 +1529,7 @@ pub struct Stability {
 pub struct Deprecation {
     pub since: Option<String>,
     pub note: Option<String>,
+    pub is_since_rustc_version: bool,
 }
 
 /// An type binding on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
index f872ed7010c7537ad3aae0cdec855f2e6a771213..f7050cf377722622eee91859903f82a04b0cf5d0 100644 (file)
@@ -2216,16 +2216,10 @@ fn tag_html(class: &str, contents: &str) -> String {
     }
 
     // The trailing space after each tag is to space it properly against the rest of the docs.
-    if item.deprecation().is_some() {
+    if let Some(depr) = &item.deprecation {
         let mut message = "Deprecated";
-        if let Some(ref stab) = item.stability {
-            if let Some(ref depr) = stab.deprecation {
-                if let Some(ref since) = depr.since {
-                    if !stability::deprecation_in_effect(&since) {
-                        message = "Deprecation planned";
-                    }
-                }
-            }
+        if !stability::deprecation_in_effect(depr.is_since_rustc_version, depr.since.as_deref()) {
+            message = "Deprecation planned";
         }
         tags += &tag_html("deprecated", message);
     }
@@ -2254,23 +2248,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
     let mut stability = vec![];
     let error_codes = cx.shared.codes;
 
-    if let Some(Deprecation { note, since }) = &item.deprecation() {
+    if let Some(Deprecation { ref note, ref since, is_since_rustc_version }) = item.deprecation {
         // We display deprecation messages for #[deprecated] and #[rustc_deprecated]
         // but only display the future-deprecation messages for #[rustc_deprecated].
         let mut message = if let Some(since) = since {
-            format!("Deprecated since {}", Escape(since))
+            if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) {
+                format!("Deprecating in {}", Escape(&since))
+            } else {
+                format!("Deprecated since {}", Escape(&since))
+            }
         } else {
             String::from("Deprecated")
         };
-        if let Some(ref stab) = item.stability {
-            if let Some(ref depr) = stab.deprecation {
-                if let Some(ref since) = depr.since {
-                    if !stability::deprecation_in_effect(&since) {
-                        message = format!("Deprecating in {}", Escape(&since));
-                    }
-                }
-            }
-        }
 
         if let Some(note) = note {
             let mut ids = cx.id_map.borrow_mut();
index 38709b445efae9aa89649872aa167af0053942dd..d0312d77a7c5d5867e5c027b76ae27957b910454 100644 (file)
@@ -1291,6 +1291,16 @@ h4 > .important-traits {
 
 /* Media Queries */
 
+@media (min-width: 701px) {
+       /* In case there is no documentation before a code block, we need to add some margin at the top
+       to prevent an overlay between the "collapse toggle" and the information tooltip.
+       However, it's needed needed with smaller screen width because the doc/code block is always put
+       "one line" below. */
+       .information:first-child > .tooltip {
+               margin-top: 16px;
+       }
+}
+
 @media (max-width: 700px) {
        body {
                padding-top: 0px;
@@ -1511,6 +1521,11 @@ h4 > .important-traits {
        #main > .line-numbers {
                margin-top: 0;
        }
+
+       .important-traits .important-traits-tooltiptext {
+               left: 0;
+               top: 100%;
+       }
 }
 
 @media print {
index e0ab7170ea8772d0bc5816d6d557f03d6f3b551f..41fe8e0fafb413185b7fa4e0043758435b2539d4 100644 (file)
@@ -62,6 +62,10 @@ pre {
        background-color: #14191f;
 }
 
+.logo-container > img {
+       filter: drop-shadow(0 0 5px #fff);
+}
+
 /* Improve the scrollbar display on firefox */
 * {
        scrollbar-color: #5c6773 transparent;
@@ -237,16 +241,6 @@ a {
 
 #crate-search+.search-input:focus {
        box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
-       color: #ffffff;
-       background-color: #141920;
-       box-shadow: none;
-       transition: box-shadow 150ms ease-in-out;
-       border-radius: 4px;
-       margin-left: 8px;
-}
-
-#crate-search+.search-input:focus {
-       box-shadow: 0px 6px 20px 0px black;
 }
 
 .search-focus:disabled {
@@ -318,12 +312,12 @@ a.test-arrow {
        font-size: 100%;
        color: #788797;
        border-radius: 4px;
-       background-color: rgba(255, 255, 255, 0);
+       background-color: rgba(57, 175, 215, 0.09);
 }
 
 a.test-arrow:hover {
-       background-color: rgba(242, 151, 24, 0.05);
-       color: #ffb44c;
+       background-color: rgba(57, 175, 215, 0.368);
+       color: #c5c5c5;
 }
 
 .toggle-label {
@@ -332,7 +326,7 @@ a.test-arrow:hover {
 
 :target > code, :target > .in-band {
        background: rgba(255, 236, 164, 0.06);
-       border-right: 3px solid #ffb44c;
+       border-right: 3px solid rgba(255, 180, 76, 0.85);
 }
 
 pre.compile_fail {
index 33c0f885fa95b4afe9f136c299f4db23e9c59b1b..b3b586ba362fa475b9f7c5c392bcf126305527c8 100644 (file)
@@ -34,6 +34,10 @@ pre {
        background-color: #505050;
 }
 
+.logo-container > img {
+       filter: drop-shadow(0 0 5px #fff);
+}
+
 /* Improve the scrollbar display on firefox */
 * {
        scrollbar-color: rgb(64, 65, 67) #717171;
@@ -270,6 +274,7 @@ a.test-arrow:hover{
 
 :target > code, :target > .in-band {
        background-color: #494a3d;
+       border-right: 3px solid #bb7410;
 }
 
 pre.compile_fail {
index 569ce7da2091f07d79c2499d6f7fe4335de6bdd6..b0c5715604baab86ea5d29eab697f5b3b6a0701f 100644 (file)
@@ -45,6 +45,10 @@ pre {
        scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
 }
 
+.logo-container > img {
+       filter: drop-shadow(0 0 5px #aaa);
+}
+
 /* Improve the scrollbar display on webkit-based browsers */
 ::-webkit-scrollbar-track {
        background-color: #ecebeb;
@@ -265,6 +269,7 @@ a.test-arrow:hover{
 
 :target > code, :target > .in-band {
        background: #FDFFD3;
+       border-right: 3px solid #ffb44c;
 }
 
 pre.compile_fail {
index e187b9251f71e5194d002060dbca21f94b2211e7..5187839423d6b1d8e00f981b6ee2d54f07e5a310 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_ast::ast;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtensionKind;
 use rustc_feature::UnstableFeatures;
 use rustc_hir as hir;
@@ -45,7 +45,17 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
 
 enum ErrorKind {
     ResolutionFailure,
-    AnchorFailure(&'static str),
+    AnchorFailure(AnchorFailure),
+}
+
+enum AnchorFailure {
+    MultipleAnchors,
+    Primitive,
+    Variant,
+    AssocConstant,
+    AssocType,
+    Field,
+    Method,
 }
 
 struct LinkCollector<'a, 'tcx> {
@@ -197,9 +207,7 @@ fn resolve(
                     // Not a trait item; just return what we found.
                     Res::PrimTy(..) => {
                         if extra_fragment.is_some() {
-                            return Err(ErrorKind::AnchorFailure(
-                                "primitive types cannot be followed by anchors",
-                            ));
+                            return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
                         }
                         return Ok((res, Some(path_str.to_owned())));
                     }
@@ -209,9 +217,7 @@ fn resolve(
                         if disambiguator == Some("type") {
                             if let Some(prim) = is_primitive(path_str, ns) {
                                 if extra_fragment.is_some() {
-                                    return Err(ErrorKind::AnchorFailure(
-                                        "primitive types cannot be followed by anchors",
-                                    ));
+                                    return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
                                 }
                                 return Ok((prim, Some(path_str.to_owned())));
                             }
@@ -228,9 +234,7 @@ fn resolve(
                 }
             } else if let Some(prim) = is_primitive(path_str, ns) {
                 if extra_fragment.is_some() {
-                    return Err(ErrorKind::AnchorFailure(
-                        "primitive types cannot be followed by anchors",
-                    ));
+                    return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
                 }
                 return Ok((prim, Some(path_str.to_owned())));
             } else {
@@ -338,9 +342,9 @@ fn resolve(
                         };
                         if extra_fragment.is_some() {
                             Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Fn {
-                                "methods cannot be followed by anchors"
+                                AnchorFailure::Method
                             } else {
-                                "associated constants cannot be followed by anchors"
+                                AnchorFailure::AssocConstant
                             }))
                         } else {
                             Ok((ty_res, Some(format!("{}.{}", out, item_name))))
@@ -358,9 +362,9 @@ fn resolve(
                                 } {
                                     if extra_fragment.is_some() {
                                         Err(ErrorKind::AnchorFailure(if def.is_enum() {
-                                            "enum variants cannot be followed by anchors"
+                                            AnchorFailure::Variant
                                         } else {
-                                            "struct fields cannot be followed by anchors"
+                                            AnchorFailure::Field
                                         }))
                                     } else {
                                         Ok((
@@ -404,11 +408,11 @@ fn resolve(
 
                         if extra_fragment.is_some() {
                             Err(ErrorKind::AnchorFailure(if item.kind == ty::AssocKind::Const {
-                                "associated constants cannot be followed by anchors"
+                                AnchorFailure::AssocConstant
                             } else if item.kind == ty::AssocKind::Type {
-                                "associated types cannot be followed by anchors"
+                                AnchorFailure::AssocType
                             } else {
-                                "methods cannot be followed by anchors"
+                                AnchorFailure::Method
                             }))
                         } else {
                             Ok((ty_res, Some(format!("{}.{}", kind, item_name))))
@@ -559,16 +563,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             let link = ori_link.replace("`", "");
             let parts = link.split('#').collect::<Vec<_>>();
             let (link, extra_fragment) = if parts.len() > 2 {
-                build_diagnostic(
-                    cx,
-                    &item,
-                    &link,
-                    &dox,
-                    link_range,
-                    "has an issue with the link anchor.",
-                    "only one `#` is allowed in a link",
-                    None,
-                );
+                anchor_failure(cx, &item, &link, &dox, link_range, AnchorFailure::MultipleAnchors);
                 continue;
             } else if parts.len() == 2 {
                 if parts[0].trim().is_empty() {
@@ -795,29 +790,22 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                 item.attrs.links.push((ori_link, None, fragment));
             } else {
                 debug!("intra-doc link to {} resolved to {:?}", path_str, res);
-                if let Some(local) = res.opt_def_id().and_then(|def_id| def_id.as_local()) {
+
+                // item can be non-local e.g. when using #[doc(primitive = "pointer")]
+                if let Some((src_id, dst_id)) = res
+                    .opt_def_id()
+                    .and_then(|def_id| def_id.as_local())
+                    .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id)))
+                {
                     use rustc_hir::def_id::LOCAL_CRATE;
 
-                    let hir_id = self.cx.tcx.hir().as_local_hir_id(local);
-                    if !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_id)
-                        && (item.visibility == Visibility::Public)
-                        && !self.cx.render_options.document_private
+                    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);
+
+                    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)
                     {
-                        let item_name = item.name.as_deref().unwrap_or("<unknown>");
-                        let err_msg = format!(
-                            "public documentation for `{}` links to a private item",
-                            item_name
-                        );
-                        build_diagnostic(
-                            cx,
-                            &item,
-                            path_str,
-                            &dox,
-                            link_range,
-                            &err_msg,
-                            "this item is private",
-                            None,
-                        );
+                        privacy_error(cx, &item, &path_str, &dox, link_range);
                         continue;
                     }
                 }
@@ -851,24 +839,33 @@ fn fold_crate(&mut self, mut c: Crate) -> Crate {
     }
 }
 
-fn build_diagnostic(
+/// Reports a diagnostic for an intra-doc link.
+///
+/// If no link range is provided, or the source span of the link cannot be determined, the span of
+/// the entire documentation block is used for the lint. If a range is provided but the span
+/// calculation fails, a note is added to the diagnostic pointing to the link in the markdown.
+///
+/// The `decorate` callback is invoked in all cases to allow further customization of the
+/// diagnostic before emission. If the span of the link was able to be determined, the second
+/// parameter of the callback will contain it, and the primary span of the diagnostic will be set
+/// to it.
+fn report_diagnostic(
     cx: &DocContext<'_>,
+    msg: &str,
     item: &Item,
-    path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
-    err_msg: &str,
-    short_err_msg: &str,
-    help_msg: Option<&str>,
+    decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
 ) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
         Some(hir_id) => hir_id,
         None => {
             // If non-local, no need to check anything.
-            info!("ignoring warning from parent crate: {}", err_msg);
+            info!("ignoring warning from parent crate: {}", msg);
             return;
         }
     };
+
     let attrs = &item.attrs;
     let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
 
@@ -877,12 +874,15 @@ fn build_diagnostic(
         hir_id,
         sp,
         |lint| {
-            let mut diag = lint.build(&format!("`[{}]` {}", path_str, err_msg));
+            let mut diag = lint.build(msg);
+
+            let span = link_range
+                .as_ref()
+                .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
+
             if let Some(link_range) = link_range {
-                if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs)
-                {
+                if let Some(sp) = span {
                     diag.set_span(sp);
-                    diag.span_label(sp, short_err_msg);
                 } else {
                     // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
                     //                       ^     ~~~~
@@ -902,20 +902,15 @@ fn build_diagnostic(
                         found = link_range.len(),
                     ));
                 }
-            };
-            if let Some(help_msg) = help_msg {
-                diag.help(help_msg);
             }
+
+            decorate(&mut diag, span);
+
             diag.emit();
         },
     );
 }
 
-/// Reports a resolution failure diagnostic.
-///
-/// If we cannot find the exact source span of the resolution failure, we use the span of the
-/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
-/// line containing the failure as a note as well.
 fn resolution_failure(
     cx: &DocContext<'_>,
     item: &Item,
@@ -923,15 +918,19 @@ fn resolution_failure(
     dox: &str,
     link_range: Option<Range<usize>>,
 ) {
-    build_diagnostic(
+    report_diagnostic(
         cx,
+        &format!("unresolved link to `{}`", path_str),
         item,
-        path_str,
         dox,
         link_range,
-        "cannot be resolved, ignoring it.",
-        "cannot be resolved, ignoring",
-        Some("to escape `[` and `]` characters, just add '\\' before them like `\\[` or `\\]`"),
+        |diag, sp| {
+            if let Some(sp) = sp {
+                diag.span_label(sp, "unresolved link");
+            }
+
+            diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
+        },
     );
 }
 
@@ -941,18 +940,39 @@ fn anchor_failure(
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
-    msg: &str,
+    failure: AnchorFailure,
 ) {
-    build_diagnostic(
-        cx,
-        item,
-        path_str,
-        dox,
-        link_range,
-        "has an issue with the link anchor.",
-        msg,
-        None,
-    );
+    let msg = match failure {
+        AnchorFailure::MultipleAnchors => format!("`{}` contains multiple anchors", path_str),
+        AnchorFailure::Primitive
+        | AnchorFailure::Variant
+        | AnchorFailure::AssocConstant
+        | AnchorFailure::AssocType
+        | AnchorFailure::Field
+        | AnchorFailure::Method => {
+            let kind = match failure {
+                AnchorFailure::Primitive => "primitive type",
+                AnchorFailure::Variant => "enum variant",
+                AnchorFailure::AssocConstant => "associated constant",
+                AnchorFailure::AssocType => "associated type",
+                AnchorFailure::Field => "struct field",
+                AnchorFailure::Method => "method",
+                AnchorFailure::MultipleAnchors => unreachable!("should be handled already"),
+            };
+
+            format!(
+                "`{}` contains an anchor, but links to {kind}s are already anchored",
+                path_str,
+                kind = kind
+            )
+        }
+    };
+
+    report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| {
+        if let Some(sp) = sp {
+            diag.span_label(sp, "contains invalid anchor");
+        }
+    });
 }
 
 fn ambiguity_error(
@@ -963,121 +983,107 @@ fn ambiguity_error(
     link_range: Option<Range<usize>>,
     candidates: PerNS<Option<Res>>,
 ) {
-    let hir_id = match cx.as_local_hir_id(item.def_id) {
-        Some(hir_id) => hir_id,
-        None => {
-            // If non-local, no need to check anything.
-            return;
+    let mut msg = format!("`{}` is ", path_str);
+
+    let candidates = [TypeNS, ValueNS, MacroNS]
+        .iter()
+        .filter_map(|&ns| candidates[ns].map(|res| (res, ns)))
+        .collect::<Vec<_>>();
+    match candidates.as_slice() {
+        [(first_def, _), (second_def, _)] => {
+            msg += &format!(
+                "both {} {} and {} {}",
+                first_def.article(),
+                first_def.descr(),
+                second_def.article(),
+                second_def.descr(),
+            );
         }
-    };
-    let attrs = &item.attrs;
-    let sp = span_of_attrs(attrs).unwrap_or(item.source.span());
-
-    cx.tcx.struct_span_lint_hir(
-        lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir_id,
-        sp,
-        |lint| {
-            let mut msg = format!("`{}` is ", path_str);
-
-            let candidates = [TypeNS, ValueNS, MacroNS]
-                .iter()
-                .filter_map(|&ns| candidates[ns].map(|res| (res, ns)))
-                .collect::<Vec<_>>();
-            match candidates.as_slice() {
-                [(first_def, _), (second_def, _)] => {
-                    msg += &format!(
-                        "both {} {} and {} {}",
-                        first_def.article(),
-                        first_def.descr(),
-                        second_def.article(),
-                        second_def.descr(),
-                    );
-                }
-                _ => {
-                    let mut candidates = candidates.iter().peekable();
-                    while let Some((res, _)) = candidates.next() {
-                        if candidates.peek().is_some() {
-                            msg += &format!("{} {}, ", res.article(), res.descr());
-                        } else {
-                            msg += &format!("and {} {}", res.article(), res.descr());
-                        }
-                    }
+        _ => {
+            let mut candidates = candidates.iter().peekable();
+            while let Some((res, _)) = candidates.next() {
+                if candidates.peek().is_some() {
+                    msg += &format!("{} {}, ", res.article(), res.descr());
+                } else {
+                    msg += &format!("and {} {}", res.article(), res.descr());
                 }
             }
+        }
+    }
 
-            let mut diag = lint.build(&msg);
-
-            if let Some(link_range) = link_range {
-                if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs)
-                {
-                    diag.set_span(sp);
-                    diag.span_label(sp, "ambiguous link");
+    report_diagnostic(cx, &msg, item, dox, link_range.clone(), |diag, sp| {
+        if let Some(sp) = sp {
+            diag.span_label(sp, "ambiguous link");
 
-                    for (res, ns) in candidates {
-                        let (action, mut suggestion) = match res {
-                            Res::Def(DefKind::AssocFn | DefKind::Fn, _) => {
-                                ("add parentheses", format!("{}()", path_str))
-                            }
-                            Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
-                                ("add an exclamation mark", format!("{}!", path_str))
-                            }
-                            _ => {
-                                let type_ = match (res, ns) {
-                                    (Res::Def(DefKind::Const, _), _) => "const",
-                                    (Res::Def(DefKind::Static, _), _) => "static",
-                                    (Res::Def(DefKind::Struct, _), _) => "struct",
-                                    (Res::Def(DefKind::Enum, _), _) => "enum",
-                                    (Res::Def(DefKind::Union, _), _) => "union",
-                                    (Res::Def(DefKind::Trait, _), _) => "trait",
-                                    (Res::Def(DefKind::Mod, _), _) => "module",
-                                    (_, TypeNS) => "type",
-                                    (_, ValueNS) => "value",
-                                    (Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => {
-                                        "derive"
-                                    }
-                                    (_, MacroNS) => "macro",
-                                };
+            let link_range = link_range.expect("must have a link range if we have a span");
 
-                                // FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
-                                ("prefix with the item type", format!("{}@{}", type_, path_str))
-                            }
+            for (res, ns) in candidates {
+                let (action, mut suggestion) = match res {
+                    Res::Def(DefKind::AssocFn | DefKind::Fn, _) => {
+                        ("add parentheses", format!("{}()", path_str))
+                    }
+                    Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
+                        ("add an exclamation mark", format!("{}!", path_str))
+                    }
+                    _ => {
+                        let type_ = match (res, ns) {
+                            (Res::Def(DefKind::Const, _), _) => "const",
+                            (Res::Def(DefKind::Static, _), _) => "static",
+                            (Res::Def(DefKind::Struct, _), _) => "struct",
+                            (Res::Def(DefKind::Enum, _), _) => "enum",
+                            (Res::Def(DefKind::Union, _), _) => "union",
+                            (Res::Def(DefKind::Trait, _), _) => "trait",
+                            (Res::Def(DefKind::Mod, _), _) => "module",
+                            (_, TypeNS) => "type",
+                            (_, ValueNS) => "value",
+                            (Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => "derive",
+                            (_, MacroNS) => "macro",
                         };
 
-                        if dox.bytes().nth(link_range.start) == Some(b'`') {
-                            suggestion = format!("`{}`", suggestion);
-                        }
-
-                        diag.span_suggestion(
-                            sp,
-                            &format!("to link to the {}, {}", res.descr(), action),
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
+                        // FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
+                        ("prefix with the item type", format!("{}@{}", type_, path_str))
                     }
-                } else {
-                    // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-                    //                       ^     ~~~~
-                    //                       |     link_range
-                    //                       last_new_line_offset
-                    let last_new_line_offset =
-                        dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-                    let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+                };
 
-                    // Print the line containing the `link_range` and manually mark it with '^'s.
-                    diag.note(&format!(
-                        "the link appears in this line:\n\n{line}\n\
-                         {indicator: <before$}{indicator:^<found$}",
-                        line = line,
-                        indicator = "",
-                        before = link_range.start - last_new_line_offset,
-                        found = link_range.len(),
-                    ));
+                if dox.bytes().nth(link_range.start) == Some(b'`') {
+                    suggestion = format!("`{}`", suggestion);
                 }
+
+                // FIXME: Create a version of this suggestion for when we don't have the span.
+                diag.span_suggestion(
+                    sp,
+                    &format!("to link to the {}, {}", res.descr(), action),
+                    suggestion,
+                    Applicability::MaybeIncorrect,
+                );
             }
-            diag.emit();
-        },
-    );
+        }
+    });
+}
+
+fn privacy_error(
+    cx: &DocContext<'_>,
+    item: &Item,
+    path_str: &str,
+    dox: &str,
+    link_range: Option<Range<usize>>,
+) {
+    let item_name = item.name.as_deref().unwrap_or("<unknown>");
+    let msg =
+        format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
+
+    report_diagnostic(cx, &msg, item, dox, link_range, |diag, sp| {
+        if let Some(sp) = sp {
+            diag.span_label(sp, "this item is private");
+        }
+
+        let note_msg = if cx.render_options.document_private {
+            "this link resolves only because you passed `--document-private-items`, but will break without"
+        } else {
+            "this link will resolve properly if you pass `--document-private-items`"
+        };
+        diag.note(note_msg);
+    });
 }
 
 /// Given an enum variant's res, return the res of its enum and the associated fragment.
@@ -1089,7 +1095,7 @@ fn handle_variant(
     use rustc_middle::ty::DefIdTree;
 
     if extra_fragment.is_some() {
-        return Err(ErrorKind::AnchorFailure("variants cannot be followed by anchors"));
+        return Err(ErrorKind::AnchorFailure(AnchorFailure::Variant));
     }
     let parent = if let Some(parent) = cx.tcx.parent(res.def_id()) {
         parent
index 136db6d5d3239d55211c9cf27a669b033d2d5428..2c1e71c64c4e5a4d01d7d02890790397d247b0e2 100644 (file)
@@ -2,7 +2,6 @@
 authors = ["The Rust Project Developers"]
 name = "std"
 version = "0.0.0"
-build = "build.rs"
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust.git"
 description = "The Rust Standard Library"
@@ -25,15 +24,11 @@ profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
 hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] }
 
-# Dependencies of the `backtrace` crate
-addr2line = { version = "0.13.0", optional = true, default-features = false }
-rustc-demangle = { version = "0.1.4", optional = true }
-miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
-[dependencies.object]
-version = "0.20"
-optional = true
-default-features = false
-features = ['read_core', 'elf', 'macho', 'pe']
+[dependencies.backtrace_rs]
+package = "backtrace"
+version = "0.3.46"
+default-features = false # without the libstd `backtrace` feature, stub out everything
+features = [ "rustc-dep-of-std" ] # enable build support for integrating into libstd
 
 [dev-dependencies]
 rand = "0.7"
@@ -45,20 +40,18 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 
 [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
-hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] }
+hermit-abi = { version = "0.1.15", features = ['rustc-dep-of-std'] }
 
 [target.wasm32-wasi.dependencies]
 wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
 
 [features]
 backtrace = [
-  "gimli-symbolize",
-  'addr2line/rustc-dep-of-std',
-  'object/rustc-dep-of-std',
-  'rustc-demangle/rustc-dep-of-std',
-  'miniz_oxide/rustc-dep-of-std',
+  "backtrace_rs/dbghelp",          # backtrace/symbolize on MSVC
+  "backtrace_rs/libbacktrace",     # symbolize on most platforms
+  "backtrace_rs/libunwind",        # backtrace on most platforms
+  "backtrace_rs/dladdr",           # symbolize on platforms w/o libbacktrace
 ]
-gimli-symbolize = []
 
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
index e65775c1ced67909ad9d5e0954f946e78ffd55b5..02e6811bc3f4357e33b732e17f138925562a31f7 100644 (file)
@@ -91,7 +91,6 @@
 // `Backtrace`, but that's a relatively small price to pay relative to capturing
 // a backtrace or actually symbolizing it.
 
-use crate::backtrace_rs::{self, BytesOrWideString};
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
@@ -99,6 +98,8 @@
 use crate::sync::Mutex;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
+use backtrace::BytesOrWideString;
+use backtrace_rs as backtrace;
 
 /// A captured OS thread stack backtrace.
 ///
@@ -149,7 +150,7 @@ struct BacktraceFrame {
 }
 
 enum RawFrame {
-    Actual(backtrace_rs::Frame),
+    Actual(backtrace::Frame),
     #[cfg(test)]
     Fake,
 }
@@ -196,7 +197,7 @@ impl fmt::Debug for BacktraceSymbol {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(fmt, "{{ ")?;
 
-        if let Some(fn_name) = self.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)) {
+        if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) {
             write!(fmt, "fn: \"{:#}\"", fn_name)?;
         } else {
             write!(fmt, "fn: <unknown>")?;
@@ -222,7 +223,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                 BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                 BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
             },
-            backtrace_rs::PrintFmt::Short,
+            backtrace::PrintFmt::Short,
             crate::env::current_dir().as_ref().ok(),
         )
     }
@@ -291,6 +292,12 @@ pub fn force_capture() -> Backtrace {
         Backtrace::create(Backtrace::force_capture as usize)
     }
 
+    /// Forcibly captures a disabled backtrace, regardless of environment
+    /// variable configuration.
+    pub const fn disabled() -> Backtrace {
+        Backtrace { inner: Inner::Disabled }
+    }
+
     // Capture a backtrace which start just before the function addressed by
     // `ip`
     fn create(ip: usize) -> Backtrace {
@@ -298,7 +305,7 @@ fn create(ip: usize) -> Backtrace {
         let mut frames = Vec::new();
         let mut actual_start = None;
         unsafe {
-            backtrace_rs::trace_unsynchronized(|frame| {
+            backtrace::trace_unsynchronized(|frame| {
                 frames.push(BacktraceFrame {
                     frame: RawFrame::Actual(frame.clone()),
                     symbols: Vec::new(),
@@ -349,9 +356,9 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         let full = fmt.alternate();
         let (frames, style) = if full {
-            (&capture.frames[..], backtrace_rs::PrintFmt::Full)
+            (&capture.frames[..], backtrace::PrintFmt::Full)
         } else {
-            (&capture.frames[capture.actual_start..], backtrace_rs::PrintFmt::Short)
+            (&capture.frames[capture.actual_start..], backtrace::PrintFmt::Short)
         };
 
         // When printing paths we try to strip the cwd if it exists, otherwise
@@ -363,7 +370,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
             output_filename(fmt, path, style, cwd.as_ref().ok())
         };
 
-        let mut f = backtrace_rs::BacktraceFmt::new(fmt, style, &mut print_path);
+        let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path);
         f.add_context()?;
         for frame in frames {
             let mut f = f.frame();
@@ -373,7 +380,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                 for symbol in frame.symbols.iter() {
                     f.print_raw(
                         frame.frame.ip(),
-                        symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
+                        symbol.name.as_ref().map(|b| backtrace::SymbolName::new(b)),
                         symbol.filename.as_ref().map(|b| match b {
                             BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w),
                             BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
@@ -408,7 +415,7 @@ fn resolve(&mut self) {
                 RawFrame::Fake => unimplemented!(),
             };
             unsafe {
-                backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
+                backtrace::resolve_frame_unsynchronized(frame, |symbol| {
                     symbols.push(BacktraceSymbol {
                         name: symbol.name().map(|m| m.as_bytes().to_vec()),
                         filename: symbol.filename_raw().map(|b| match b {
index 58fb6fda19aabed41aafde057139836be1c69c2e..43a3327d84b613905ad8c65daaf9ab52ff181633 100644 (file)
@@ -1,6 +1,7 @@
 use std::env;
 
 fn main() {
+    println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
     if target.contains("linux") {
         if target.contains("android") {
@@ -87,5 +88,4 @@ fn main() {
         println!("cargo:rustc-cfg=feature=\"restricted-std\"");
     }
     println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
-    println!("cargo:rustc-cfg=backtrace_in_libstd");
 }
index cc6663bebd3d4cf99aa8ce21f798d0f43010d3dc..b6488ae61b153ee2c1cb6ffeb0184f7d70dbace5 100644 (file)
@@ -86,7 +86,7 @@
 //! cost are suffixed with a `~`.
 //!
 //! All amortized costs are for the potential need to resize when capacity is
-//! exhausted. If a resize occurs it will take O(n) time. Our collections never
+//! exhausted. If a resize occurs it will take *O*(*n*) time. Our collections never
 //! automatically shrink, so removal operations aren't amortized. Over a
 //! sufficiently large series of operations, the average cost per operation will
 //! deterministically equal the given cost.
index b392d6e7226d2d7bba2080ebefae53cd89626c45..c905bcf5e3db4255819b3c952eb5277012042add 100644 (file)
@@ -1500,7 +1500,7 @@ fn test_float_bits_conv() {
         assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
         assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
 
-        // Check that NaNs roundtrip their bits regardless of signalingness
+        // Check that NaNs roundtrip their bits regardless of signaling-ness
         // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
         let masked_nan1 = f32::NAN.to_bits() ^ 0x002A_AAAA;
         let masked_nan2 = f32::NAN.to_bits() ^ 0x0055_5555;
index 72268d2cc2f984be863501d2e4df84197d3fbb61..f09fc8d790b28faade6c3d0a2193263d32b07a42 100644 (file)
@@ -1523,7 +1523,7 @@ fn test_float_bits_conv() {
         assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
         assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
 
-        // Check that NaNs roundtrip their bits regardless of signalingness
+        // Check that NaNs roundtrip their bits regardless of signaling-ness
         // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
         let masked_nan1 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
         let masked_nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
index 823ce30febed425ac794e6e1440a203b43029edb..797318d95b7775f3d5e13011acc9401da7cfb1ee 100644 (file)
@@ -722,7 +722,9 @@ fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
     /// No guarantees are provided about the contents of `buf` when this
     /// function is called, implementations cannot rely on any property of the
     /// contents of `buf` being true. It is recommended that implementations
-    /// only write data to `buf` instead of reading its contents.
+    /// only write data to `buf` instead of reading its contents. The
+    /// documentation on [`read`] has a more detailed explanation on this
+    /// subject.
     ///
     /// # Errors
     ///
@@ -745,6 +747,7 @@ fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
     ///
     /// [`File`]s implement `Read`:
     ///
+    /// [`read`]: Read::read
     /// [`File`]: crate::fs::File
     ///
     /// ```no_run
index d985f10ccb486489fe65680c495e9127b851dbd7..1fa438747c165ad27a9e4de5bc495c53f109ec65 100644 (file)
@@ -387,10 +387,11 @@ mod extern_keyword {}
 //
 /// A value of type [`bool`] representing logical **false**.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `false` is the logical opposite of [`true`].
 ///
-/// [`bool`]: primitive.bool.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// See the documentation for [`true`] for more information.
+///
+/// [`true`]: keyword.true.html
 mod false_keyword {}
 
 #[doc(keyword = "fn")]
@@ -473,8 +474,8 @@ mod fn_keyword {}
 /// * `for` is also used for [higher-ranked trait bounds] as in `for<'a> &'a T: PartialEq<i32>`.
 ///
 /// for-in-loops, or to be more precise, iterator loops, are a simple syntactic sugar over a common
-/// practice within Rust, which is to loop over an iterator until that iterator returns `None` (or
-/// `break` is called).
+/// practice within Rust, which is to loop over anything that implements [`IntoIterator`] until the
+/// iterator returned by `.into_iter()` returns `None` (or the loop body uses `break`).
 ///
 /// ```rust
 /// for i in 0..5 {
@@ -680,7 +681,7 @@ mod impl_keyword {}
 //
 /// Iterate over a series of values with [`for`].
 ///
-/// The expression immediately following `in` must implement the [`Iterator`] trait.
+/// The expression immediately following `in` must implement the [`IntoIterator`] trait.
 ///
 /// ## Literal Examples:
 ///
@@ -689,7 +690,7 @@ mod impl_keyword {}
 ///
 /// (Read more about [range patterns])
 ///
-/// [`Iterator`]: ../book/ch13-04-performance.html
+/// [`IntoIterator`]: ../book/ch13-04-performance.html
 /// [range patterns]: ../reference/patterns.html?highlight=range#range-patterns
 /// [`for`]: keyword.for.html
 mod in_keyword {}
@@ -1059,9 +1060,50 @@ mod pub_keyword {}
 //
 /// Bind by reference during pattern matching.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `ref` annotates pattern bindings to make them borrow rather than move.
+/// It is **not** a part of the pattern as far as matching is concerned: it does
+/// not affect *whether* a value is matched, only *how* it is matched.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// By default, [`match`] statements consume all they can, which can sometimes
+/// be a problem, when you don't really need the value to be moved and owned:
+///
+/// ```compile_fail,E0382
+/// let maybe_name = Some(String::from("Alice"));
+/// // The variable 'maybe_name' is consumed here ...
+/// match maybe_name {
+///     Some(n) => println!("Hello, {}", n),
+///     _ => println!("Hello, world"),
+/// }
+/// // ... and is now unavailable.
+/// println!("Hello again, {}", maybe_name.unwrap_or("world".into()));
+/// ```
+///
+/// Using the `ref` keyword, the value is only borrowed, not moved, making it
+/// available for use after the [`match`] statement:
+///
+/// ```
+/// let maybe_name = Some(String::from("Alice"));
+/// // Using `ref`, the value is borrowed, not moved ...
+/// match maybe_name {
+///     Some(ref n) => println!("Hello, {}", n),
+///     _ => println!("Hello, world"),
+/// }
+/// // ... so it's available here!
+/// println!("Hello again, {}", maybe_name.unwrap_or("world".into()));
+/// ```
+///
+/// # `&` vs `ref`
+///
+/// - `&` denotes that your pattern expects a reference to an object. Hence `&`
+/// is a part of said pattern: `&Foo` matches different objects than `Foo` does.
+///
+/// - `ref` indicates that you want a reference to an unpacked value. It is not
+/// matched against: `Foo(ref foo)` matches the same objects as `Foo(foo)`.
+///
+/// See also the [Reference] for more information.
+///
+/// [`match`]: keyword.match.html
+/// [Reference]: ../reference/patterns.html#identifier-patterns
 mod ref_keyword {}
 
 #[doc(keyword = "return")]
@@ -1828,9 +1870,100 @@ mod use_keyword {}
 //
 /// Add constraints that must be upheld to use an item.
 ///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// `where` allows specifying constraints on lifetime and generic parameters.
+/// The [RFC] introducing `where` contains detailed informations about the
+/// keyword.
 ///
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// # Examples
+///
+/// `where` can be used for constraints with traits:
+///
+/// ```rust
+/// fn new<T: Default>() -> T {
+///     T::default()
+/// }
+///
+/// fn new_where<T>() -> T
+/// where
+///     T: Default,
+/// {
+///     T::default()
+/// }
+///
+/// assert_eq!(0.0, new());
+/// assert_eq!(0.0, new_where());
+///
+/// assert_eq!(0, new());
+/// assert_eq!(0, new_where());
+/// ```
+///
+/// `where` can also be used for lifetimes.
+///
+/// This compiles because `longer` outlives `shorter`, thus the constraint is
+/// respected:
+///
+/// ```rust
+/// fn select<'short, 'long>(s1: &'short str, s2: &'long str, second: bool) -> &'short str
+/// where
+///     'long: 'short,
+/// {
+///     if second { s2 } else { s1 }
+/// }
+///
+/// let outer = String::from("Long living ref");
+/// let longer = &outer;
+/// {
+///     let inner = String::from("Short living ref");
+///     let shorter = &inner;
+///
+///     assert_eq!(select(shorter, longer, false), shorter);
+///     assert_eq!(select(shorter, longer, true), longer);
+/// }
+/// ```
+///
+/// On the other hand, this will not compile because the `where 'b: 'a` clause
+/// is missing: the `'b` lifetime is not known to live at least as long as `'a`
+/// which means this function cannot ensure it always returns a valid reference:
+///
+/// ```rust,compile_fail,E0623
+/// fn select<'a, 'b>(s1: &'a str, s2: &'b str, second: bool) -> &'a str
+/// {
+///     if second { s2 } else { s1 }
+/// }
+/// ```
+///
+/// `where` can also be used to express more complicated constraints that cannot
+/// be written with the `<T: Trait>` syntax:
+///
+/// ```rust
+/// fn first_or_default<I>(mut i: I) -> I::Item
+/// where
+///     I: Iterator,
+///     I::Item: Default,
+/// {
+///     i.next().unwrap_or_else(I::Item::default)
+/// }
+///
+/// assert_eq!(first_or_default(vec![1, 2, 3].into_iter()), 1);
+/// assert_eq!(first_or_default(Vec::<i32>::new().into_iter()), 0);
+/// ```
+///
+/// `where` is available anywhere generic and lifetime parameters are available,
+/// as can be seen with the [`Cow`](crate::borrow::Cow) type from the standard
+/// library:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// pub enum Cow<'a, B>
+/// where
+///     B: 'a + ToOwned + ?Sized,
+///  {
+///     Borrowed(&'a B),
+///     Owned(<B as ToOwned>::Owned),
+/// }
+/// ```
+///
+/// [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md
 mod where_keyword {}
 
 // 2018 Edition keywords
index 11b8f953be46008c0a8cd05c3e62da77e8a4ea03..00f2fff94c9a16928b34e188bad85b7cf27bfcb7 100644 (file)
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform, ptr_wrapping_offset_from)
 )]
-#![cfg_attr(
-    all(test, target_vendor = "fortanix", target_env = "sgx"),
-    feature(fixed_size_array, maybe_uninit_extra)
-)]
+#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))]
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
 // NB: the following list is sorted to minimize merge conflicts.
@@ -514,10 +511,6 @@ pub mod task {
 // compiler
 pub mod rt;
 
-#[path = "../backtrace/src/lib.rs"]
-#[allow(dead_code, unused_attributes)]
-mod backtrace_rs;
-
 // Pull in the `std_detect` crate directly into libstd. The contents of
 // `std_detect` are in a different repository: rust-lang/stdarch.
 //
index d22b44a06666295787ed0a614c5418b35ad51ecb..657737394ab82fe5feb1f29a57f2402cf1a2495c 100644 (file)
@@ -285,7 +285,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime_nsec(&self) -> i64;
-    /// Returns the "preferred" blocksize for efficient filesystem I/O.
+    /// Returns the "preferred" block size for efficient filesystem I/O.
     ///
     /// # Examples
     ///
index 6c87df534bdc683c929cbddc584a361bb7b95717..61b5bff380518674c4341fc74f121ea7a5381142 100644 (file)
@@ -289,7 +289,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime_nsec(&self) -> i64;
-    /// Returns the "preferred" blocksize for efficient filesystem I/O.
+    /// Returns the "preferred" block size for efficient filesystem I/O.
     ///
     /// # Examples
     ///
index ab2a60103069d6571179c20c565f5e64800d6f0b..9542e7209b4cf168347e18b00cc3253c349fb020 100644 (file)
@@ -171,7 +171,7 @@ fn default_hook(info: &PanicInfo<'_>) {
     // If this is a double panic, make sure that we print a backtrace
     // for this panic. Otherwise only print it if logging is enabled.
     let backtrace_env = if panic_count::get() >= 2 {
-        RustBacktrace::Print(crate::backtrace_rs::PrintFmt::Full)
+        RustBacktrace::Print(backtrace_rs::PrintFmt::Full)
     } else {
         backtrace::rust_backtrace_env()
     };
index f14a9ff72f62f473ef8437ed5c63650cbab30785..392c815ef2803a5002d03564d49e5f330c55e884 100644 (file)
@@ -2244,6 +2244,9 @@ fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
     ///
     /// let path = Path::new("foo.rs");
     /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
+    ///
+    /// let path = Path::new("foo.tar.gz");
+    /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
index e0ceb9f3f3810ff1c1e93fc7d9b5815e1062a561..86de509e80a106ab0930531df3e7163359bd23b5 100644 (file)
@@ -460,8 +460,7 @@ mod prim_pointer {}
 /// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
 ///   The type of `x` must be [`Copy`][copy].
 ///
-/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits if
-/// the element type allows it:
+/// Arrays of *any* size implement the following traits if the element type allows it:
 ///
 /// - [`Debug`][debug]
 /// - [`IntoIterator`][intoiterator] (implemented for `&[T; N]` and `&mut [T; N]`)
@@ -469,12 +468,9 @@ mod prim_pointer {}
 /// - [`Hash`][hash]
 /// - [`AsRef`][asref], [`AsMut`][asmut]
 /// - [`Borrow`][borrow], [`BorrowMut`][borrowmut]
-/// - [`Default`][default]
 ///
-/// This limitation on the size `N` exists because Rust does not yet support
-/// code that is generic over the size of an array type. `[Foo; 3]` and `[Bar; 3]`
-/// are instances of same generic type `[T; 3]`, but `[Foo; 3]` and `[Foo; 5]` are
-/// entirely different types. As a stopgap, trait implementations are
+/// Arrays of sizes from 0 to 32 (inclusive) implement [`Default`][default] trait
+/// if the element type allows it. As a stopgap, trait implementations are
 /// statically generated up to size 32.
 ///
 /// Arrays of *any* size are [`Copy`][copy] if the element type is [`Copy`][copy]
@@ -521,8 +517,7 @@ mod prim_pointer {}
 /// for x in array.iter() { }
 /// ```
 ///
-/// If the array has 32 or fewer elements (see above), you can also use the
-/// array reference's [`IntoIterator`] implementation:
+/// You can also use the array reference's [`IntoIterator`] implementation:
 ///
 /// ```
 /// # let array: [i32; 3] = [0; 3];
index 132e579b3a5cbcd38d3e698af47bd3903359f5ac..52c8c3b17e8262571775b4a41b1ab543fbd78b39 100644 (file)
@@ -1,60 +1,64 @@
-use crate::cmp;
+use crate::ffi::c_void;
+use crate::ptr;
+use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 use crate::sys::hermit::abi;
 use crate::sys::mutex::Mutex;
 use crate::time::Duration;
 
+// The implementation is inspired by Andrew D. Birrell's paper
+// "Implementing Condition Variables with Semaphores"
+
 pub struct Condvar {
-    identifier: usize,
+    counter: AtomicUsize,
+    sem1: *const c_void,
+    sem2: *const c_void,
 }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 impl Condvar {
     pub const fn new() -> Condvar {
-        Condvar { identifier: 0 }
+        Condvar { counter: AtomicUsize::new(0), sem1: ptr::null(), sem2: ptr::null() }
     }
 
     pub unsafe fn init(&mut self) {
-        let _ = abi::init_queue(self.id());
+        let _ = abi::sem_init(&mut self.sem1 as *mut *const c_void, 0);
+        let _ = abi::sem_init(&mut self.sem2 as *mut *const c_void, 0);
     }
 
     pub unsafe fn notify_one(&self) {
-        let _ = abi::notify(self.id(), 1);
+        if self.counter.load(SeqCst) > 0 {
+            self.counter.fetch_sub(1, SeqCst);
+            abi::sem_post(self.sem1);
+            abi::sem_timedwait(self.sem2, 0);
+        }
     }
 
-    #[inline]
     pub unsafe fn notify_all(&self) {
-        let _ = abi::notify(self.id(), -1 /* =all */);
+        let counter = self.counter.swap(0, SeqCst);
+        for _ in 0..counter {
+            abi::sem_post(self.sem1);
+        }
+        for _ in 0..counter {
+            abi::sem_timedwait(self.sem2, 0);
+        }
     }
 
     pub unsafe fn wait(&self, mutex: &Mutex) {
-        // add current task to the wait queue
-        let _ = abi::add_queue(self.id(), -1 /* no timeout */);
+        self.counter.fetch_add(1, SeqCst);
         mutex.unlock();
-        let _ = abi::wait(self.id());
+        abi::sem_timedwait(self.sem1, 0);
+        abi::sem_post(self.sem2);
         mutex.lock();
     }
 
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let nanos = dur.as_nanos();
-        let nanos = cmp::min(i64::MAX as u128, nanos);
-
-        // add current task to the wait queue
-        let _ = abi::add_queue(self.id(), nanos as i64);
-
-        mutex.unlock();
-        // If the return value is !0 then a timeout happened, so we return
-        // `false` as we weren't actually notified.
-        let ret = abi::wait(self.id()) == 0;
-        mutex.lock();
-
-        ret
+    pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+        panic!("wait_timeout not supported on hermit");
     }
 
     pub unsafe fn destroy(&self) {
-        let _ = abi::destroy_queue(self.id());
-    }
-
-    #[inline]
-    fn id(&self) -> usize {
-        &self.identifier as *const usize as usize
+        let _ = abi::sem_destroy(self.sem1);
+        let _ = abi::sem_destroy(self.sem2);
     }
 }
index c19799af3c7ee3c2d1ada043f32158aa7a062b7a..06442e925f4c8710d33caf6fff3e18a54e495081 100644 (file)
-use super::mutex::Mutex;
+use crate::cell::UnsafeCell;
+use crate::sys::condvar::Condvar;
+use crate::sys::mutex::Mutex;
 
 pub struct RWLock {
-    mutex: Mutex,
+    lock: Mutex,
+    cond: Condvar,
+    state: UnsafeCell<State>,
+}
+
+enum State {
+    Unlocked,
+    Reading(usize),
+    Writing,
 }
 
 unsafe impl Send for RWLock {}
 unsafe impl Sync for RWLock {}
 
+// This rwlock implementation is a relatively simple implementation which has a
+// condition variable for readers/writers as well as a mutex protecting the
+// internal state of the lock. A current downside of the implementation is that
+// unlocking the lock will notify *all* waiters rather than just readers or just
+// writers. This can cause lots of "thundering stampede" problems. While
+// hopefully correct this implementation is very likely to want to be changed in
+// the future.
+
 impl RWLock {
     pub const fn new() -> RWLock {
-        RWLock { mutex: Mutex::new() }
+        RWLock { lock: Mutex::new(), cond: Condvar::new(), state: UnsafeCell::new(State::Unlocked) }
     }
 
     #[inline]
     pub unsafe fn read(&self) {
-        self.mutex.lock();
+        self.lock.lock();
+        while !(*self.state.get()).inc_readers() {
+            self.cond.wait(&self.lock);
+        }
+        self.lock.unlock();
     }
 
     #[inline]
     pub unsafe fn try_read(&self) -> bool {
-        self.mutex.try_lock()
+        self.lock.lock();
+        let ok = (*self.state.get()).inc_readers();
+        self.lock.unlock();
+        return ok;
     }
 
     #[inline]
     pub unsafe fn write(&self) {
-        self.mutex.lock();
+        self.lock.lock();
+        while !(*self.state.get()).inc_writers() {
+            self.cond.wait(&self.lock);
+        }
+        self.lock.unlock();
     }
 
     #[inline]
     pub unsafe fn try_write(&self) -> bool {
-        self.mutex.try_lock()
+        self.lock.lock();
+        let ok = (*self.state.get()).inc_writers();
+        self.lock.unlock();
+        return ok;
     }
 
     #[inline]
     pub unsafe fn read_unlock(&self) {
-        self.mutex.unlock();
+        self.lock.lock();
+        let notify = (*self.state.get()).dec_readers();
+        self.lock.unlock();
+        if notify {
+            // FIXME: should only wake up one of these some of the time
+            self.cond.notify_all();
+        }
     }
 
     #[inline]
     pub unsafe fn write_unlock(&self) {
-        self.mutex.unlock();
+        self.lock.lock();
+        (*self.state.get()).dec_writers();
+        self.lock.unlock();
+        // FIXME: should only wake up one of these some of the time
+        self.cond.notify_all();
     }
 
     #[inline]
     pub unsafe fn destroy(&self) {
-        self.mutex.destroy();
+        self.lock.destroy();
+        self.cond.destroy();
+    }
+}
+
+impl State {
+    fn inc_readers(&mut self) -> bool {
+        match *self {
+            State::Unlocked => {
+                *self = State::Reading(1);
+                true
+            }
+            State::Reading(ref mut cnt) => {
+                *cnt += 1;
+                true
+            }
+            State::Writing => false,
+        }
+    }
+
+    fn inc_writers(&mut self) -> bool {
+        match *self {
+            State::Unlocked => {
+                *self = State::Writing;
+                true
+            }
+            State::Reading(_) | State::Writing => false,
+        }
+    }
+
+    fn dec_readers(&mut self) -> bool {
+        let zero = match *self {
+            State::Reading(ref mut cnt) => {
+                *cnt -= 1;
+                *cnt == 0
+            }
+            State::Unlocked | State::Writing => invalid(),
+        };
+        if zero {
+            *self = State::Unlocked;
+        }
+        zero
     }
+
+    fn dec_writers(&mut self) {
+        match *self {
+            State::Writing => {}
+            State::Unlocked | State::Reading(_) => invalid(),
+        }
+        *self = State::Unlocked;
+    }
+}
+
+fn invalid() -> ! {
+    panic!("inconsistent rwlock");
 }
index 90158030c7fbe19c8a6c00f8d2e367fb8bc6fa45..e5dc5b5adaa934a0ed34de571c425e2e231275da 100644 (file)
@@ -19,7 +19,7 @@ pub fn raw(&self) -> Fd {
         self.fd
     }
 
-    /// Extracts the actual filedescriptor without closing it.
+    /// Extracts the actual file descriptor without closing it.
     pub fn into_raw(self) -> Fd {
         let fd = self.fd;
         mem::forget(self);
index 2b2bbc6e9d6ae473a24ca68f6b2676fa0428fffa..f174a59b49a6ba51b01a1bc50f720ee2a6e4dd37 100644 (file)
@@ -624,7 +624,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime_nsec(&self) -> i64;
-    /// Returns the blocksize for filesystem I/O.
+    /// Returns the block size for filesystem I/O.
     ///
     /// # Examples
     ///
@@ -635,7 +635,7 @@ pub trait MetadataExt {
     ///
     /// fn main() -> io::Result<()> {
     ///     let meta = fs::metadata("some_file")?;
-    ///     let blocksize = meta.blksize();
+    ///     let block_size = meta.blksize();
     ///     Ok(())
     /// }
     /// ```
index c481ca8961f86192a3629e4660690bff33b141e9..84c4d662161bca7fac8a938c71e5799618787e10 100644 (file)
@@ -3,28 +3,28 @@
 use crate::cmp;
 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
 use crate::mem;
-use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::cvt;
 use crate::sys_common::AsInner;
 
-use libc::{c_int, c_void, ssize_t};
+use libc::{c_int, c_void};
 
 #[derive(Debug)]
 pub struct FileDesc {
     fd: c_int,
 }
 
-fn max_len() -> usize {
-    // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
-    // with the man page quoting that if the count of bytes to read is
-    // greater than `SSIZE_MAX` the result is "unspecified".
-    //
-    // On macOS, however, apparently the 64-bit libc is either buggy or
-    // intentionally showing odd behavior by rejecting any read with a size
-    // larger than or equal to INT_MAX. To handle both of these the read
-    // size is capped on both platforms.
-    if cfg!(target_os = "macos") { <c_int>::MAX as usize - 1 } else { <ssize_t>::MAX as usize }
-}
+// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
+// with the man page quoting that if the count of bytes to read is
+// greater than `SSIZE_MAX` the result is "unspecified".
+//
+// On macOS, however, apparently the 64-bit libc is either buggy or
+// intentionally showing odd behavior by rejecting any read with a size
+// larger than or equal to INT_MAX. To handle both of these the read
+// size is capped on both platforms.
+#[cfg(target_os = "macos")]
+const READ_LIMIT: usize = c_int::MAX as usize - 1;
+#[cfg(not(target_os = "macos"))]
+const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
 
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
@@ -44,7 +44,7 @@ pub fn into_raw(self) -> c_int {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
-            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), max_len()))
+            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
         })?;
         Ok(ret as usize)
     }
@@ -92,7 +92,7 @@ unsafe fn cvt_pread64(
             cvt_pread64(
                 self.fd,
                 buf.as_mut_ptr() as *mut c_void,
-                cmp::min(buf.len(), max_len()),
+                cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
             )
             .map(|n| n as usize)
@@ -101,7 +101,7 @@ unsafe fn cvt_pread64(
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
-            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), max_len()))
+            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
         })?;
         Ok(ret as usize)
     }
@@ -144,7 +144,7 @@ unsafe fn cvt_pwrite64(
             cvt_pwrite64(
                 self.fd,
                 buf.as_ptr() as *const c_void,
-                cmp::min(buf.len(), max_len()),
+                cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
             )
             .map(|n| n as usize)
@@ -223,50 +223,9 @@ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
     pub fn duplicate(&self) -> io::Result<FileDesc> {
         // We want to atomically duplicate this file descriptor and set the
         // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
-        // flag, however, isn't supported on older Linux kernels (earlier than
-        // 2.6.24).
-        //
-        // To detect this and ensure that CLOEXEC is still set, we
-        // follow a strategy similar to musl [1] where if passing
-        // F_DUPFD_CLOEXEC causes `fcntl` to return EINVAL it means it's not
-        // supported (the third parameter, 0, is always valid), so we stop
-        // trying that.
-        //
-        // Also note that Android doesn't have F_DUPFD_CLOEXEC, but get it to
-        // resolve so we at least compile this.
-        //
-        // [1]: http://comments.gmane.org/gmane.linux.lib.musl.general/2963
-        #[cfg(any(target_os = "android", target_os = "haiku"))]
-        use libc::F_DUPFD as F_DUPFD_CLOEXEC;
-        #[cfg(not(any(target_os = "android", target_os = "haiku")))]
-        use libc::F_DUPFD_CLOEXEC;
-
-        let make_filedesc = |fd| {
-            let fd = FileDesc::new(fd);
-            fd.set_cloexec()?;
-            Ok(fd)
-        };
-        static TRY_CLOEXEC: AtomicBool = AtomicBool::new(!cfg!(target_os = "android"));
-        let fd = self.raw();
-        if TRY_CLOEXEC.load(Ordering::Relaxed) {
-            match cvt(unsafe { libc::fcntl(fd, F_DUPFD_CLOEXEC, 0) }) {
-                // We *still* call the `set_cloexec` method as apparently some
-                // linux kernel at some point stopped setting CLOEXEC even
-                // though it reported doing so on F_DUPFD_CLOEXEC.
-                Ok(fd) => {
-                    return Ok(if cfg!(target_os = "linux") {
-                        make_filedesc(fd)?
-                    } else {
-                        FileDesc::new(fd)
-                    });
-                }
-                Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {
-                    TRY_CLOEXEC.store(false, Ordering::Relaxed);
-                }
-                Err(e) => return Err(e),
-            }
-        }
-        cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc)
+        // is a POSIX flag that was added to Linux in 2.6.24.
+        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
+        Ok(FileDesc::new(fd))
     }
 }
 
index 29cdbf05354fbe353ba382332c54d8f927bb20a1..acb18e6d064e6e826d0e3910035e12fd516f1e98 100644 (file)
@@ -708,56 +708,7 @@ pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
         // However, since this is a variadic function, C integer promotion rules mean that on
         // the ABI level, this still gets passed as `c_int` (aka `u32` on Unix platforms).
         let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode as c_int) })?;
-        let fd = FileDesc::new(fd);
-
-        // Currently the standard library supports Linux 2.6.18 which did not
-        // have the O_CLOEXEC flag (passed above). If we're running on an older
-        // Linux kernel then the flag is just ignored by the OS. After we open
-        // the first file, we check whether it has CLOEXEC set. If it doesn't,
-        // we will explicitly ask for a CLOEXEC fd for every further file we
-        // open, if it does, we will skip that step.
-        //
-        // The CLOEXEC flag, however, is supported on versions of macOS/BSD/etc
-        // that we support, so we only do this on Linux currently.
-        #[cfg(target_os = "linux")]
-        fn ensure_cloexec(fd: &FileDesc) -> io::Result<()> {
-            use crate::sync::atomic::{AtomicUsize, Ordering};
-
-            const OPEN_CLOEXEC_UNKNOWN: usize = 0;
-            const OPEN_CLOEXEC_SUPPORTED: usize = 1;
-            const OPEN_CLOEXEC_NOTSUPPORTED: usize = 2;
-            static OPEN_CLOEXEC: AtomicUsize = AtomicUsize::new(OPEN_CLOEXEC_UNKNOWN);
-
-            let need_to_set;
-            match OPEN_CLOEXEC.load(Ordering::Relaxed) {
-                OPEN_CLOEXEC_UNKNOWN => {
-                    need_to_set = !fd.get_cloexec()?;
-                    OPEN_CLOEXEC.store(
-                        if need_to_set {
-                            OPEN_CLOEXEC_NOTSUPPORTED
-                        } else {
-                            OPEN_CLOEXEC_SUPPORTED
-                        },
-                        Ordering::Relaxed,
-                    );
-                }
-                OPEN_CLOEXEC_SUPPORTED => need_to_set = false,
-                OPEN_CLOEXEC_NOTSUPPORTED => need_to_set = true,
-                _ => unreachable!(),
-            }
-            if need_to_set {
-                fd.set_cloexec()?;
-            }
-            Ok(())
-        }
-
-        #[cfg(not(target_os = "linux"))]
-        fn ensure_cloexec(_: &FileDesc) -> io::Result<()> {
-            Ok(())
-        }
-
-        ensure_cloexec(&fd)?;
-        Ok(File(fd))
+        Ok(File(FileDesc::new(fd)))
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
index 3717c660b575d6f1c9e2d353be65fdfa6be3212f..011325fddc5b93b08304406256bcc748d7e8e3eb 100644 (file)
@@ -54,31 +54,26 @@ pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> {
 
     pub fn new_raw(fam: c_int, ty: c_int) -> io::Result<Socket> {
         unsafe {
-            // On linux we first attempt to pass the SOCK_CLOEXEC flag to
-            // atomically create the socket and set it as CLOEXEC. Support for
-            // this option, however, was added in 2.6.27, and we still support
-            // 2.6.18 as a kernel, so if the returned error is EINVAL we
-            // fallthrough to the fallback.
-            #[cfg(target_os = "linux")]
-            {
-                match cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0)) {
-                    Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
-                    Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
-                    Err(e) => return Err(e),
-                }
-            }
-
-            let fd = cvt(libc::socket(fam, ty, 0))?;
-            let fd = FileDesc::new(fd);
-            fd.set_cloexec()?;
-            let socket = Socket(fd);
+            cfg_if::cfg_if! {
+                if #[cfg(target_os = "linux")] {
+                    // On Linux we pass the SOCK_CLOEXEC flag to atomically create
+                    // the socket and set it as CLOEXEC, added in 2.6.27.
+                    let fd = cvt(libc::socket(fam, ty | libc::SOCK_CLOEXEC, 0))?;
+                    Ok(Socket(FileDesc::new(fd)))
+                } else {
+                    let fd = cvt(libc::socket(fam, ty, 0))?;
+                    let fd = FileDesc::new(fd);
+                    fd.set_cloexec()?;
+                    let socket = Socket(fd);
 
-            // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt`
-            // flag to disable `SIGPIPE` emission on socket.
-            #[cfg(target_vendor = "apple")]
-            setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?;
+                    // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt`
+                    // flag to disable `SIGPIPE` emission on socket.
+                    #[cfg(target_vendor = "apple")]
+                    setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?;
 
-            Ok(socket)
+                    Ok(socket)
+                }
+            }
         }
     }
 
@@ -86,24 +81,20 @@ pub fn new_pair(fam: c_int, ty: c_int) -> io::Result<(Socket, Socket)> {
         unsafe {
             let mut fds = [0, 0];
 
-            // Like above, see if we can set cloexec atomically
-            #[cfg(target_os = "linux")]
-            {
-                match cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr())) {
-                    Ok(_) => {
-                        return Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))));
-                    }
-                    Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {}
-                    Err(e) => return Err(e),
+            cfg_if::cfg_if! {
+                if #[cfg(target_os = "linux")] {
+                    // Like above, set cloexec atomically
+                    cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?;
+                    Ok((Socket(FileDesc::new(fds[0])), Socket(FileDesc::new(fds[1]))))
+                } else {
+                    cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?;
+                    let a = FileDesc::new(fds[0]);
+                    let b = FileDesc::new(fds[1]);
+                    a.set_cloexec()?;
+                    b.set_cloexec()?;
+                    Ok((Socket(a), Socket(b)))
                 }
             }
-
-            cvt(libc::socketpair(fam, ty, 0, fds.as_mut_ptr()))?;
-            let a = FileDesc::new(fds[0]);
-            let b = FileDesc::new(fds[1]);
-            a.set_cloexec()?;
-            b.set_cloexec()?;
-            Ok((Socket(a), Socket(b)))
         }
     }
 
@@ -177,30 +168,20 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
     pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result<Socket> {
         // Unfortunately the only known way right now to accept a socket and
         // atomically set the CLOEXEC flag is to use the `accept4` syscall on
-        // Linux. This was added in 2.6.28, however, and because we support
-        // 2.6.18 we must detect this support dynamically.
-        #[cfg(target_os = "linux")]
-        {
-            syscall! {
-                fn accept4(
-                    fd: c_int,
-                    addr: *mut sockaddr,
-                    addr_len: *mut socklen_t,
-                    flags: c_int
-                ) -> c_int
-            }
-            let res = cvt_r(|| unsafe { accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC) });
-            match res {
-                Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
-                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
-                Err(e) => return Err(e),
+        // Linux. This was added in 2.6.28, glibc 2.10 and musl 0.9.5.
+        cfg_if::cfg_if! {
+            if #[cfg(target_os = "linux")] {
+                let fd = cvt_r(|| unsafe {
+                    libc::accept4(self.0.raw(), storage, len, libc::SOCK_CLOEXEC)
+                })?;
+                Ok(Socket(FileDesc::new(fd)))
+            } else {
+                let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?;
+                let fd = FileDesc::new(fd);
+                fd.set_cloexec()?;
+                Ok(Socket(fd))
             }
         }
-
-        let fd = cvt_r(|| unsafe { libc::accept(self.0.raw(), storage, len) })?;
-        let fd = FileDesc::new(fd);
-        fd.set_cloexec()?;
-        Ok(Socket(fd))
     }
 
     pub fn duplicate(&self) -> io::Result<Socket> {
index a9cd5094997bd68b9e2ae6e675f0bcb61862777d..2fcb5b9c4e66e722098efde38810b1ab60389582 100644 (file)
@@ -71,6 +71,7 @@ pub fn errno() -> i32 {
 
 /// Sets the platform-specific value of errno
 #[cfg(all(not(target_os = "linux"), not(target_os = "dragonfly")))] // needed for readdir and syscall!
+#[allow(dead_code)] // but not all target cfgs actually end up using it
 pub fn set_errno(e: i32) {
     unsafe { *errno_location() = e as c_int }
 }
index f2a2eabef9132509db4c864a40ba769b0974fb0f..7ae37bdda70bded963b72d304b7abbbbfed904a9 100644 (file)
@@ -1,11 +1,8 @@
 use crate::io::{self, IoSlice, IoSliceMut};
 use crate::mem;
-use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::fd::FileDesc;
 use crate::sys::{cvt, cvt_r};
 
-use libc::c_int;
-
 ////////////////////////////////////////////////////////////////////////////////
 // Anonymous pipes
 ////////////////////////////////////////////////////////////////////////////////
 pub struct AnonPipe(FileDesc);
 
 pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
-    syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int }
-    static INVALID: AtomicBool = AtomicBool::new(false);
-
     let mut fds = [0; 2];
 
-    // Unfortunately the only known way right now to create atomically set the
-    // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
-    // 2.6.27, however, and because we support 2.6.18 we must detect this
-    // support dynamically.
-    if cfg!(any(
-        target_os = "dragonfly",
-        target_os = "freebsd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "openbsd",
-        target_os = "redox"
-    )) && !INVALID.load(Ordering::SeqCst)
-    {
-        // Note that despite calling a glibc function here we may still
-        // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
-        // emulate on older kernels, so if you happen to be running on
-        // an older kernel you may see `pipe2` as a symbol but still not
-        // see the syscall.
-        match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
-            Ok(_) => {
-                return Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1]))));
-            }
-            Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
-                INVALID.store(true, Ordering::SeqCst);
-            }
-            Err(e) => return Err(e),
+    // The only known way right now to create atomically set the CLOEXEC flag is
+    // to use the `pipe2` syscall. This was added to Linux in 2.6.27, glibc 2.9
+    // and musl 0.9.3, and some other targets also have it.
+    cfg_if::cfg_if! {
+        if #[cfg(any(
+            target_os = "dragonfly",
+            target_os = "freebsd",
+            target_os = "linux",
+            target_os = "netbsd",
+            target_os = "openbsd",
+            target_os = "redox"
+        ))] {
+            cvt(unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
+            Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1]))))
+        } else {
+            cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
+
+            let fd0 = FileDesc::new(fds[0]);
+            let fd1 = FileDesc::new(fds[1]);
+            fd0.set_cloexec()?;
+            fd1.set_cloexec()?;
+            Ok((AnonPipe(fd0), AnonPipe(fd1)))
         }
     }
-    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
-
-    let fd0 = FileDesc::new(fds[0]);
-    let fd1 = FileDesc::new(fds[1]);
-    fd0.set_cloexec()?;
-    fd1.set_cloexec()?;
-    Ok((AnonPipe(fd0), AnonPipe(fd1)))
 }
 
 impl AnonPipe {
index 08cbe59617465731a22fdc228c84b9d5ce7e9733..f4b33a00f7c85d79d8b682be0884024283a529f0 100644 (file)
 //! symbol, but that caused Debian to detect an unnecessarily strict versioned
 //! dependency on libc6 (#23628).
 
+// There are a variety of `#[cfg]`s controlling which targets are involved in
+// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
+// that, we'll just allow that some unix targets don't use this module at all.
+#![allow(dead_code, unused_macros)]
+
 use crate::ffi::CStr;
 use crate::marker;
 use crate::mem;
index 7fa86f0db043f21bc2be1efa9a6c719aba73327d..ea186846929be135479736277e31ece1035b4960 100644 (file)
@@ -13,12 +13,10 @@ pub struct FileDesc {
     fd: c_int,
 }
 
-fn max_len() -> usize {
-    // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
-    // with the man page quoting that if the count of bytes to read is
-    // greater than `SSIZE_MAX` the result is "unspecified".
-    <ssize_t>::MAX as usize
-}
+// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
+// with the man page quoting that if the count of bytes to read is
+// greater than `SSIZE_MAX` the result is "unspecified".
+const READ_LIMIT: usize = ssize_t::MAX as usize;
 
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
@@ -29,7 +27,7 @@ pub fn raw(&self) -> c_int {
         self.fd
     }
 
-    /// Extracts the actual filedescriptor without closing it.
+    /// Extracts the actual file descriptor without closing it.
     pub fn into_raw(self) -> c_int {
         let fd = self.fd;
         mem::forget(self);
@@ -38,7 +36,7 @@ pub fn into_raw(self) -> c_int {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
-            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), max_len()))
+            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
         })?;
         Ok(ret as usize)
     }
@@ -79,7 +77,7 @@ unsafe fn cvt_pread(
             cvt_pread(
                 self.fd,
                 buf.as_mut_ptr() as *mut c_void,
-                cmp::min(buf.len(), max_len()),
+                cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
             )
             .map(|n| n as usize)
@@ -88,7 +86,7 @@ unsafe fn cvt_pread(
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
-            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), max_len()))
+            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
         })?;
         Ok(ret as usize)
     }
@@ -124,7 +122,7 @@ unsafe fn cvt_pwrite(
             cvt_pwrite(
                 self.fd,
                 buf.as_ptr() as *const c_void,
-                cmp::min(buf.len(), max_len()),
+                cmp::min(buf.len(), READ_LIMIT),
                 offset as i64,
             )
             .map(|n| n as usize)
index 8365c9ee9c995dbdd70c045e30fb573dac424eeb..8f46f4d284f0bf71ad499c3457da75c9faac5a55 100644 (file)
@@ -1,6 +1,6 @@
 use crate::cmp::Ordering;
 use crate::time::Duration;
-use ::core::hash::{Hash, Hasher};
+use core::hash::{Hash, Hasher};
 
 pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
 use crate::convert::TryInto;
index 5f8b1cbfa0b5314a37a4355318a52996a84ad344..58c8c46c969c180cf38f46107908de10445f577f 100644 (file)
@@ -18,5 +18,5 @@ pub mod prelude {
     pub use crate::sys::ext::fs::{DirEntryExt, FileExt, MetadataExt, OpenOptionsExt};
     #[doc(no_inline)]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd};
+    pub use crate::sys::ext::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
 }
index 793daea43c215baf07149e2157d73781a7102634..2eed9e436a956003a200a6af668024da9b786f0c 100644 (file)
@@ -597,14 +597,14 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
 ///
 /// WASI has no fundamental capability to do this. All syscalls and operations
 /// are relative to already-open file descriptors. The C library, however,
-/// manages a map of preopened file descriptors to their path, and then the C
+/// manages a map of pre-opened file descriptors to their path, and then the C
 /// library provides an API to look at this. In other words, when you want to
 /// open a path `p`, you have to find a previously opened file descriptor in a
 /// global table and then see if `p` is relative to that file descriptor.
 ///
 /// This function, if successful, will return two items:
 ///
-/// * The first is a `ManuallyDrop<WasiFd>`. This represents a preopened file
+/// * The first is a `ManuallyDrop<WasiFd>`. This represents a pre-opened file
 ///   descriptor which we don't have ownership of, but we can use. You shouldn't
 ///   actually drop the `fd`.
 ///
@@ -619,7 +619,7 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
 /// appropriate rights for performing `rights` actions.
 ///
 /// Note that this can fail if `p` doesn't look like it can be opened relative
-/// to any preopened file descriptor.
+/// to any pre-opened file descriptor.
 fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
     let p = CString::new(p.as_os_str().as_bytes())?;
     unsafe {
@@ -627,7 +627,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
         let fd = __wasilibc_find_relpath(p.as_ptr(), &mut ret);
         if fd == -1 {
             let msg = format!(
-                "failed to find a preopened file descriptor \
+                "failed to find a pre-opened file descriptor \
                  through which {:?} could be opened",
                 p
             );
index e0bb102b3afe5b8e746ea51d420466e41b8112bb..82901871e78ae25d68abdc50948af105064251af 100644 (file)
@@ -110,6 +110,16 @@ struct Node {
     next: *mut Node,
 }
 
+#[cfg(miri)]
+extern "Rust" {
+    /// Miri-provided extern function to mark the block `ptr` points to as a "root"
+    /// for some static memory. This memory and everything reachable by it is not
+    /// considered leaking even if it still exists when the program terminates.
+    ///
+    /// `ptr` has to point to the beginning of an allocated block.
+    fn miri_static_root(ptr: *const u8);
+}
+
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
     let mut node = Box::new(Node { key, dtor, next: ptr::null_mut() });
 
@@ -117,7 +127,13 @@ unsafe fn register_dtor(key: Key, dtor: Dtor) {
     loop {
         node.next = head;
         match DTORS.compare_exchange(head, &mut *node, SeqCst, SeqCst) {
-            Ok(_) => return mem::forget(node),
+            Ok(_) => {
+                #[cfg(miri)]
+                miri_static_root(&*node as *const _ as *const u8);
+
+                mem::forget(node);
+                return;
+            }
             Err(cur) => head = cur,
         }
     }
index d386a656e4ffdc896aa93fdceb53060d1c75a71c..e9b1e86d7ae49ed8e66a6f5a995be65ceb8ef4d5 100644 (file)
@@ -1,4 +1,3 @@
-use crate::backtrace_rs::{self, BacktraceFmt, BytesOrWideString, PrintFmt};
 use crate::borrow::Cow;
 /// Common code for printing the backtrace in the same way across the different
 /// supported platforms.
@@ -10,6 +9,8 @@
 use crate::sync::atomic::{self, Ordering};
 use crate::sys::mutex::Mutex;
 
+use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt};
+
 /// Max number of frames to print.
 const MAX_NB_FRAMES: usize = 100;
 
index 77bcfffd506c93a6913f1f0fea7390a435793814..b6baa9a8c6bcc71b77d42e3ffe1cf2fef45ab7bd 100644 (file)
@@ -2,7 +2,6 @@
 authors = ["The Rust Project Developers"]
 name = "unwind"
 version = "0.0.0"
-build = "build.rs"
 edition = "2018"
 include = [
   '/libunwind/*',
index f6005eed43c7d85afba6c4ddef2516fe70206a4b..9d79171c4cb98e120f46390d19bdb128cf48bf88 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags:-Zprint-mono-items=eager
+// compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on
 
 #![feature(start)]
 
@@ -6,7 +6,7 @@
 
 pub fn foo<T>() { }
 
-//~ MONO_ITEM fn static_init::foo[0]<i32>
+//~ MONO_ITEM fn static_init::foo[0]<T>
 //~ MONO_ITEM static static_init::FN[0]
 
 //~ MONO_ITEM fn static_init::start[0]
index 11f6cc62d49e3c9ee72f3b8c2befb8db8a5297f1..6cf59fdc39694b3488eed5848cc83c90511c5e08 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags:-Zprint-mono-items=eager
+// compile-flags:-Zprint-mono-items=eager -Zpolymorphize=on
 
 #![deny(dead_code)]
 #![feature(start)]
@@ -27,7 +27,7 @@ impl SomeGenericTrait<u64> for i32 {
 
     // For the non-generic foo(), we should generate a codegen-item even if it
     // is not called anywhere
-    //~ MONO_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<i32, u64>
+    //~ MONO_ITEM fn trait_method_default_impl::SomeGenericTrait[0]::foo[0]<i32, T1>
 }
 
 // Non-generic impl of generic trait
diff --git a/src/test/codegen-units/polymorphization/unused_type_parameters.rs b/src/test/codegen-units/polymorphization/unused_type_parameters.rs
new file mode 100644 (file)
index 0000000..403f68b
--- /dev/null
@@ -0,0 +1,323 @@
+// compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1
+// ignore-tidy-linelength
+
+#![crate_type = "rlib"]
+
+// This test checks that the polymorphization analysis correctly reduces the
+// generated mono items.
+
+mod functions {
+    // Function doesn't have any type parameters to be unused.
+    pub fn no_parameters() {}
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::no_parameters[0]
+
+    // Function has an unused type parameter.
+    pub fn unused<T>() {
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::unused[0]<T>
+
+    // Function uses type parameter in value of a binding.
+    pub fn used_binding_value<T: Default>() {
+        let _: T = Default::default();
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_value[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_value[0]<u64>
+
+    // Function uses type parameter in type of a binding.
+    pub fn used_binding_type<T>() {
+        let _: Option<T> = None;
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_type[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_binding_type[0]<u64>
+
+    // Function uses type parameter in argument.
+    pub fn used_argument<T>(_: T) {
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_argument[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_argument[0]<u64>
+//
+    // Function uses type parameter in substitutions to another function.
+    pub fn used_substs<T>() {
+        unused::<T>()
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_substs[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::functions[0]::used_substs[0]<u64>
+}
+
+
+mod closures {
+    // Function doesn't have any type parameters to be unused.
+    pub fn no_parameters() {
+        let _ = || {};
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::no_parameters[0]
+
+    // Function has an unused type parameter in parent and closure.
+    pub fn unused<T>() -> u32 {
+        let add_one = |x: u32| x + 1;
+        add_one(3)
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::unused[0]::{{closure}}[0]<T, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::unused[0]<T>
+
+    // Function has an unused type parameter in closure, but not in parent.
+    pub fn used_parent<T: Default>() -> u32 {
+        let _: T = Default::default();
+        let add_one = |x: u32| x + 1;
+        add_one(3)
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0]::{{closure}}[0]<T, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_parent[0]<u64>
+
+    // Function uses type parameter in value of a binding in closure.
+    pub fn used_binding_value<T: Default>() -> T {
+        let x = || {
+            let y: T = Default::default();
+            y
+        };
+
+        x()
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn(()) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn(()) -> u64, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_value[0]<u64>
+
+    // Function uses type parameter in type of a binding in closure.
+    pub fn used_binding_type<T>() -> Option<T> {
+        let x = || {
+            let y: Option<T> = None;
+            y
+        };
+
+        x()
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn(()) -> core::option[0]::Option[0]<u32>, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn(()) -> core::option[0]::Option[0]<u64>, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_binding_type[0]<u64>
+
+    // Function and closure uses type parameter in argument.
+    pub fn used_argument<T>(t: T) -> u32 {
+        let x = |_: T| 3;
+        x(t)
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn((u64)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument[0]<u64>
+
+    // Closure uses type parameter in argument.
+    pub fn used_argument_closure<T: Default>() -> u32 {
+        let t: T = Default::default();
+        let x = |_: T| 3;
+        x(t)
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn((u64)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_argument_closure[0]<u64>
+
+    // Closure uses type parameter as upvar.
+    pub fn used_upvar<T: Default>() -> T {
+        let x: T = Default::default();
+        let y = || x;
+        y()
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]::{{closure}}[0]<u32, i32, extern "rust-call" fn(()) -> u32, (u32)>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]::{{closure}}[0]<u64, i32, extern "rust-call" fn(()) -> u64, (u64)>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_upvar[0]<u64>
+
+    // Closure uses type parameter in substitutions to another function.
+    pub fn used_substs<T>() {
+        let x = || super::functions::unused::<T>();
+        x()
+    }
+
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn(()), ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn(()), ()>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::closures[0]::used_substs[0]<u64>
+}
+
+mod methods {
+    pub struct Foo<F>(F);
+
+    impl<F: Default> Foo<F> {
+        // Function has an unused type parameter from impl.
+        pub fn unused_impl() {
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::unused_impl[0]<F>
+
+        // Function has an unused type parameter from impl and fn.
+        pub fn unused_both<G: Default>() {
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::unused_both[0]<F, G>
+
+        // Function uses type parameter from impl.
+        pub fn used_impl() {
+            let _: F = Default::default();
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_impl[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_impl[0]<u64>
+
+        // Function uses type parameter from impl.
+        pub fn used_fn<G: Default>() {
+            let _: G = Default::default();
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_fn[0]<F, u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_fn[0]<F, u64>
+
+        // Function uses type parameter from impl.
+        pub fn used_both<G: Default>() {
+            let _: F = Default::default();
+            let _: G = Default::default();
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_both[0]<u32, u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_both[0]<u64, u64>
+
+        // Function uses type parameter in substitutions to another function.
+        pub fn used_substs() {
+            super::functions::unused::<F>()
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_substs[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::used_substs[0]<u64>
+
+        // Function has an unused type parameter from impl and fn.
+        pub fn closure_unused_all<G: Default>() -> u32 {
+            let add_one = |x: u32| x + 1;
+            add_one(3)
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_unused_all[0]::{{closure}}[0]<F, G, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_unused_all[0]<F, G>
+
+        // Function uses type parameter from impl and fn in closure.
+        pub fn closure_used_both<G: Default>() -> u32 {
+            let add_one = |x: u32| {
+                let _: F = Default::default();
+                let _: G = Default::default();
+                x + 1
+            };
+
+            add_one(3)
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]::{{closure}}[0]<u32, u32, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]::{{closure}}[0]<u64, u64, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]<u32, u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_both[0]<u64, u64>
+
+        // Function uses type parameter from fn in closure.
+        pub fn closure_used_fn<G: Default>() -> u32 {
+            let add_one = |x: u32| {
+                let _: G = Default::default();
+                x + 1
+            };
+
+            add_one(3)
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]::{{closure}}[0]<F, u32, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]::{{closure}}[0]<F, u64, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]<F, u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_fn[0]<F, u64>
+
+        // Function uses type parameter from impl in closure.
+        pub fn closure_used_impl<G: Default>() -> u32 {
+            let add_one = |x: u32| {
+                let _: F = Default::default();
+                x + 1
+            };
+
+            add_one(3)
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]::{{closure}}[0]<u32, G, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]::{{closure}}[0]<u64, G, i8, extern "rust-call" fn((u32)) -> u32, ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]<u32, G>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_impl[0]<u64, G>
+
+        // Closure uses type parameter in substitutions to another function.
+        pub fn closure_used_substs() {
+            let x = || super::functions::unused::<F>();
+            x()
+        }
+
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]::{{closure}}[0]<u32, i8, extern "rust-call" fn(()), ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]::{{closure}}[0]<u64, i8, extern "rust-call" fn(()), ()>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::methods[0]::{{impl}}[0]::closure_used_substs[0]<u64>
+    }
+}
+
+
+
+fn dispatch<T: Default>() {
+    functions::no_parameters();
+    functions::unused::<T>();
+    functions::used_binding_value::<T>();
+    functions::used_binding_type::<T>();
+    functions::used_argument::<T>(Default::default());
+    functions::used_substs::<T>();
+
+    closures::no_parameters();
+    let _ = closures::unused::<T>();
+    let _ = closures::used_parent::<T>();
+    let _ = closures::used_binding_value::<T>();
+    let _ = closures::used_binding_type::<T>();
+    let _ = closures::used_argument::<T>(Default::default());
+    let _ = closures::used_argument_closure::<T>();
+    let _ = closures::used_upvar::<T>();
+    let _ = closures::used_substs::<T>();
+
+    methods::Foo::<T>::unused_impl();
+    methods::Foo::<T>::unused_both::<T>();
+    methods::Foo::<T>::used_impl();
+    methods::Foo::<T>::used_fn::<T>();
+    methods::Foo::<T>::used_both::<T>();
+    methods::Foo::<T>::used_substs();
+    let _ = methods::Foo::<T>::closure_unused_all::<T>();
+    let _ = methods::Foo::<T>::closure_used_both::<T>();
+    let _ = methods::Foo::<T>::closure_used_impl::<T>();
+    let _ = methods::Foo::<T>::closure_used_fn::<T>();
+    let _ = methods::Foo::<T>::closure_used_substs();
+}
+
+//~ MONO_ITEM fn unused_type_parameters::dispatch[0]<u32>
+//~ MONO_ITEM fn unused_type_parameters::dispatch[0]<u64>
+
+pub fn foo() {
+    // Generate two copies of each function to check that where the type parameter is unused,
+    // there is only a single copy.
+    dispatch::<u32>();
+    dispatch::<u64>();
+}
+
+//~ MONO_ITEM fn unused_type_parameters::foo[0] @@ unused_type_parameters-cgu.0[External]
+
+// These are all the items that aren't relevant to the test.
+//~ MONO_ITEM fn core::default[0]::{{impl}}[6]::default[0]
+//~ MONO_ITEM fn core::default[0]::{{impl}}[7]::default[0]
index 8aeee5859d0adedcf8be1436101ebe03aa35e840..7c61b7809901f81c7f67d1d7c0b45ee5489fffe4 100644 (file)
@@ -2,7 +2,7 @@
 
 // revisions:x86_64 i686 arm
 
-// min-llvm-version 9.0
+// min-llvm-version: 9.0
 
 //[x86_64] compile-flags: --target x86_64-unknown-uefi
 //[i686] compile-flags: --target i686-unknown-linux-musl
diff --git a/src/test/codegen/avr/avr-func-addrspace.rs b/src/test/codegen/avr/avr-func-addrspace.rs
new file mode 100644 (file)
index 0000000..7759d96
--- /dev/null
@@ -0,0 +1,93 @@
+// compile-flags: -O --target=avr-unknown-unknown --crate-type=rlib
+
+// This test validates that function pointers can be stored in global variables
+// and called upon. It ensures that Rust emits function pointers in the correct
+// address space to LLVM so that an assertion error relating to casting is
+// not triggered.
+//
+// It also validates that functions can be called through function pointers
+// through traits.
+
+#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized { }
+#[lang = "copy"]
+pub trait Copy { }
+#[lang = "receiver"]
+pub trait Receiver { }
+
+pub struct Result<T, E> { _a: T, _b: E }
+
+impl Copy for usize {}
+
+#[lang = "drop_in_place"]
+pub unsafe fn drop_in_place<T: ?Sized>(_: *mut T) {}
+
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn_mut"]
+pub trait FnMut<Args> : FnOnce<Args> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+#[lang = "fn"]
+pub trait Fn<Args>: FnOnce<Args> {
+    /// Performs the call operation.
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
+impl<'a, A, R> FnOnce<A> for &'a fn(A) -> R {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, args: A) -> R {
+        (*self)(args)
+    }
+}
+
+pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
+pub static mut STORAGE_BAR: u32 = 12;
+
+fn arbitrary_black_box(ptr: &usize, _: &mut u32) -> Result<(), ()> {
+    let raw_ptr = ptr as *const usize;
+    let _v: usize = unsafe { *raw_ptr };
+    loop {}
+}
+
+#[inline(never)]
+#[no_mangle]
+fn call_through_fn_trait(a: &mut impl Fn<(), Output=()>) {
+    (*a)()
+}
+
+#[inline(never)]
+fn update_bar_value() {
+    unsafe {
+        STORAGE_BAR = 88;
+    }
+}
+
+// CHECK: define void @test(){{.+}}addrspace(1)
+#[no_mangle]
+pub extern "C" fn test() {
+    let mut buf = 7;
+
+    // A call through the Fn trait must use address space 1.
+    //
+    // CHECK: call{{.+}}addrspace(1) void @call_through_fn_trait()
+    call_through_fn_trait(&mut update_bar_value);
+
+    // A call through a global variable must use address space 1.
+    // CHECK: load {{.*}}addrspace(1){{.+}}FOO
+    unsafe {
+        STORAGE_FOO(&1, &mut buf);
+    }
+}
index 96a0a321199a37dc6e03eeb8f973cda45862ba64..571a2654bcbfd2f6d7f6543479d009f6abe3cad7 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z control-flow-guard=checks
+// compile-flags: -C control-flow-guard=checks
 // only-msvc
 
 #![crate_type = "lib"]
index 925e4e8e2d15557bc4dd9fdb9d43fcddba7cc6c1..c3f8f4116819ce2bf420dce85a50b7c7926dc24c 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z control-flow-guard=no
+// compile-flags: -C control-flow-guard=no
 // only-msvc
 
 #![crate_type = "lib"]
index d7dc3d7e89eea007fdeb644d237efab8dd6c181d..3847c3e81ed7a6d78f2e3e6b50741fb549c68431 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z control-flow-guard=nochecks
+// compile-flags: -C control-flow-guard=nochecks
 // only-msvc
 
 #![crate_type = "lib"]
index 4008f0187a0b05bc318262744e5d8bb17d4ff63e..6278a951e35f1565151946520f4919088e9b20eb 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z control-flow-guard
+// compile-flags: -C control-flow-guard
 // ignore-msvc
 
 #![crate_type = "lib"]
index fbaf38d69df7fc2608e92060fe69bdc50b3bcefd..eba4a7469f9308d2ade0946fdaa1d916cc82e6e0 100644 (file)
@@ -1,4 +1,4 @@
-// min-llvm-version 8.0
+// min-llvm-version: 8.0
 // compile-flags: -C no-prepopulate-passes -C force-unwind-tables=y
 
 #![crate_type="lib"]
index 8ade583b5712732466153f2161f43fa49d0d7141..a3aca3a2912a6c2cc31b0bc0829200dae96f817e 100644 (file)
@@ -12,7 +12,7 @@
 // CHECK-LABEL: @already_sliced_no_bounds_check
 #[no_mangle]
 pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
-    // CHECK: slice_index_len_fail
+    // CHECK: slice_end_index_len_fail
     // CHECK-NOT: panic_bounds_check
     let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
     for i in 0..1024 {
@@ -23,7 +23,7 @@ pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
 // CHECK-LABEL: @already_sliced_no_bounds_check_exact
 #[no_mangle]
 pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
-    // CHECK: slice_index_len_fail
+    // CHECK: slice_end_index_len_fail
     // CHECK-NOT: panic_bounds_check
     let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
     for i in 0..1024 {
@@ -35,7 +35,7 @@ pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
 // CHECK-LABEL: @already_sliced_bounds_check
 #[no_mangle]
 pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
-    // CHECK: slice_index_len_fail
+    // CHECK: slice_end_index_len_fail
     // CHECK: panic_bounds_check
     let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
     for i in 0..1024 {
index 789feea12d6d7e8a67ecfd84b406b5fb99571c37..4e3bfcd439744cb77b60cdbcc8575cb9a4e3441f 100644 (file)
@@ -2,6 +2,7 @@
 // unchecked intrinsics.
 
 // compile-flags: -C opt-level=3
+// ignore-wasm32 the wasm target is tested in `wasm_casts_*`
 
 #![crate_type = "lib"]
 
index 45b905190493a12151704411e8b8955842f16d1b..b7f8522fdfb033664327e8e7a65d84e1730af16c 100644 (file)
@@ -38,7 +38,6 @@ pub fn cast_f32_i32(a: f32) -> i32 {
     a as _
 }
 
-
 // CHECK-LABEL: @cast_f64_u64
 #[no_mangle]
 pub fn cast_f64_u64(a: f64) -> u64 {
@@ -84,13 +83,10 @@ pub fn cast_f32_u8(a: f32) -> u8 {
     a as _
 }
 
-
-
 // CHECK-LABEL: @cast_unchecked_f64_i64
 #[no_mangle]
 pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptosi double {{.*}} to i64
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
     // CHECK-NEXT: ret i64 {{.*}}
     a.to_int_unchecked()
 }
@@ -98,8 +94,7 @@ pub unsafe fn cast_unchecked_f64_i64(a: f64) -> i64 {
 // CHECK-LABEL: @cast_unchecked_f64_i32
 #[no_mangle]
 pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptosi double {{.*}} to i32
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
     // CHECK-NEXT: ret i32 {{.*}}
     a.to_int_unchecked()
 }
@@ -107,8 +102,7 @@ pub unsafe fn cast_unchecked_f64_i32(a: f64) -> i32 {
 // CHECK-LABEL: @cast_unchecked_f32_i64
 #[no_mangle]
 pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptosi float {{.*}} to i64
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
     // CHECK-NEXT: ret i64 {{.*}}
     a.to_int_unchecked()
 }
@@ -116,18 +110,15 @@ pub unsafe fn cast_unchecked_f32_i64(a: f32) -> i64 {
 // CHECK-LABEL: @cast_unchecked_f32_i32
 #[no_mangle]
 pub unsafe fn cast_unchecked_f32_i32(a: f32) -> i32 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptosi float {{.*}} to i32
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.signed.{{.*}}
     // CHECK-NEXT: ret i32 {{.*}}
     a.to_int_unchecked()
 }
 
-
 // CHECK-LABEL: @cast_unchecked_f64_u64
 #[no_mangle]
 pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptoui double {{.*}} to i64
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
     // CHECK-NEXT: ret i64 {{.*}}
     a.to_int_unchecked()
 }
@@ -135,8 +126,7 @@ pub unsafe fn cast_unchecked_f64_u64(a: f64) -> u64 {
 // CHECK-LABEL: @cast_unchecked_f64_u32
 #[no_mangle]
 pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptoui double {{.*}} to i32
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
     // CHECK-NEXT: ret i32 {{.*}}
     a.to_int_unchecked()
 }
@@ -144,8 +134,7 @@ pub unsafe fn cast_unchecked_f64_u32(a: f64) -> u32 {
 // CHECK-LABEL: @cast_unchecked_f32_u64
 #[no_mangle]
 pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptoui float {{.*}} to i64
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
     // CHECK-NEXT: ret i64 {{.*}}
     a.to_int_unchecked()
 }
@@ -153,8 +142,7 @@ pub unsafe fn cast_unchecked_f32_u64(a: f32) -> u64 {
 // CHECK-LABEL: @cast_unchecked_f32_u32
 #[no_mangle]
 pub unsafe fn cast_unchecked_f32_u32(a: f32) -> u32 {
-    // CHECK-NOT: {{.*}} call {{.*}} @llvm.wasm.trunc.{{.*}}
-    // CHECK: fptoui float {{.*}} to i32
+    // CHECK: {{.*}} call {{.*}} @llvm.wasm.trunc.unsigned.{{.*}}
     // CHECK-NEXT: ret i32 {{.*}}
     a.to_int_unchecked()
 }
index 98ad8983a60a0bd470360bddc2ac9c196c168ea1..a5d5942b539539861978d420ba2bd61630c7a591 100644 (file)
@@ -1,5 +1,5 @@
 // This test does not passed with gdb < 8.0. See #53497.
-// min-gdb-version 8.0
+// min-gdb-version: 8.0
 
 // compile-flags:-g
 
index 2616c9465246ee5ef96497735086cf26e2961da9..cbd2278f7e27c863f3dd5211e5022f82afc5f0a3 100644 (file)
@@ -2,7 +2,7 @@
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 8.1
+// min-gdb-version: 8.1
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
index 4e95a028e074948baadc3a085a515d54dc8a9edd..a4fbff5725c97aa20bbf0694a219199d597384c4 100644 (file)
@@ -6,7 +6,7 @@
 
 // The pretty printers being tested here require the patch from
 // https://sourceware.org/bugzilla/show_bug.cgi?id=21763
-// min-gdb-version 8.1
+// min-gdb-version: 8.1
 
 // min-lldb-version: 310
 
index 57721ce103c3921706a6fe24a33d99aa0c35e463..7ae82d522b09dc37dfe588b52b7da46a4d428501 100644 (file)
@@ -2,7 +2,7 @@
 // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 7.7
+// min-gdb-version: 7.7
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
index 7ce004681e100ab6954382c1567ade4cf2a8a90b..61791f48f4db76683adde4dcbacbed0038a72015 100644 (file)
@@ -2,7 +2,7 @@
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 8.1
+// min-gdb-version: 8.1
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
diff --git a/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs b/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
new file mode 100644 (file)
index 0000000..91a9f63
--- /dev/null
@@ -0,0 +1,36 @@
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+
+// We use #[inline(always)] to ensure that the downstream crate
+// will always load the MIR for these functions
+
+#![feature(rustc_attrs)]
+
+#[allow(unused)]
+macro_rules! first_macro {
+    () => {
+        println!("New call!");
+    }
+}
+
+#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[inline(always)]
+pub fn changed_fn() {
+    // This will cause additional hygiene to be generate,
+    // which will cause the SyntaxContext/ExpnId raw ids to be
+    // different when we write out `my_fn` to the crate metadata.
+    #[cfg(rpass2)]
+    first_macro!();
+}
+
+macro_rules! print_loc {
+    () => {
+        println!("Caller loc: {}", std::panic::Location::caller());
+    }
+}
+
+#[rustc_clean(cfg="rpass2")]
+#[inline(always)]
+pub fn unchanged_fn() {
+    print_loc!();
+}
diff --git a/src/test/incremental/hygiene/load_cached_hygiene.rs b/src/test/incremental/hygiene/load_cached_hygiene.rs
new file mode 100644 (file)
index 0000000..8124141
--- /dev/null
@@ -0,0 +1,48 @@
+// revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
+// aux-build:cached_hygiene.rs
+
+// This tests the folllowing scenario
+// 1. A foreign crate is compiled with incremental compilation.
+//    This causes hygiene information to be saved to the incr cache.
+// 2. One function is the foreign crate is modified. This causes the
+//    optimized mir for an unmodified function to be loaded from the
+//    incremental cache and written out to the crate metadata.
+// 3. In the process of loading and writing out this function's MIR,
+//    we load hygiene information from the incremental cache and
+//    write it to our metadata.
+// 4. This hygiene information is loaded by another crate (this file)
+
+// Previously, this situation would cause hygiene identifiers
+// (SyntaxContexts and ExpnIds) to get corrupted when we tried to
+// serialize the hygiene information loaded from the incr cache into
+// the metadata. Specifically, we were not resetting `orig_id`
+// for an `EpxnData` generate in the current crate, which would cause
+// us to serialize the `ExpnId` pointing to a garbage location in
+// the metadata.
+
+#![feature(rustc_attrs)]
+
+#![rustc_partition_reused(module="load_cached_hygiene-call_unchanged_function", cfg="rpass2")]
+#![rustc_partition_codegened(module="load_cached_hygiene-call_changed_function", cfg="rpass2")]
+
+
+extern crate cached_hygiene;
+
+pub mod call_unchanged_function {
+
+    pub fn unchanged() {
+        cached_hygiene::unchanged_fn();
+    }
+}
+
+pub mod call_changed_function {
+    pub fn changed() {
+        cached_hygiene::changed_fn();
+    }
+}
+
+pub fn main() {
+    call_unchanged_function::unchanged();
+    call_changed_function::changed();
+}
index 48908479935d1e2a2311e5fb627d882360e354a4..bbd6c8042f1964ab3f22f748bbf70b7d4315bb5b 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/array_index.rs:5:18: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/array_index.rs:5:18: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000004))
++                                          // mir::Constant
++                                          // + span: $DIR/array_index.rs:5:18: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000004)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000002))
++                                          // mir::Constant
++                                          // + span: $DIR/array_index.rs:5:18: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) }
       }
   
       bb1: {
index fd662698a0fd431b4003d4156907aeca2e5c15ce..d9096e5f3f13e27a7a3174da6ee29cda6d11f0d7 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/array_index.rs:5:18: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/array_index.rs:5:18: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000004))
++                                          // mir::Constant
++                                          // + span: $DIR/array_index.rs:5:18: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000004)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000002))
++                                          // mir::Constant
++                                          // + span: $DIR/array_index.rs:5:18: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
       }
   
       bb1: {
index ed28678edb30d6aef09522d7760a799d7ba2cd58..4bd4bb0dd7dd4ea4b5fe846b7c29f64659ae1048 100644 (file)
 -                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // + span: $DIR/bad_op_div_by_zero.rs:5:18: 5:19
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
+-         assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+                                           // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         assert(!const true, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-          assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
-                                           // ty::Const
++                                          // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
 -         _7 = BitAnd(move _5, move _6);   // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 -         assert(!move _7, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
-+         assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
-+                                          // ty::Const
++         assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+                                           // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x00))
 +                                          // mir::Constant
 +                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
-                                           // ty::Const
++                                          // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000000))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
       }
   
       bb2: {
-          _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+-         _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++         _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
                                            // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000000))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
           StorageDead(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19
           _0 = const ();                   // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2
                                            // ty::Const
index 8855df95aeab5c5e2590cd81a8aeac12a13b05bd..ecd030e32b4ee76dc01668d8925e9d79a7ee09b0 100644 (file)
 -                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
+-         assert(!move _4, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+                                           // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++         assert(!const true, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-          assert(!move _4, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
-                                           // ty::Const
++                                          // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
 -         _7 = BitAnd(move _5, move _6);   // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 -         assert(!move _7, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
-+         assert(!const false, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
-+                                          // ty::Const
++         assert(!const false, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+                                           // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x00))
 +                                          // mir::Constant
 +                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
-                                           // ty::Const
++                                          // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000000))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
       }
   
       bb2: {
-          _2 = Rem(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+-         _2 = Rem(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++         _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
                                            // ty::Const
                                            // + ty: i32
                                            // + val: Value(Scalar(0x00000001))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15
                                            // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
++                                          // ty::Const
++                                          // + ty: i32
++                                          // + val: Value(Scalar(0x00000000))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
++                                          // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
           StorageDead(_3);                 // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19
           _0 = const ();                   // scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 6:2
                                            // ty::Const
index 0f9c81943eda98677beb8e0aee98546620e906ea..2b5010759d75000e74b2f75c4e8e16a748c6a5de 100644 (file)
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
                                            // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
           _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-          _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-          assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000003))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
++         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000003))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
       }
   
       bb1: {
index da2c8dffb24110c4650f9ae0a84c00c4d39eb654..301aaf29247612556cac550f40d633c26dba1952 100644 (file)
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24
                                            // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
           _7 = Len((*_1));                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-          _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
-          assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         _8 = Lt(_6, _7);                 // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
+-         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++         _8 = Lt(const 3_usize, _7);      // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000003))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
++         assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000003))
++                                          // mir::Constant
++                                          // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs
new file mode 100644 (file)
index 0000000..4e09acb
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: -O -Zmir-opt-level=3
+
+// EMIT_MIR rustc.test.ConstProp.diff
+pub fn test(x: bool, y: bool) -> bool {
+    (y | true) & (x & false)
+}
+
+fn main() {
+    test(true, false);
+}
diff --git a/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/boolean_identities/rustc.test.ConstProp.diff
new file mode 100644 (file)
index 0000000..b8f0ad4
--- /dev/null
@@ -0,0 +1,53 @@
+- // MIR for `test` before ConstProp
++ // MIR for `test` after ConstProp
+  
+  fn test(_1: bool, _2: bool) -> bool {
+      debug x => _1;                       // in scope 0 at $DIR/boolean_identities.rs:4:13: 4:14
+      debug y => _2;                       // in scope 0 at $DIR/boolean_identities.rs:4:22: 4:23
+      let mut _0: bool;                    // return place in scope 0 at $DIR/boolean_identities.rs:4:34: 4:38
+      let mut _3: bool;                    // in scope 0 at $DIR/boolean_identities.rs:5:5: 5:15
+      let mut _4: bool;                    // in scope 0 at $DIR/boolean_identities.rs:5:6: 5:7
+      let mut _5: bool;                    // in scope 0 at $DIR/boolean_identities.rs:5:18: 5:29
+      let mut _6: bool;                    // in scope 0 at $DIR/boolean_identities.rs:5:19: 5:20
+  
+      bb0: {
+          StorageLive(_3);                 // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15
+          StorageLive(_4);                 // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7
+          _4 = _2;                         // scope 0 at $DIR/boolean_identities.rs:5:6: 5:7
+-         _3 = BitOr(move _4, const true); // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15
++         _3 = const true;                 // scope 0 at $DIR/boolean_identities.rs:5:5: 5:15
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x01))
+                                           // mir::Constant
+-                                          // + span: $DIR/boolean_identities.rs:5:10: 5:14
++                                          // + span: $DIR/boolean_identities.rs:5:5: 5:15
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+          StorageDead(_4);                 // scope 0 at $DIR/boolean_identities.rs:5:14: 5:15
+          StorageLive(_5);                 // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29
+          StorageLive(_6);                 // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20
+          _6 = _1;                         // scope 0 at $DIR/boolean_identities.rs:5:19: 5:20
+-         _5 = BitAnd(move _6, const false); // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29
++         _5 = const false;                // scope 0 at $DIR/boolean_identities.rs:5:18: 5:29
+                                           // ty::Const
+                                           // + ty: bool
+                                           // + val: Value(Scalar(0x00))
+                                           // mir::Constant
+-                                          // + span: $DIR/boolean_identities.rs:5:23: 5:28
++                                          // + span: $DIR/boolean_identities.rs:5:18: 5:29
+                                           // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          StorageDead(_6);                 // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29
+-         _0 = BitAnd(move _3, move _5);   // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29
++         _0 = const false;                // scope 0 at $DIR/boolean_identities.rs:5:5: 5:29
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x00))
++                                          // mir::Constant
++                                          // + span: $DIR/boolean_identities.rs:5:5: 5:29
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+          StorageDead(_5);                 // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29
+          StorageDead(_3);                 // scope 0 at $DIR/boolean_identities.rs:5:28: 5:29
+          return;                          // scope 0 at $DIR/boolean_identities.rs:6:2: 6:2
+      }
+  }
+  
index 26010b43c922ae80dcefc7c5e579958a9dc7333a..539a16f52dca285440733f10777372b557cb2204 100644 (file)
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
+-         switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
++         switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/discriminant.rs:11:26: 11:30
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
       }
   
       bb3: {
index b09c9c47661169dd07ec9c7752aa3b3425041eec..20875448eddc91c78abf5370fc501ce67b119f3f 100644 (file)
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
+-         switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
++         switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
++                                          // ty::Const
++                                          // + ty: bool
++                                          // + val: Value(Scalar(0x01))
++                                          // mir::Constant
++                                          // + span: $DIR/discriminant.rs:11:26: 11:30
++                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
       }
   
       bb3: {
index 71980185fd5cd38bad195ab60f9b20ed7603ea1e..57906b1cabddb9c01b37afb877d0696e69b9b31a 100644 (file)
@@ -43,7 +43,7 @@
 +                                          // mir::Constant
 +                                          // + span: $DIR/indirect.rs:5:13: 5:29
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
-+         assert(!const false, "attempt to compute `{} + {}` which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
++         assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x00))
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
 +                                          // ty::Const
                                            // + ty: u8
++                                          // + val: Value(Scalar(0x02))
++                                          // mir::Constant
++                                          // + span: $DIR/indirect.rs:5:13: 5:29
++                                          // + literal: Const { ty: u8, val: Value(Scalar(0x02)) }
++                                          // ty::Const
++                                          // + ty: u8
                                            // + val: Value(Scalar(0x01))
                                            // mir::Constant
                                            // + span: $DIR/indirect.rs:5:28: 5:29
diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs
new file mode 100644 (file)
index 0000000..f40faee
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: -O -Zmir-opt-level=3
+
+// EMIT_MIR rustc.test.ConstProp.diff
+fn test(x : i32) -> i32 {
+  x * 0
+}
+
+fn main() {
+    test(10);
+}
diff --git a/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff b/src/test/mir-opt/const_prop/mult_by_zero/rustc.test.ConstProp.diff
new file mode 100644 (file)
index 0000000..7b36669
--- /dev/null
@@ -0,0 +1,25 @@
+- // MIR for `test` before ConstProp
++ // MIR for `test` after ConstProp
+  
+  fn test(_1: i32) -> i32 {
+      debug x => _1;                       // in scope 0 at $DIR/mult_by_zero.rs:4:9: 4:10
+      let mut _0: i32;                     // return place in scope 0 at $DIR/mult_by_zero.rs:4:21: 4:24
+      let mut _2: i32;                     // in scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4
+          _2 = _1;                         // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:4
+-         _0 = Mul(move _2, const 0_i32);  // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8
++         _0 = const 0_i32;                // scope 0 at $DIR/mult_by_zero.rs:5:3: 5:8
+                                           // ty::Const
+                                           // + ty: i32
+                                           // + val: Value(Scalar(0x00000000))
+                                           // mir::Constant
+-                                          // + span: $DIR/mult_by_zero.rs:5:7: 5:8
++                                          // + span: $DIR/mult_by_zero.rs:5:3: 5:8
+                                           // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) }
+          StorageDead(_2);                 // scope 0 at $DIR/mult_by_zero.rs:5:7: 5:8
+          return;                          // scope 0 at $DIR/mult_by_zero.rs:6:2: 6:2
+      }
+  }
+  
index 4bfa50e9851f417cbc2946fd8d74e485ae8ec4a4..5312784bc8aaef138f7d45d4edff8cfd73049f98 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000006))
++                                          // mir::Constant
++                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000006)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000003))
++                                          // mir::Constant
++                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
       }
   
       bb2: {
index 2d40567ce8da17d80cb8531d1a9501830651f627..7af99841366676a9964333b963931e4334d53180 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000006))
++                                          // mir::Constant
++                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000006)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000003))
++                                          // mir::Constant
++                                          // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
       }
   
       bb2: {
index 3046b2ca9b8a42b7946a91e51c12cc78624d1517..c30075bbb05fdd7dcc0c2f845a5e21dd8192346b 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/repeat.rs:6:18: 6:28
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/repeat.rs:6:18: 6:28
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000008))
++                                          // mir::Constant
++                                          // + span: $DIR/repeat.rs:6:18: 6:28
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000008)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000002))
++                                          // mir::Constant
++                                          // + span: $DIR/repeat.rs:6:18: 6:28
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) }
       }
   
       bb1: {
index c06ed33df24c1bc052ccdc0d6371e7ccec87f01f..cadce59cf954db2dddcdb3270196210183bed789 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/repeat.rs:6:18: 6:28
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/repeat.rs:6:18: 6:28
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000008))
++                                          // mir::Constant
++                                          // + span: $DIR/repeat.rs:6:18: 6:28
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000008)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000002))
++                                          // mir::Constant
++                                          // + span: $DIR/repeat.rs:6:18: 6:28
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) }
       }
   
       bb1: {
index 6eb64f75ef17e8acb79239af315246609515a65d..0a07a1a11f27541cff7a471ec14c87b9fe0ec395 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/slice_len.rs:5:5: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/slice_len.rs:5:5: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000003))
++                                          // mir::Constant
++                                          // + span: $DIR/slice_len.rs:5:5: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x00000001))
++                                          // mir::Constant
++                                          // + span: $DIR/slice_len.rs:5:5: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) }
       }
   
       bb1: {
index 2b641bef1d8028a503f079f81f9f4ddef2f520f5..f8c6f29e854df77e106c790260f01b32ace6cb3e 100644 (file)
 +                                          // mir::Constant
 +                                          // + span: $DIR/slice_len.rs:5:5: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
-+         assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
++         assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33
 +                                          // ty::Const
 +                                          // + ty: bool
 +                                          // + val: Value(Scalar(0x01))
 +                                          // mir::Constant
 +                                          // + span: $DIR/slice_len.rs:5:5: 5:33
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000003))
++                                          // mir::Constant
++                                          // + span: $DIR/slice_len.rs:5:5: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) }
++                                          // ty::Const
++                                          // + ty: usize
++                                          // + val: Value(Scalar(0x0000000000000001))
++                                          // mir::Constant
++                                          // + span: $DIR/slice_len.rs:5:5: 5:33
++                                          // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) }
       }
   
       bb1: {
index 0e30a15671528437870fb905b0e0f1e671b41ff5..2c5816c51e3e256a61921d6a5c43e7f1b243a520 100644 (file)
@@ -9,8 +9,7 @@
 //   all of the bindings for that scope.
 // * No drop flags are used.
 
-// EMIT_MIR rustc.complicated_match.SimplifyCfg-initial.after.mir
-// EMIT_MIR rustc.complicated_match.ElaborateDrops.after.mir
+// EMIT_MIR rustc.complicated_match SimplifyCfg-initial.after ElaborateDrops.after
 fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 {
     match items {
         (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1,
diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.ElaborateDrops.after.mir
deleted file mode 100644 (file)
index df6a247..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-// MIR for `complicated_match` after ElaborateDrops
-
-fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
-    debug cond => _1;                    // in scope 0 at $DIR/match-arm-scopes.rs:14:22: 14:26
-    debug items => _2;                   // in scope 0 at $DIR/match-arm-scopes.rs:14:34: 14:39
-    let mut _0: i32;                     // return place in scope 0 at $DIR/match-arm-scopes.rs:14:66: 14:69
-    let mut _3: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-    let mut _4: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-    let _5: bool;                        // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-    let _6: &bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-    let _7: std::string::String;         // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    let _8: &std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    let mut _9: bool;                    // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    let mut _10: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-    let mut _11: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    let mut _12: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    let mut _13: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-    let mut _14: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    let _15: bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-    let _16: std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-    scope 1 {
-        debug a => _5;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        debug a => _6;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        debug s => _7;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        debug s => _8;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    }
-    scope 2 {
-        debug b => _15;                  // in scope 2 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        debug t => _16;                  // in scope 2 at $DIR/match-arm-scopes.rs:17:19: 17:20
-    }
-
-    bb0: {
-        switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:15
-    }
-
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/match-arm-scopes.rs:14:1: 19:2
-    }
-
-    bb2: {
-        switchInt((_2.1: bool)) -> [false: bb14, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:16:29: 16:34
-    }
-
-    bb3: {
-        switchInt((_2.0: bool)) -> [false: bb4, otherwise: bb21]; // scope 0 at $DIR/match-arm-scopes.rs:17:10: 17:14
-    }
-
-    bb4: {
-        StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33
-        _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33
-        StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36
-        _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36
-        goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb5: {
-        _0 = const 1_i32;                // scope 1 at $DIR/match-arm-scopes.rs:16:77: 16:78
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000001))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:77: 16:78
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
-        drop(_7) -> [return: bb19, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-    }
-
-    bb6: {
-        StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        _6 = &(_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        StorageLive(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-        StorageLive(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        _10 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        switchInt(_10) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb7: {
-        _9 = (*_6);                      // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71
-        StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        switchInt(move _9) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb8: {
-        _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000003))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
-        StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb11;                    // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    }
-
-    bb9: {
-        return;                          // scope 0 at $DIR/match-arm-scopes.rs:19:2: 19:2
-    }
-
-    bb10 (cleanup): {
-        goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb11: {
-        drop(_2) -> [return: bb9, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb12: {
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        _5 = (_2.1: bool);               // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        goto -> bb5;                     // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb13: {
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb2;                     // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb14: {
-        StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        _6 = &(_2.0: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        StorageLive(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-        StorageLive(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        _13 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        switchInt(_13) -> [false: bb15, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb15: {
-        _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71
-        StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        switchInt(move _12) -> [false: bb18, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb16: {
-        _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000003))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
-        StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb11;                    // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    }
-
-    bb17: {
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        _5 = (_2.0: bool);               // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        goto -> bb5;                     // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb18: {
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb3;                     // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb19: {
-        StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb20: {
-        _0 = const 2_i32;                // scope 2 at $DIR/match-arm-scopes.rs:17:41: 17:42
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000002))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:17:41: 17:42
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) }
-        drop(_16) -> [return: bb22, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-    }
-
-    bb21: {
-        StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-        _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-        goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb22: {
-        StorageDead(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-        StorageDead(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-        goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb23: {
-        goto -> bb29;                    // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb24 (cleanup): {
-        goto -> bb1;                     // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb25 (cleanup): {
-        goto -> bb24;                    // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb26: {
-        goto -> bb9;                     // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb27 (cleanup): {
-        goto -> bb1;                     // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb28 (cleanup): {
-        goto -> bb27;                    // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb29: {
-        goto -> bb26;                    // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-}
diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
new file mode 100644 (file)
index 0000000..58847e1
--- /dev/null
@@ -0,0 +1,313 @@
+- // MIR for `complicated_match` after SimplifyCfg-initial
++ // MIR for `complicated_match` after ElaborateDrops
+  
+  fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
+      debug cond => _1;                    // in scope 0 at $DIR/match-arm-scopes.rs:13:22: 13:26
+      debug items => _2;                   // in scope 0 at $DIR/match-arm-scopes.rs:13:34: 13:39
+      let mut _0: i32;                     // return place in scope 0 at $DIR/match-arm-scopes.rs:13:66: 13:69
+      let mut _3: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+      let mut _4: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+      let _5: bool;                        // in scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+      let _6: &bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+      let _7: std::string::String;         // in scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+      let _8: &std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+      let mut _9: bool;                    // in scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      let mut _10: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+      let mut _11: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
+      let mut _12: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      let mut _13: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+      let mut _14: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
+      let _15: bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17
+      let _16: std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20
+      scope 1 {
+          debug a => _5;                   // in scope 1 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          debug a => _6;                   // in scope 1 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          debug s => _7;                   // in scope 1 at $DIR/match-arm-scopes.rs:15:20: 15:21
+          debug s => _8;                   // in scope 1 at $DIR/match-arm-scopes.rs:15:20: 15:21
+      }
+      scope 2 {
+          debug b => _15;                  // in scope 2 at $DIR/match-arm-scopes.rs:16:16: 16:17
+          debug t => _16;                  // in scope 2 at $DIR/match-arm-scopes.rs:16:19: 16:20
+      }
+  
+      bb0: {
+-         FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+-         switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
++         switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
+      }
+  
+      bb1 (cleanup): {
+          resume;                          // scope 0 at $DIR/match-arm-scopes.rs:13:1: 18:2
+      }
+  
+      bb2: {
+-         falseEdge -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:15:9: 15:22
++         switchInt((_2.1: bool)) -> [false: bb14, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34
+      }
+  
+      bb3: {
+-         switchInt((_2.1: bool)) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34
++         switchInt((_2.0: bool)) -> [false: bb4, otherwise: bb21]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14
+      }
+  
+      bb4: {
+-         falseEdge -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:25: 15:38
+-     }
+- 
+-     bb5: {
+-         switchInt((_2.0: bool)) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14
+-     }
+- 
+-     bb6: {
+-         falseEdge -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:21
+-     }
+- 
+-     bb7: {
+          StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:32: 16:33
+          _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:32: 16:33
+          StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36
+          _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:35: 16:36
+-         goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb8: {
++     bb5: {
+          _0 = const 1_i32;                // scope 1 at $DIR/match-arm-scopes.rs:15:77: 15:78
+                                           // ty::Const
+                                           // + ty: i32
+                                           // + val: Value(Scalar(0x00000001))
+                                           // mir::Constant
+                                           // + span: $DIR/match-arm-scopes.rs:15:77: 15:78
+                                           // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
+-         drop(_7) -> [return: bb24, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
++         drop(_7) -> [return: bb19, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+      }
+  
+-     bb9: {
++     bb6: {
+          StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          _6 = &(_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+          _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+-         _3 = &shallow (_2.0: bool);      // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+-         _4 = &shallow (_2.1: bool);      // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+          StorageLive(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+          StorageLive(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+          _10 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+-         FakeRead(ForMatchedPlace, _10);  // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+-         switchInt(_10) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(_10) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb10: {
+-         falseEdge -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-     }
+- 
+-     bb11: {
++     bb7: {
+          _9 = (*_6);                      // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
+          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         switchInt(move _9) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(move _9) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb12: {
++     bb8: {
+          _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
+                                           // ty::Const
+                                           // + ty: i32
+                                           // + val: Value(Scalar(0x00000003))
+                                           // mir::Constant
+                                           // + span: $DIR/match-arm-scopes.rs:15:59: 15:60
+                                           // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
+          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         goto -> bb15;                    // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
++         goto -> bb11;                    // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
+      }
+  
+-     bb13: {
++     bb9: {
+          return;                          // scope 0 at $DIR/match-arm-scopes.rs:18:2: 18:2
+      }
+  
+-     bb14 (cleanup): {
+-         drop(_2) -> bb1;                 // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     bb10 (cleanup): {
++         goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+      }
+  
+-     bb15: {
+-         drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     bb11: {
++         drop(_2) -> [return: bb9, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+      }
+  
+-     bb16: {
++     bb12: {
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForGuardBinding, _8);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          _5 = (_2.1: bool);               // scope 0 at $DIR/match-arm-scopes.rs:15:17: 15:18
+          StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+          _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:20: 15:21
+-         goto -> bb8;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb5;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb17: {
++     bb13: {
+          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         falseEdge -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         goto -> bb2;                     // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb18: {
++     bb14: {
+          StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
+          _6 = &(_2.0: bool);              // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
+          StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37
+          _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37
+-         _3 = &shallow (_2.0: bool);      // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+-         _4 = &shallow (_2.1: bool);      // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
+          StorageLive(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+          StorageLive(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+          _13 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+-         FakeRead(ForMatchedPlace, _13);  // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
+-         switchInt(_13) -> [false: bb20, otherwise: bb19]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(_13) -> [false: bb15, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb19: {
+-         falseEdge -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-     }
+- 
+-     bb20: {
++     bb15: {
+          _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
+          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         switchInt(move _12) -> [false: bb23, otherwise: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         switchInt(move _12) -> [false: bb18, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb21: {
++     bb16: {
+          _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:15:59: 15:60
+                                           // ty::Const
+                                           // + ty: i32
+                                           // + val: Value(Scalar(0x00000003))
+                                           // mir::Constant
+                                           // + span: $DIR/match-arm-scopes.rs:15:59: 15:60
+                                           // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
+          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         goto -> bb15;                    // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
++         goto -> bb11;                    // scope 0 at $DIR/match-arm-scopes.rs:15:52: 15:60
+      }
+  
+-     bb22: {
++     bb17: {
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+-         FakeRead(ForGuardBinding, _8);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
+          StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
+          _5 = (_2.0: bool);               // scope 0 at $DIR/match-arm-scopes.rs:15:26: 15:27
+          StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37
+          _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:15:36: 15:37
+-         goto -> bb8;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb5;                     // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb23: {
++     bb18: {
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         falseEdge -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
++         goto -> bb3;                     // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+      }
+  
+-     bb24: {
++     bb19: {
+          StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+-         goto -> bb28;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb25: {
++     bb20: {
+          _0 = const 2_i32;                // scope 2 at $DIR/match-arm-scopes.rs:16:41: 16:42
+                                           // ty::Const
+                                           // + ty: i32
+                                           // + val: Value(Scalar(0x00000002))
+                                           // mir::Constant
+                                           // + span: $DIR/match-arm-scopes.rs:16:41: 16:42
+                                           // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) }
+-         drop(_16) -> [return: bb27, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
++         drop(_16) -> [return: bb22, unwind: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
+      }
+  
+-     bb26: {
++     bb21: {
+          StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17
+          _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:16: 16:17
+          StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20
+          _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:19: 16:20
+-         goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb20;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb27: {
++     bb22: {
+          StorageDead(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
+          StorageDead(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
+-         goto -> bb28;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
++         goto -> bb23;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+      }
+  
+-     bb28: {
+-         drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     bb23: {
++         goto -> bb29;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb24 (cleanup): {
++         goto -> bb1;                     // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb25 (cleanup): {
++         goto -> bb24;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb26: {
++         goto -> bb9;                     // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb27 (cleanup): {
++         goto -> bb1;                     // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb28 (cleanup): {
++         goto -> bb27;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
++     }
++ 
++     bb29: {
++         goto -> bb26;                    // scope 0 at $DIR/match-arm-scopes.rs:18:1: 18:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match-arm-scopes/rustc.complicated_match.SimplifyCfg-initial.after.mir
deleted file mode 100644 (file)
index dadbc36..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-// MIR for `complicated_match` after SimplifyCfg-initial
-
-fn complicated_match(_1: bool, _2: (bool, bool, std::string::String)) -> i32 {
-    debug cond => _1;                    // in scope 0 at $DIR/match-arm-scopes.rs:14:22: 14:26
-    debug items => _2;                   // in scope 0 at $DIR/match-arm-scopes.rs:14:34: 14:39
-    let mut _0: i32;                     // return place in scope 0 at $DIR/match-arm-scopes.rs:14:66: 14:69
-    let mut _3: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-    let mut _4: &bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-    let _5: bool;                        // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-    let _6: &bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-    let _7: std::string::String;         // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    let _8: &std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    let mut _9: bool;                    // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    let mut _10: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-    let mut _11: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    let mut _12: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    let mut _13: bool;                   // in scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-    let mut _14: !;                      // in scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    let _15: bool;                       // in scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-    let _16: std::string::String;        // in scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-    scope 1 {
-        debug a => _5;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        debug a => _6;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        debug s => _7;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        debug s => _8;                   // in scope 1 at $DIR/match-arm-scopes.rs:16:20: 16:21
-    }
-    scope 2 {
-        debug b => _15;                  // in scope 2 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        debug t => _16;                  // in scope 2 at $DIR/match-arm-scopes.rs:17:19: 17:20
-    }
-
-    bb0: {
-        FakeRead(ForMatchedPlace, _2);   // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-        switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:15
-    }
-
-    bb1 (cleanup): {
-        resume;                          // scope 0 at $DIR/match-arm-scopes.rs:14:1: 19:2
-    }
-
-    bb2: {
-        falseEdge -> [real: bb9, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:9: 16:22
-    }
-
-    bb3: {
-        switchInt((_2.1: bool)) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:16:29: 16:34
-    }
-
-    bb4: {
-        falseEdge -> [real: bb18, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:25: 16:38
-    }
-
-    bb5: {
-        switchInt((_2.0: bool)) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:17:10: 17:14
-    }
-
-    bb6: {
-        falseEdge -> [real: bb26, imaginary: bb7]; // scope 0 at $DIR/match-arm-scopes.rs:17:9: 17:21
-    }
-
-    bb7: {
-        StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33
-        _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:17:32: 17:33
-        StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36
-        _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:35: 17:36
-        goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb8: {
-        _0 = const 1_i32;                // scope 1 at $DIR/match-arm-scopes.rs:16:77: 16:78
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000001))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:77: 16:78
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
-        drop(_7) -> [return: bb24, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-    }
-
-    bb9: {
-        StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        _6 = &(_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        _3 = &shallow (_2.0: bool);      // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-        _4 = &shallow (_2.1: bool);      // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-        StorageLive(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-        StorageLive(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        _10 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        FakeRead(ForMatchedPlace, _10);  // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        switchInt(_10) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb10: {
-        falseEdge -> [real: bb12, imaginary: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb11: {
-        _9 = (*_6);                      // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71
-        StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        switchInt(move _9) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb12: {
-        _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000003))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
-        StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb15;                    // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    }
-
-    bb13: {
-        return;                          // scope 0 at $DIR/match-arm-scopes.rs:19:2: 19:2
-    }
-
-    bb14 (cleanup): {
-        drop(_2) -> bb1;                 // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb15: {
-        drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-
-    bb16: {
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForGuardBinding, _8);   // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        _5 = (_2.1: bool);               // scope 0 at $DIR/match-arm-scopes.rs:16:17: 16:18
-        StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:20: 16:21
-        goto -> bb8;                     // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb17: {
-        StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        falseEdge -> [real: bb3, imaginary: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb18: {
-        StorageLive(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        _6 = &(_2.0: bool);              // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        StorageLive(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        _8 = &(_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        _3 = &shallow (_2.0: bool);      // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-        _4 = &shallow (_2.1: bool);      // scope 0 at $DIR/match-arm-scopes.rs:15:11: 15:16
-        StorageLive(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-        StorageLive(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        _13 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        FakeRead(ForMatchedPlace, _13);  // scope 0 at $DIR/match-arm-scopes.rs:16:45: 16:49
-        switchInt(_13) -> [false: bb20, otherwise: bb19]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb19: {
-        falseEdge -> [real: bb21, imaginary: bb20]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb20: {
-        _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:16:70: 16:71
-        StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        switchInt(move _12) -> [false: bb23, otherwise: bb22]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb21: {
-        _0 = const 3_i32;                // scope 0 at $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000003))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:16:59: 16:60
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000003)) }
-        StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb15;                    // scope 0 at $DIR/match-arm-scopes.rs:16:52: 16:60
-    }
-
-    bb22: {
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        FakeRead(ForGuardBinding, _8);   // scope 0 at $DIR/match-arm-scopes.rs:16:72: 16:73
-        StorageLive(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        _5 = (_2.0: bool);               // scope 0 at $DIR/match-arm-scopes.rs:16:26: 16:27
-        StorageLive(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        _7 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:16:36: 16:37
-        goto -> bb8;                     // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb23: {
-        StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        falseEdge -> [real: bb5, imaginary: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:16:42: 16:73
-    }
-
-    bb24: {
-        StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:16:77: 16:78
-        goto -> bb28;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb25: {
-        _0 = const 2_i32;                // scope 2 at $DIR/match-arm-scopes.rs:17:41: 17:42
-                                         // ty::Const
-                                         // + ty: i32
-                                         // + val: Value(Scalar(0x00000002))
-                                         // mir::Constant
-                                         // + span: $DIR/match-arm-scopes.rs:17:41: 17:42
-                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) }
-        drop(_16) -> [return: bb27, unwind: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-    }
-
-    bb26: {
-        StorageLive(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        _15 = (_2.1: bool);              // scope 0 at $DIR/match-arm-scopes.rs:17:16: 17:17
-        StorageLive(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-        _16 = move (_2.2: std::string::String); // scope 0 at $DIR/match-arm-scopes.rs:17:19: 17:20
-        goto -> bb25;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb27: {
-        StorageDead(_16);                // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-        StorageDead(_15);                // scope 0 at $DIR/match-arm-scopes.rs:17:41: 17:42
-        goto -> bb28;                    // scope 0 at $DIR/match-arm-scopes.rs:15:5: 18:6
-    }
-
-    bb28: {
-        drop(_2) -> [return: bb13, unwind: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:19:1: 19:2
-    }
-}
index a0a5b141ec0e19df5eb6b2db83b757a070643b88..5830ef033d38990198300d15843d721b42b41d29 100644 (file)
@@ -91,3 +91,58 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool {
 pub unsafe extern "C" fn check_varargs_2(_: c_int, _ap: ...) -> usize {
     0
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize {
+    continue_if!(ap.arg::<c_int>() == 1);
+    continue_if!(ap.arg::<c_int>() == 2);
+    continue_if!(ap.arg::<c_int>() == 3);
+    continue_if!(ap.arg::<c_int>() == 4);
+    continue_if!(ap.arg::<c_int>() == 5);
+    continue_if!(ap.arg::<c_int>() == 6);
+    continue_if!(ap.arg::<c_int>() == 7);
+    continue_if!(ap.arg::<c_int>() == 8);
+    continue_if!(ap.arg::<c_int>() == 9);
+    continue_if!(ap.arg::<c_int>() == 10);
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize {
+    continue_if!(ap.arg::<c_double>() == 1.0);
+    continue_if!(ap.arg::<c_double>() == 2.0);
+    continue_if!(ap.arg::<c_double>() == 3.0);
+    continue_if!(ap.arg::<c_double>() == 4.0);
+    continue_if!(ap.arg::<c_double>() == 5.0);
+    continue_if!(ap.arg::<c_double>() == 6.0);
+    continue_if!(ap.arg::<c_double>() == 7.0);
+    continue_if!(ap.arg::<c_double>() == 8.0);
+    continue_if!(ap.arg::<c_double>() == 9.0);
+    continue_if!(ap.arg::<c_double>() == 10.0);
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize {
+    continue_if!(ap.arg::<c_double>() == 1.0);
+    continue_if!(ap.arg::<c_int>() == 1);
+    continue_if!(ap.arg::<c_double>() == 2.0);
+    continue_if!(ap.arg::<c_int>() == 2);
+    continue_if!(ap.arg::<c_double>() == 3.0);
+    continue_if!(ap.arg::<c_int>() == 3);
+    continue_if!(ap.arg::<c_double>() == 4.0);
+    continue_if!(ap.arg::<c_int>() == 4);
+    continue_if!(ap.arg::<c_int>() == 5);
+    continue_if!(ap.arg::<c_double>() == 5.0);
+    continue_if!(ap.arg::<c_int>() == 6);
+    continue_if!(ap.arg::<c_double>() == 6.0);
+    continue_if!(ap.arg::<c_int>() == 7);
+    continue_if!(ap.arg::<c_double>() == 7.0);
+    continue_if!(ap.arg::<c_int>() == 8);
+    continue_if!(ap.arg::<c_double>() == 8.0);
+    continue_if!(ap.arg::<c_int>() == 9);
+    continue_if!(ap.arg::<c_double>() == 9.0);
+    continue_if!(ap.arg::<c_int>() == 10);
+    continue_if!(ap.arg::<c_double>() == 10.0);
+    0
+}
index 91b060dce26f436f6f9f5d21b7d038784dba115d..5bdb51680a6562ec25d03597146de4bdf4cbb417 100644 (file)
@@ -11,6 +11,9 @@ extern size_t check_list_copy_0(va_list ap);
 extern size_t check_varargs_0(int fixed, ...);
 extern size_t check_varargs_1(int fixed, ...);
 extern size_t check_varargs_2(int fixed, ...);
+extern size_t check_varargs_3(int fixed, ...);
+extern size_t check_varargs_4(double fixed, ...);
+extern size_t check_varargs_5(int fixed, ...);
 
 int test_rust(size_t (*fn)(va_list), ...) {
     size_t ret = 0;
@@ -36,5 +39,12 @@ int main(int argc, char* argv[]) {
 
     assert(check_varargs_2(0, "All", "of", "these", "are", "ignored", ".") == 0);
 
+    assert(check_varargs_3(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) == 0);
+
+    assert(check_varargs_4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0) == 0);
+
+    assert(check_varargs_5(0, 1.0, 1, 2.0, 2, 3.0, 3, 4.0, 4, 5, 5.0, 6, 6.0, 7, 7.0, 8, 8.0,
+                           9, 9.0, 10, 10.0) == 0);
+
     return 0;
 }
index bc21cfd47c5d1000e535e5db74ebf8e21d634039..894518faa31686f810052fad43a2f3790da9c8e0 100644 (file)
@@ -1,15 +1,15 @@
-error: `[v2]` cannot be resolved, ignoring it.
+error: unresolved link to `v2`
   --> $DIR/deny-intra-link-resolution-failure.rs:3:6
    |
 LL | /// [v2]
-   |      ^^ cannot be resolved, ignoring
+   |      ^^ unresolved link
    |
 note: the lint level is defined here
   --> $DIR/deny-intra-link-resolution-failure.rs:1:9
    |
 LL | #![deny(intra_doc_link_resolution_failure)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
 
index cf26675163054067e30c40a75bed45e2a9990e86..d2b2b90a4e50d69a7222f0e377c840ad8c302762 100644 (file)
@@ -1,15 +1,15 @@
-error: `[TypeAlias::hoge]` cannot be resolved, ignoring it.
+error: unresolved link to `TypeAlias::hoge`
   --> $DIR/intra-doc-alias-ice.rs:5:30
    |
 LL | /// [broken cross-reference](TypeAlias::hoge)
-   |                              ^^^^^^^^^^^^^^^ cannot be resolved, ignoring
+   |                              ^^^^^^^^^^^^^^^ unresolved link
    |
 note: the lint level is defined here
   --> $DIR/intra-doc-alias-ice.rs:1:9
    |
 LL | #![deny(intra_doc_link_resolution_failure)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
 
index 44997c90f59320465bbc7a6b063886aca329afe1..95388003f84704a79b8f01637e386c0430987eb4 100644 (file)
@@ -7,7 +7,7 @@
 /// ## For example:
 ///
 /// ï¼ˆarr[i])
-//~^ ERROR `[i]` cannot be resolved, ignoring it.
+//~^ ERROR `i`
 pub fn test_ice() {
     unimplemented!();
 }
index ce31eb3a8a3786cd2bf9712ac1c4c45d3f7dd6f6..156e214a79ff05258fb811d0bbb3d7f1d6bc2555 100644 (file)
@@ -1,15 +1,15 @@
-error: `[i]` cannot be resolved, ignoring it.
+error: unresolved link to `i`
   --> $DIR/intra-link-span-ice-55723.rs:9:10
    |
 LL | /// ï¼ˆarr[i])
-   |           ^ cannot be resolved, ignoring
+   |           ^ unresolved link
    |
 note: the lint level is defined here
   --> $DIR/intra-link-span-ice-55723.rs:1:9
    |
 LL | #![deny(intra_doc_link_resolution_failure)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: aborting due to previous error
 
index 7f8a8dd3c45e03e7a396cfbaad84e0dd060b4e9e..7e61bd725359a4c57422264bce630bc1244096d7 100644 (file)
@@ -23,23 +23,23 @@ pub enum Enum {
 /// Like [Foo#hola].
 ///
 /// Or maybe [Foo::f#hola].
-//~^ ERROR `[Foo::f#hola]` has an issue with the link anchor.
+//~^ ERROR `Foo::f#hola` contains an anchor
 pub fn foo() {}
 
 /// Empty.
 ///
 /// Another anchor error: [hello#people#!].
-//~^ ERROR `[hello#people#!]` has an issue with the link anchor.
+//~^ ERROR `hello#people#!` contains multiple anchors
 pub fn bar() {}
 
 /// Empty?
 ///
 /// Damn enum's variants: [Enum::A#whatever].
-//~^ ERROR `[Enum::A#whatever]` has an issue with the link anchor.
+//~^ ERROR `Enum::A#whatever` contains an anchor
 pub fn enum_link() {}
 
 /// Primitives?
 ///
 /// [u32#hello]
-//~^ ERROR `[u32#hello]` has an issue with the link anchor.
+//~^ ERROR `u32#hello` contains an anchor
 pub fn x() {}
index 11dee5547db4f541c8ecaea0637609ad985b8757..ef33d8f3e06fefbee4a4c1c0c3987ac6de8345e5 100644 (file)
@@ -1,8 +1,8 @@
-error: `[Foo::f#hola]` has an issue with the link anchor.
+error: `Foo::f#hola` contains an anchor, but links to struct fields are already anchored
   --> $DIR/intra-links-anchors.rs:25:15
    |
 LL | /// Or maybe [Foo::f#hola].
-   |               ^^^^^^^^^^^ struct fields cannot be followed by anchors
+   |               ^^^^^^^^^^^ contains invalid anchor
    |
 note: the lint level is defined here
   --> $DIR/intra-links-anchors.rs:1:9
@@ -10,23 +10,23 @@ note: the lint level is defined here
 LL | #![deny(intra_doc_link_resolution_failure)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `[hello#people#!]` has an issue with the link anchor.
+error: `hello#people#!` contains multiple anchors
   --> $DIR/intra-links-anchors.rs:31:28
    |
 LL | /// Another anchor error: [hello#people#!].
-   |                            ^^^^^^^^^^^^^^ only one `#` is allowed in a link
+   |                            ^^^^^^^^^^^^^^ contains invalid anchor
 
-error: `[Enum::A#whatever]` has an issue with the link anchor.
+error: `Enum::A#whatever` contains an anchor, but links to enum variants are already anchored
   --> $DIR/intra-links-anchors.rs:37:28
    |
 LL | /// Damn enum's variants: [Enum::A#whatever].
-   |                            ^^^^^^^^^^^^^^^^ variants cannot be followed by anchors
+   |                            ^^^^^^^^^^^^^^^^ contains invalid anchor
 
-error: `[u32#hello]` has an issue with the link anchor.
+error: `u32#hello` contains an anchor, but links to primitive types are already anchored
   --> $DIR/intra-links-anchors.rs:43:6
    |
 LL | /// [u32#hello]
-   |      ^^^^^^^^^ primitive types cannot be followed by anchors
+   |      ^^^^^^^^^ contains invalid anchor
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/rustdoc-ui/intra-links-private.private.stderr b/src/test/rustdoc-ui/intra-links-private.private.stderr
new file mode 100644 (file)
index 0000000..a2148b8
--- /dev/null
@@ -0,0 +1,11 @@
+warning: public documentation for `DocMe` links to private item `DontDocMe`
+  --> $DIR/intra-links-private.rs:5:11
+   |
+LL | /// docs [DontDocMe]
+   |           ^^^^^^^^^ this item is private
+   |
+   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: this link resolves only because you passed `--document-private-items`, but will break without
+
+warning: 1 warning emitted
+
index 0a8dafdaf94667ef591fcc5f9ad5f8fd00c28cb3..56742406992fcc63138c147074c0d176f207b8b8 100644 (file)
@@ -1,10 +1,11 @@
-warning: `[DontDocMe]` public documentation for `DocMe` links to a private item
-  --> $DIR/intra-links-private.rs:6:11
+warning: public documentation for `DocMe` links to private item `DontDocMe`
+  --> $DIR/intra-links-private.rs:5:11
    |
 LL | /// docs [DontDocMe]
    |           ^^^^^^^^^ this item is private
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: this link will resolve properly if you pass `--document-private-items`
 
 warning: 1 warning emitted
 
index 86cf9fed3dab48cb176a2009969632bc26c7a647..613236d75d2ee952e847f7ac23590a95509bfccd 100644 (file)
@@ -1,10 +1,9 @@
 // check-pass
 // revisions: public private
 // [private]compile-flags: --document-private-items
-#![cfg_attr(private, deny(intra_doc_link_resolution_failure))]
 
 /// docs [DontDocMe]
-//[public]~^ WARNING `[DontDocMe]` public documentation for `DocMe` links to a private item
+//~^ WARNING public documentation for `DocMe` links to private item `DontDocMe`
 // FIXME: for [private] we should also make sure the link was actually generated
 pub struct DocMe;
 struct DontDocMe;
index 18c9837b0bb457e449312e21e811e12cec6b5b97..a19c33b53be09673b8f24197a2ab001812800f13 100644 (file)
@@ -6,16 +6,16 @@
 
 /// [error]
 pub struct A;
-//~^^ WARNING `[error]` cannot be resolved
+//~^^ WARNING `error`
 
 ///
 /// docs [error1]
-//~^ WARNING `[error1]` cannot be resolved
+//~^ WARNING `error1`
 
 /// docs [error2]
 ///
 pub struct B;
-//~^^^ WARNING `[error2]` cannot be resolved
+//~^^^ WARNING `error2`
 
 /**
  * This is a multi-line comment.
@@ -23,4 +23,4 @@
  * It also has an [error].
  */
 pub struct C;
-//~^^^ WARNING `[error]` cannot be resolved
+//~^^^ WARNING `error`
index ac8691a8743ba7dbffe9e984e029f1b07c183f41..bc31264c170eaf3bed48c3bd07eda0fdd4d891f5 100644 (file)
@@ -1,35 +1,35 @@
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning-crlf.rs:7:6
    |
 LL | /// [error]
-   |      ^^^^^ cannot be resolved, ignoring
+   |      ^^^^^ unresolved link
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error1]` cannot be resolved, ignoring it.
+warning: unresolved link to `error1`
   --> $DIR/intra-links-warning-crlf.rs:12:11
    |
 LL | /// docs [error1]
-   |           ^^^^^^ cannot be resolved, ignoring
+   |           ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error2]` cannot be resolved, ignoring it.
+warning: unresolved link to `error2`
   --> $DIR/intra-links-warning-crlf.rs:15:11
    |
 LL | /// docs [error2]
-   |           ^^^^^^ cannot be resolved, ignoring
+   |           ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning-crlf.rs:23:20
    |
 LL |  * It also has an [error].
-   |                    ^^^^^ cannot be resolved, ignoring
+   |                    ^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 warning: 4 warnings emitted
 
index 623dcc320bb8dcd83a06b860640f4fb3dbba7733..eab1f03480460b2d05d9c722a44aaa41085805bc 100644 (file)
@@ -1,37 +1,37 @@
 // check-pass
 
        //! Test with [Foo::baz], [Bar::foo], ...
-//~^ WARNING `[Foo::baz]` cannot be resolved
-//~| WARNING `[Bar::foo]` cannot be resolved
+//~^ WARNING `Foo::baz`
+//~| WARNING `Bar::foo`
      //! , [Uniooon::X] and [Qux::Z].
-//~^ WARNING `[Uniooon::X]` cannot be resolved
-//~| WARNING `[Qux::Z]` cannot be resolved
+//~^ WARNING `Uniooon::X`
+//~| WARNING `Qux::Z`
        //!
       //! , [Uniooon::X] and [Qux::Z].
-//~^ WARNING `[Uniooon::X]` cannot be resolved
-//~| WARNING `[Qux::Z]` cannot be resolved
+//~^ WARNING `Uniooon::X`
+//~| WARNING `Qux::Z`
 
        /// [Qux:Y]
-//~^ WARNING `[Qux:Y]` cannot be resolved
+//~^ WARNING `Qux:Y`
 pub struct Foo {
     pub bar: usize,
 }
 
 /// Foo
-/// bar [BarA] bar //~ WARNING `[BarA]` cannot be resolved
+/// bar [BarA] bar //~ WARNING `BarA`
 /// baz
 pub fn a() {}
 
 /**
  * Foo
- * bar [BarB] bar //~ WARNING `[BarB]` cannot be resolved
+ * bar [BarB] bar //~ WARNING `BarB`
  * baz
  */
 pub fn b() {}
 
 /** Foo
 
-bar [BarC] bar //~ WARNING `[BarC]` cannot be resolved
+bar [BarC] bar //~ WARNING `BarC`
 baz
 
     let bar_c_1 = 0;
@@ -42,12 +42,12 @@ pub fn b() {}
 */
 pub fn c() {}
 
-#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `[BarD]` cannot be resolved
+#[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `BarD`
 pub fn d() {}
 
 macro_rules! f {
     ($f:expr) => {
-        #[doc = $f] //~ WARNING `[BarF]` cannot be resolved
+        #[doc = $f] //~ WARNING `BarF`
         pub fn f() {}
     }
 }
@@ -55,30 +55,30 @@ pub fn f() {}
 
 /** # for example,
  *
- * time to introduce a link [error]*/ //~ WARNING `[error]` cannot be resolved
+ * time to introduce a link [error]*/ //~ WARNING `error`
 pub struct A;
 
 /**
  * # for example,
  *
- * time to introduce a link [error] //~ WARNING `[error]` cannot be resolved
+ * time to introduce a link [error] //~ WARNING `error`
  */
 pub struct B;
 
-#[doc = "single line [error]"] //~ WARNING `[error]` cannot be resolved
+#[doc = "single line [error]"] //~ WARNING `error`
 pub struct C;
 
-#[doc = "single line with \"escaping\" [error]"] //~ WARNING `[error]` cannot be resolved
+#[doc = "single line with \"escaping\" [error]"] //~ WARNING `error`
 pub struct D;
 
-/// Item docs. //~ WARNING `[error]` cannot be resolved
+/// Item docs. //~ WARNING `error`
 #[doc="Hello there!"]
 /// [error]
 pub struct E;
 
 ///
-/// docs [error1] //~ WARNING `[error1]` cannot be resolved
+/// docs [error1] //~ WARNING `error1`
 
-/// docs [error2] //~ WARNING `[error2]` cannot be resolved
+/// docs [error2] //~ WARNING `error2`
 ///
 pub struct F;
index 914a19fc536c7f185e6f9126f4b09fe11e1b4ef8..81931399c240a87f29cfa8a5b7aaf658be4c95f9 100644 (file)
@@ -1,77 +1,77 @@
-warning: `[Foo::baz]` cannot be resolved, ignoring it.
+warning: unresolved link to `Foo::baz`
   --> $DIR/intra-links-warning.rs:3:23
    |
 LL |        //! Test with [Foo::baz], [Bar::foo], ...
-   |                       ^^^^^^^^ cannot be resolved, ignoring
+   |                       ^^^^^^^^ unresolved link
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Bar::foo]` cannot be resolved, ignoring it.
+warning: unresolved link to `Bar::foo`
   --> $DIR/intra-links-warning.rs:3:35
    |
 LL |        //! Test with [Foo::baz], [Bar::foo], ...
-   |                                   ^^^^^^^^ cannot be resolved, ignoring
+   |                                   ^^^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Uniooon::X]` cannot be resolved, ignoring it.
+warning: unresolved link to `Uniooon::X`
   --> $DIR/intra-links-warning.rs:6:13
    |
 LL |      //! , [Uniooon::X] and [Qux::Z].
-   |             ^^^^^^^^^^ cannot be resolved, ignoring
+   |             ^^^^^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Qux::Z]` cannot be resolved, ignoring it.
+warning: unresolved link to `Qux::Z`
   --> $DIR/intra-links-warning.rs:6:30
    |
 LL |      //! , [Uniooon::X] and [Qux::Z].
-   |                              ^^^^^^ cannot be resolved, ignoring
+   |                              ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Uniooon::X]` cannot be resolved, ignoring it.
+warning: unresolved link to `Uniooon::X`
   --> $DIR/intra-links-warning.rs:10:14
    |
 LL |       //! , [Uniooon::X] and [Qux::Z].
-   |              ^^^^^^^^^^ cannot be resolved, ignoring
+   |              ^^^^^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Qux::Z]` cannot be resolved, ignoring it.
+warning: unresolved link to `Qux::Z`
   --> $DIR/intra-links-warning.rs:10:31
    |
 LL |       //! , [Uniooon::X] and [Qux::Z].
-   |                               ^^^^^^ cannot be resolved, ignoring
+   |                               ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[Qux:Y]` cannot be resolved, ignoring it.
+warning: unresolved link to `Qux:Y`
   --> $DIR/intra-links-warning.rs:14:13
    |
 LL |        /// [Qux:Y]
-   |             ^^^^^ cannot be resolved, ignoring
+   |             ^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:58:30
    |
 LL |  * time to introduce a link [error]*/
-   |                              ^^^^^ cannot be resolved, ignoring
+   |                              ^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:64:30
    |
 LL |  * time to introduce a link [error]
-   |                              ^^^^^ cannot be resolved, ignoring
+   |                              ^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:68:1
    |
 LL | #[doc = "single line [error]"]
@@ -81,9 +81,9 @@ LL | #[doc = "single line [error]"]
            
            single line [error]
                         ^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:71:1
    |
 LL | #[doc = "single line with \"escaping\" [error]"]
@@ -93,9 +93,9 @@ LL | #[doc = "single line with \"escaping\" [error]"]
            
            single line with "escaping" [error]
                                         ^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error]` cannot be resolved, ignoring it.
+warning: unresolved link to `error`
   --> $DIR/intra-links-warning.rs:74:1
    |
 LL | / /// Item docs.
@@ -107,49 +107,49 @@ LL | | /// [error]
            
            [error]
             ^^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error1]` cannot be resolved, ignoring it.
+warning: unresolved link to `error1`
   --> $DIR/intra-links-warning.rs:80:11
    |
 LL | /// docs [error1]
-   |           ^^^^^^ cannot be resolved, ignoring
+   |           ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[error2]` cannot be resolved, ignoring it.
+warning: unresolved link to `error2`
   --> $DIR/intra-links-warning.rs:82:11
    |
 LL | /// docs [error2]
-   |           ^^^^^^ cannot be resolved, ignoring
+   |           ^^^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[BarA]` cannot be resolved, ignoring it.
+warning: unresolved link to `BarA`
   --> $DIR/intra-links-warning.rs:21:10
    |
 LL | /// bar [BarA] bar
-   |          ^^^^ cannot be resolved, ignoring
+   |          ^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[BarB]` cannot be resolved, ignoring it.
+warning: unresolved link to `BarB`
   --> $DIR/intra-links-warning.rs:27:9
    |
 LL |  * bar [BarB] bar
-   |         ^^^^ cannot be resolved, ignoring
+   |         ^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[BarC]` cannot be resolved, ignoring it.
+warning: unresolved link to `BarC`
   --> $DIR/intra-links-warning.rs:34:6
    |
 LL | bar [BarC] bar
-   |      ^^^^ cannot be resolved, ignoring
+   |      ^^^^ unresolved link
    |
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[BarD]` cannot be resolved, ignoring it.
+warning: unresolved link to `BarD`
   --> $DIR/intra-links-warning.rs:45:1
    |
 LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
@@ -159,9 +159,9 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
            
            bar [BarD] bar
                 ^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
-warning: `[BarF]` cannot be resolved, ignoring it.
+warning: unresolved link to `BarF`
   --> $DIR/intra-links-warning.rs:50:9
    |
 LL |         #[doc = $f]
@@ -174,7 +174,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz");
            
            bar [BarF] bar
                 ^^^^
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
    = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 warning: 19 warnings emitted
diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr
new file mode 100644 (file)
index 0000000..9c5cdf0
--- /dev/null
@@ -0,0 +1,11 @@
+warning: public documentation for `public_item` links to private item `PrivateType`
+  --> $DIR/issue-74134.rs:19:10
+   |
+LL |     /// [`PrivateType`]
+   |          ^^^^^^^^^^^^^ this item is private
+   |
+   = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: this link resolves only because you passed `--document-private-items`, but will break without
+
+warning: 1 warning emitted
+
index 03f95f19d326e7b531896f9e2fa56e59de9f6343..ff2951d864e642e6dd57f13068f1bfec40f50e67 100644 (file)
@@ -1,10 +1,11 @@
-warning: `[PrivateType]` public documentation for `public_item` links to a private item
+warning: public documentation for `public_item` links to private item `PrivateType`
   --> $DIR/issue-74134.rs:19:10
    |
 LL |     /// [`PrivateType`]
    |          ^^^^^^^^^^^^^ this item is private
    |
    = note: `#[warn(intra_doc_link_resolution_failure)]` on by default
+   = note: this link will resolve properly if you pass `--document-private-items`
 
 warning: 1 warning emitted
 
index d561c2dd8901502736ab1001b06b3f671b65724f..b1be9123aaf838cf4750c84dc06fb23d1f01b5cd 100644 (file)
@@ -4,7 +4,7 @@
 
 // There are 4 cases here:
 // 1. public item  -> public type:  no warning
-// 2. public item  -> private type: warning, if --document-private-items is not passed
+// 2. public item  -> private type: warning
 // 3. private item -> public type:  no warning
 // 4. private item -> private type: no warning
 // All 4 cases are tested with and without --document-private-items.
@@ -17,7 +17,7 @@
 pub struct Public {
     /// [`PublicType`]
     /// [`PrivateType`]
-    //[public]~^ WARNING public documentation for `public_item` links to a private
+    //~^ WARNING public documentation for `public_item` links to private item `PrivateType`
     pub public_item: u32,
 
     /// [`PublicType`]
index 06766db5335a1eeb4d3c2ec7da0f1db03cac6e7f..e58c8b12f68cb8550ef9bd0c43bbe40f54554175 100644 (file)
@@ -11,7 +11,7 @@
 /// ```
 /// println!("sup");
 /// ```
-pub fn link_error() {} //~^^^^^ ERROR cannot be resolved, ignoring it
+pub fn link_error() {} //~^^^^^ ERROR unresolved link to `error`
 
 /// wait, this doesn't have a doctest?
 pub fn no_doctest() {} //~^ ERROR missing code example in this documentation
index 852c9120e0bf9ca141b9e7cbdca9369a74020965..14d72e9aad3ba8cfaa9a21db2ab5dd41fccc9569 100644 (file)
@@ -15,11 +15,11 @@ LL | #![deny(rustdoc)]
    |         ^^^^^^^
    = note: `#[deny(private_doc_tests)]` implied by `#[deny(rustdoc)]`
 
-error: `[error]` cannot be resolved, ignoring it.
+error: unresolved link to `error`
   --> $DIR/lint-group.rs:9:29
    |
 LL | /// what up, let's make an [error]
-   |                             ^^^^^ cannot be resolved, ignoring
+   |                             ^^^^^ unresolved link
    |
 note: the lint level is defined here
   --> $DIR/lint-group.rs:7:9
@@ -27,7 +27,7 @@ note: the lint level is defined here
 LL | #![deny(rustdoc)]
    |         ^^^^^^^
    = note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]`
-   = help: to escape `[` and `]` characters, just add '\' before them like `\[` or `\]`
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
 
 error: missing code example in this documentation
   --> $DIR/lint-group.rs:16:1
diff --git a/src/test/rustdoc/auxiliary/unstable-trait.rs b/src/test/rustdoc/auxiliary/unstable-trait.rs
new file mode 100644 (file)
index 0000000..6f06a6e
--- /dev/null
@@ -0,0 +1,26 @@
+#![feature(staged_api)]
+#![stable(feature = "private_general", since = "1.0.0")]
+
+#[unstable(feature = "private_trait", issue = "none")]
+pub trait Bar {}
+
+#[stable(feature = "private_general", since = "1.0.0")]
+pub struct Foo {
+    // nothing
+}
+
+impl Foo {
+    #[stable(feature = "private_general", since = "1.0.0")]
+    pub fn stable_impl() {}
+}
+
+impl Foo {
+    #[unstable(feature = "private_trait", issue = "none")]
+    pub fn bar() {}
+
+    #[stable(feature = "private_general", since = "1.0.0")]
+    pub fn bar2() {}
+}
+
+#[stable(feature = "private_general", since = "1.0.0")]
+impl Bar for Foo {}
diff --git a/src/test/rustdoc/hide-unstable-trait.rs b/src/test/rustdoc/hide-unstable-trait.rs
new file mode 100644 (file)
index 0000000..c30d6ed
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:unstable-trait.rs
+
+#![crate_name = "foo"]
+#![feature(private_trait)]
+
+extern crate unstable_trait;
+
+// @has foo/struct.Foo.html 'bar'
+// @has foo/struct.Foo.html 'bar2'
+#[doc(inline)]
+pub use unstable_trait::Foo;
diff --git a/src/test/ui/associated-type-bounds/issue-73818.rs b/src/test/ui/associated-type-bounds/issue-73818.rs
new file mode 100644 (file)
index 0000000..bb890f7
--- /dev/null
@@ -0,0 +1,25 @@
+// Test that associated type bounds are correctly normalized when checking
+// default associated type values.
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(specialization)]
+
+#[derive(PartialEq)]
+enum Never {}
+trait Foo {
+    type Assoc: PartialEq; // PartialEq<<Self as Foo>::Assoc>
+}
+impl<T> Foo for T {
+    default type Assoc = Never;
+}
+
+trait Trait1 {
+    type Selection: PartialEq;
+}
+trait Trait2: PartialEq<Self> {}
+impl<T: Trait2> Trait1 for T {
+    default type Selection = T;
+}
+
+fn main() {}
index 8c6073e2f7a4918bd468ebad139420b4a70487f3..1eeb01ccc846e9d82691725254e58eac7f0830e4 100644 (file)
@@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
 
 #[cfg(transmute)] // one instantiations: BAD
 fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
-   bar(foo, x) //[transmute]~ ERROR E0495
+   bar(foo, x) //[transmute]~ ERROR E0759
 }
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
index 5ea98dcd4a972a194e603ec6067d98dfb659b873..0be9b37263a48bbea3847ef93b55c4fa4b636950 100644 (file)
@@ -1,26 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/project-fn-ret-contravariant.rs:38:8
    |
-LL |    bar(foo, x)
-   |        ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
-  --> $DIR/project-fn-ret-contravariant.rs:37:8
-   |
 LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
-   |        ^^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/project-fn-ret-contravariant.rs:38:13
-   |
-LL |    bar(foo, x)
-   |             ^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/project-fn-ret-contravariant.rs:38:4
-   |
+   |                  ------- this data with lifetime `'a`...
 LL |    bar(foo, x)
-   |    ^^^^^^^^^^^
+   |    ----^^^---- ...is captured and required to live as long as `'static` here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
index 0034d796826de662b16e8aec226e8e3bfcaf8ada..08d864f7836d20467ad4292d937f2809f154b089 100644 (file)
@@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
     // Cannot instantiate `foo` with any lifetime other than `'a`,
     // since it is provided as input.
 
-    bar(foo, x) //[transmute]~ ERROR E0495
+    bar(foo, x) //[transmute]~ ERROR E0759
 }
 
 #[cfg(krisskross)] // two instantiations, mixing and matching: BAD
index ef57f9e0bc480049ba6ed9bfab821693693f1e1f..0a44864b249551b3a03d6f5f792e7f49c00c13ab 100644 (file)
@@ -1,30 +1,12 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/project-fn-ret-invariant.rs:49:9
    |
-LL |     bar(foo, x)
-   |         ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 45:8...
-  --> $DIR/project-fn-ret-invariant.rs:45:8
-   |
 LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
-   |        ^^
-note: ...so that the expression is assignable
-  --> $DIR/project-fn-ret-invariant.rs:49:14
-   |
-LL |     bar(foo, x)
-   |              ^
-   = note: expected `Type<'_>`
-              found `Type<'a>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/project-fn-ret-invariant.rs:49:5
-   |
+   |                   -------- this data with lifetime `'a`...
+...
 LL |     bar(foo, x)
-   |     ^^^^^^^^^^^
-   = note: expected `Type<'static>`
-              found `Type<'_>`
+   |     ----^^^---- ...is captured and required to live as long as `'static` here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/associated-types/issue-62200.rs b/src/test/ui/associated-types/issue-62200.rs
new file mode 100644 (file)
index 0000000..9d18690
--- /dev/null
@@ -0,0 +1,15 @@
+struct S {}
+
+trait T<'a> {
+    type A;
+}
+
+impl T<'_> for S {
+    type A = u32;
+}
+
+fn foo(x: impl Fn(<S as T<'_>>::A) -> <S as T<'_>>::A) {}
+//~^ ERROR binding for associated type `Output` references an anonymous lifetime
+//~^^ NOTE lifetimes appearing in an associated type are not considered constrained
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-62200.stderr b/src/test/ui/associated-types/issue-62200.stderr
new file mode 100644 (file)
index 0000000..f14cd81
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types
+  --> $DIR/issue-62200.rs:11:39
+   |
+LL | fn foo(x: impl Fn(<S as T<'_>>::A) -> <S as T<'_>>::A) {}
+   |                                       ^^^^^^^^^^^^^^^
+   |
+   = note: lifetimes appearing in an associated type are not considered constrained
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0582`.
index ea482d3667e2b575bc5c8fb9ef9b8d76db8c296a..66ebbd83ffa9e4546a0fcfd06b437a658b245dc1 100644 (file)
@@ -9,7 +9,7 @@ async fn foo<F>(fun: F)
 struct Struct;
 
 impl Struct {
-    pub async fn run_dummy_fn(&self) { //~ ERROR cannot infer
+    pub async fn run_dummy_fn(&self) { //~ ERROR E0759
         foo(|| self.bar()).await;
     }
 
index 0f58b158904db0a2fb3aa8fdb2e5c935c07e2707..56a28d904b91d57f29f79c8f6dba321a250422a5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
index 21368fad3b05848a47ae08cfaa1c02f3e006e264..3c4f9a1f5ee2c3c0a433022517176f4abc0b7c56 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-// compile-flags: -Z control-flow-guard
+// compile-flags: -C control-flow-guard
 
 pub fn main() {
     println!("hello, world");
index ae4f4d69b5ef500c3214be894915bb1a7b7baf96..687dd97ca6cefc438a6fc33af03dec17016cf954 100644 (file)
@@ -5,7 +5,7 @@ LL |     let y = x.or_else(4);
    |                       ^ expected an `FnOnce<()>` closure, found `{integer}`
    |
    = help: the trait `std::ops::FnOnce<()>` is not implemented for `{integer}`
-   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
 
 error: aborting due to previous error
 
index 85ed360a1f74a2d3de1a3f471e2d38900e42200c..cd18a013628c2875808e91a000bbe0e2865954b8 100644 (file)
@@ -1,12 +1,12 @@
 error[E0038]: the trait `NotObjectSafe` cannot be made into an object
-  --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:6
+  --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:24
    |
 LL | trait NotObjectSafe { fn eq(&self, other: Self); }
    |       -------------                       ---- ...because method `eq` references the `Self` type in this parameter
    |       |
    |       this trait cannot be made into an object...
 LL | impl NotObjectSafe for dyn NotObjectSafe { }
-   |      ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+   |                        ^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
    |
    = help: consider moving `eq` to another trait
 
index 6110d16c070d9016ef0faf6f4fcf39bd43f869c2..1d1adf39434712bd879cdfbe5f3c40dc9c66e029 100644 (file)
@@ -6,4 +6,14 @@ struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior
     another: T,
 }
 
-fn main() { }
+struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
+    //~^ ERROR type parameters must be declared prior
+    //~| ERROR lifetime parameters must be declared prior
+    a: &'a T,
+    b: &'b U,
+}
+
+fn main() {
+    let _: AlsoBad<7, 'static, u32, 'static, 17, u16>;
+    //~^ ERROR lifetime provided when a type was expected
+ }
index f77ae49cf10b17cc66d3466ba8e58a4ef27980c5..19e895b8eb886d2621f31b9dd1a66bee24ecd245 100644 (file)
@@ -4,6 +4,18 @@ error: type parameters must be declared prior to const parameters
 LL | struct Bad<const N: usize, T> {
    |           -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
 
+error: lifetime parameters must be declared prior to const parameters
+  --> $DIR/argument_order.rs:9:32
+   |
+LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
+   |               -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>`
+
+error: type parameters must be declared prior to const parameters
+  --> $DIR/argument_order.rs:9:36
+   |
+LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
+   |               ---------------------^----------------------^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>`
+
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/argument_order.rs:1:12
    |
@@ -13,5 +25,15 @@ 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
+error[E0747]: lifetime provided when a type was expected
+  --> $DIR/argument_order.rs:17:23
+   |
+LL |     let _: AlsoBad<7, 'static, u32, 'static, 17, u16>;
+   |                       ^^^^^^^
+   |
+   = note: lifetime arguments must be provided before type arguments
+   = help: reorder the arguments: lifetimes, then types, then consts: `<'a, 'b, T, U, N, M>`
+
+error: aborting due to 4 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-33.rs
new file mode 100644 (file)
index 0000000..35df327
--- /dev/null
@@ -0,0 +1,40 @@
+// check-pass
+
+pub fn yes_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+pub fn yes_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+where
+    A: PartialEq<B>,
+{
+    Vec::<A>::new()
+}
+
+use std::collections::VecDeque;
+
+pub fn yes_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn yes_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+pub fn yes_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
+where
+    A: PartialEq<B>,
+{
+    VecDeque::<A>::new()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.rs
deleted file mode 100644 (file)
index 19107e6..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
-where
-    A: PartialEq<B>,
-{
-    Vec::<A>::new()
-}
-
-pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
-where
-    A: PartialEq<B>,
-{
-    Vec::<A>::new()
-}
-
-use std::collections::VecDeque;
-
-pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
-where
-    A: PartialEq<B>,
-{
-    VecDeque::<A>::new()
-}
-
-pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
-where
-    A: PartialEq<B>,
-{
-    VecDeque::<A>::new()
-}
-
-pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
-where
-    A: PartialEq<B>,
-{
-    VecDeque::<A>::new()
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
deleted file mode 100644 (file)
index 6e5afcd..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-traits-no-impls-length-33.rs:1:43
-   |
-LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
-...
-LL |     Vec::<A>::new()
-   |     --------------- this returned value is of type `std::vec::Vec<A>`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-traits-no-impls-length-33.rs:9:51
-   |
-LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
-   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
-...
-LL |     Vec::<A>::new()
-   |     --------------- this returned value is of type `std::vec::Vec<A>`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-traits-no-impls-length-33.rs:19:48
-   |
-LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
-   |                                                ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
-...
-LL |     VecDeque::<A>::new()
-   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-traits-no-impls-length-33.rs:27:56
-   |
-LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
-   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
-...
-LL |     VecDeque::<A>::new()
-   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-traits-no-impls-length-33.rs:35:60
-   |
-LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
-   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
-...
-LL |     VecDeque::<A>::new()
-   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
-   = note: the return type of a function must have a statically known size
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/array-impls/alloc-types-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-types-impls-length-33.rs
new file mode 100644 (file)
index 0000000..294b405
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+use std::{convert::TryFrom, rc::Rc, sync::Arc};
+
+pub fn yes_vec() {
+    let v: Vec<_> = [0; 33].into();
+}
+
+pub fn yes_box() {
+    let boxed_slice = Box::new([0; 33]) as Box<[i32]>;
+    let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
+    let boxed_slice = <Box<[i32]>>::from([0; 33]);
+}
+
+pub fn yes_rc() {
+    let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>;
+    let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
+}
+
+pub fn yes_arc() {
+    let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>;
+    let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs
deleted file mode 100644 (file)
index 48cf21d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// ignore-tidy-linelength
-
-use std::{convert::TryFrom, rc::Rc, sync::Arc};
-
-pub fn no_vec() {
-    let v: Vec<_> = [0; 33].into();
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_box() {
-    let boxed_slice = Box::new([0; 33]) as Box<[i32]>;
-    let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
-    //~^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
-    //~^^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
-    let boxed_slice = <Box<[i32]>>::from([0; 33]);
-    //~^ 15:42: 15:49: arrays only have std trait implementations for lengths 0..=32 [E0277]
-}
-
-pub fn no_rc() {
-    let boxed_slice = Rc::new([0; 33]) as Rc<[i32]>;
-    let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
-    //~^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
-    //~^^ ERROR the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
-}
-
-pub fn no_arc() {
-    let boxed_slice = Arc::new([0; 33]) as Arc<[i32]>;
-    let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
-    //~^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
-    //~^^ ERROR the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr
deleted file mode 100644 (file)
index 5c01603..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-types-no-impls-length-33.rs:6:29
-   |
-LL |     let v: Vec<_> = [0; 33].into();
-   |                             ^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[{integer}; 33]`
-   |
-   = note: required because of the requirements on the impl of `std::convert::From<[{integer}; 33]>` for `std::vec::Vec<{integer}>`
-   = note: required because of the requirements on the impl of `std::convert::Into<std::vec::Vec<{integer}>>` for `[{integer}; 33]`
-
-error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:12:23
-   |
-LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::boxed::Box<(dyn std::error::Error + 'a)> as std::convert::From<E>>
-             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<&str>>
-             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::borrow::Cow<'a, str>>>
-             <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::string::String>>
-           and 22 others
-   = note: required because of the requirements on the impl of `std::convert::Into<std::boxed::Box<[i32; 33]>>` for `std::boxed::Box<[i32]>`
-   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::boxed::Box<[i32]>>` for `std::boxed::Box<[i32; 33]>`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/alloc-types-no-impls-length-33.rs:15:42
-   |
-LL |     let boxed_slice = <Box<[i32]>>::from([0; 33]);
-   |                                          ^^^^^^^
-   |                                          |
-   |                                          expected an implementor of trait `std::convert::From<[{integer}; 33]>`
-   |                                          help: consider borrowing here: `&[0; 33]`
-   |
-   = note: the trait bound `[i32; 33]: std::convert::From<[{integer}; 33]>` is not satisfied
-   = note: required because of the requirements on the impl of `std::convert::From<[i32; 33]>` for `std::boxed::Box<[i32]>`
-   = note: required by `std::convert::From::from`
-
-error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:12:23
-   |
-LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::boxed::Box<[i32]>>` is not implemented for `std::boxed::Box<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::boxed::Box<[T; N]> as std::convert::TryFrom<std::boxed::Box<[T]>>>
-
-error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
-   |
-LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::rc::Rc<B> as std::convert::From<std::borrow::Cow<'a, B>>>
-             <std::rc::Rc<T> as std::convert::From<T>>
-             <std::rc::Rc<T> as std::convert::From<std::boxed::Box<T>>>
-             <std::rc::Rc<[T]> as std::convert::From<&[T]>>
-           and 9 others
-   = note: required because of the requirements on the impl of `std::convert::Into<std::rc::Rc<[i32; 33]>>` for `std::rc::Rc<[i32]>`
-   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::rc::Rc<[i32]>>` for `std::rc::Rc<[i32; 33]>`
-
-error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
-   |
-LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::rc::Rc<[T; N]> as std::convert::TryFrom<std::rc::Rc<[T]>>>
-
-error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:28:23
-   |
-LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::sync::Arc<B> as std::convert::From<std::borrow::Cow<'a, B>>>
-             <std::sync::Arc<T> as std::convert::From<T>>
-             <std::sync::Arc<T> as std::convert::From<std::boxed::Box<T>>>
-             <std::sync::Arc<[T]> as std::convert::From<&[T]>>
-           and 9 others
-   = note: required because of the requirements on the impl of `std::convert::Into<std::sync::Arc<[i32; 33]>>` for `std::sync::Arc<[i32]>`
-   = note: required because of the requirements on the impl of `std::convert::TryFrom<std::sync::Arc<[i32]>>` for `std::sync::Arc<[i32; 33]>`
-
-error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:28:23
-   |
-LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
-   |
-   = help: the following implementations were found:
-             <std::sync::Arc<[T; N]> as std::convert::TryFrom<std::sync::Arc<[T]>>>
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/array-impls/core-traits-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-impls-length-33.rs
new file mode 100644 (file)
index 0000000..c609a7c
--- /dev/null
@@ -0,0 +1,66 @@
+// check-pass
+
+pub fn yes_as_ref() -> impl AsRef<[u8]> {
+    [0; 33]
+}
+
+pub fn yes_as_mut() -> impl AsMut<[u8]> {
+    [0; 33]
+}
+
+pub fn yes_borrow() -> impl std::borrow::Borrow<[u8]> {
+    [0; 33]
+}
+
+pub fn yes_borrow_mut() -> impl std::borrow::BorrowMut<[u8]> {
+    [0; 33]
+}
+
+pub fn yes_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> {
+    [0; 33]
+}
+
+pub fn yes_ref_try_from_slice() -> impl std::convert::TryFrom<&'static [u8]> {
+    let a: &'static _ = &[0; 33];
+    a
+}
+
+pub fn yes_hash() -> impl std::hash::Hash {
+    [0; 33]
+}
+
+pub fn yes_debug() -> impl std::fmt::Debug {
+    [0; 33]
+}
+
+pub fn yes_ref_into_iterator() -> impl IntoIterator<Item=&'static u8> {
+    let a: &'static _ = &[0; 33];
+    a
+}
+
+pub fn yes_partial_eq() -> impl PartialEq<[u8; 33]> {
+    [0; 33]
+}
+
+pub fn yes_partial_eq_slice() -> impl PartialEq<[u8]> {
+    [0; 33]
+}
+
+pub fn yes_slice_partial_eq() -> impl PartialEq<[u8; 33]> {
+    let a: &'static _ = &[0; 33];
+    &a[..]
+}
+
+pub fn yes_eq() -> impl Eq {
+    [0; 33]
+}
+
+pub fn yes_partial_ord() -> impl PartialOrd<[u8; 33]> {
+    [0; 33]
+}
+
+pub fn yes_ord() -> impl Ord {
+    [0; 33]
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.rs
deleted file mode 100644 (file)
index 8397d20..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-pub fn no_debug() {
-    println!("{:?}", [0_usize; 33]);
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_hash() {
-    use std::collections::HashSet;
-    let mut set = HashSet::new();
-    set.insert([0_usize; 33]);
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_partial_eq() -> bool {
-    [0_usize; 33] == [1_usize; 33]
-    //~^ ERROR binary operation `==` cannot be applied to type `[usize; 33]`
-}
-
-pub fn no_partial_ord() -> bool {
-    [0_usize; 33] < [1_usize; 33]
-    //~^ ERROR binary operation `<` cannot be applied to type `[usize; 33]`
-}
-
-pub fn no_into_iterator() {
-    for _ in &[0_usize; 33] {
-        //~^ ERROR the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr
deleted file mode 100644 (file)
index 76ccc48..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/core-traits-no-impls-length-33.rs:2:22
-   |
-LL |     println!("{:?}", [0_usize; 33]);
-   |                      ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
-   |
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `[usize; 33]`
-   = note: required by `std::fmt::Debug::fmt`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/core-traits-no-impls-length-33.rs:9:16
-   |
-LL |     set.insert([0_usize; 33]);
-   |                ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
-   |
-   = note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
-
-error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
-  --> $DIR/core-traits-no-impls-length-33.rs:14:19
-   |
-LL |     [0_usize; 33] == [1_usize; 33]
-   |     ------------- ^^ ------------- [usize; 33]
-   |     |
-   |     [usize; 33]
-
-error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
-  --> $DIR/core-traits-no-impls-length-33.rs:19:19
-   |
-LL |     [0_usize; 33] < [1_usize; 33]
-   |     ------------- ^ ------------- [usize; 33]
-   |     |
-   |     [usize; 33]
-
-error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
-  --> $DIR/core-traits-no-impls-length-33.rs:24:14
-   |
-LL |     for _ in &[0_usize; 33] {
-   |              ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
-   |
-   = help: the following implementations were found:
-             <&'a [T; N] as std::iter::IntoIterator>
-             <&'a [T] as std::iter::IntoIterator>
-             <&'a mut [T; N] as std::iter::IntoIterator>
-             <&'a mut [T] as std::iter::IntoIterator>
-   = note: required by `std::iter::IntoIterator::into_iter`
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0277, E0369.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs b/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs
new file mode 100644 (file)
index 0000000..5503813
--- /dev/null
@@ -0,0 +1,41 @@
+// check-pass
+
+#![feature(array_value_iter)]
+#![feature(trusted_len)]
+
+use std::{
+    array::IntoIter,
+    fmt::Debug,
+    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
+};
+
+pub fn yes_iterator() -> impl Iterator<Item = i32> {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_fused_iterator() -> impl FusedIterator {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_trusted_len() -> impl TrustedLen {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_clone() -> impl Clone {
+    IntoIter::new([0i32; 33])
+}
+
+pub fn yes_debug() -> impl Debug {
+    IntoIter::new([0i32; 33])
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.rs
deleted file mode 100644 (file)
index a0bbd2c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#![feature(array_value_iter)]
-#![feature(trusted_len)]
-
-use std::{
-    array::IntoIter,
-    fmt::Debug,
-    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
-};
-
-pub fn no_iterator() -> impl Iterator<Item = i32> {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_fused_iterator() -> impl FusedIterator {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_trusted_len() -> impl TrustedLen {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_clone() -> impl Clone {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-pub fn no_debug() -> impl Debug {
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-    IntoIter::new([0i32; 33])
-    //~^ ERROR arrays only have std trait implementations for lengths 0..=32
-}
-
-
-fn main() {}
diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
deleted file mode 100644 (file)
index ceda315..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:12:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:10:25
-   |
-LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:18:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:16:38
-   |
-LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
-   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:24:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:22:36
-   |
-LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:30:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:28:31
-   |
-LL | pub fn no_fused_iterator() -> impl FusedIterator {
-   |                               ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:36:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:34:28
-   |
-LL | pub fn no_trusted_len() -> impl TrustedLen {
-   |                            ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:42:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:40:22
-   |
-LL | pub fn no_clone() -> impl Clone {
-   |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:48:19
-   |
-LL |     IntoIter::new([0i32; 33])
-   |                   ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-   |
-   = note: required by `std::array::IntoIter::<T, N>::new`
-
-error[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/into-iter-no-impls-length-33.rs:46:22
-   |
-LL | pub fn no_debug() -> impl Debug {
-   |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
-LL |
-LL |     IntoIter::new([0i32; 33])
-   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33_usize>`
-   |
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33_usize>`
-   = note: the return type of a function must have a statically known size
-
-error: aborting due to 14 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index c2f9b786f8f898f4a830fd928993d8992d5b4605..2cd035639ee5cca80eb7d322b95638e1c71d560f 100644 (file)
@@ -1,3 +1,5 @@
+// run-pass
+
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete
 
@@ -5,6 +7,5 @@
 
 #[derive(Debug)]
 struct S<T: Debug, const N: usize>([T; N]);
-//~^ ERROR arrays only have std trait implementations for lengths 0..=32
 
 fn main() {}
index 05552027f13d01ee5c8f23a79c337629d87dcd0d..c36ef8450976c9aa55f888b5864a98ac438b4e12 100644 (file)
@@ -1,5 +1,5 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/broken-mir-2.rs:1:12
+  --> $DIR/broken-mir-2.rs:3:12
    |
 LL | #![feature(const_generics)]
    |            ^^^^^^^^^^^^^^
@@ -7,17 +7,5 @@ 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[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/broken-mir-2.rs:7:36
-   |
-LL | struct S<T: Debug, const N: usize>([T; N]);
-   |                                    ^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[T; N]`
-   |
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `[T; N]`
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; N]`
-   = note: required for the cast to the object type `dyn std::fmt::Debug`
-   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error; 1 warning emitted
+warning: 1 warning emitted
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.rs b/src/test/ui/const-generics/const-argument-non-static-lifetime.rs
new file mode 100644 (file)
index 0000000..bc09ba2
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+#![allow(dead_code)]
+
+fn test<const N: usize>() {}
+
+fn wow<'a>() -> &'a () {
+    test::<{
+        let _: &'a ();
+        3
+    }>();
+    &()
+}
+
+fn main() {}
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
new file mode 100644 (file)
index 0000000..53a7550
--- /dev/null
@@ -0,0 +1,11 @@
+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/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs
new file mode 100644 (file)
index 0000000..7f17c63
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+
+struct A<T = u32, const N: usize> {
+    //~^ ERROR type parameters with a default must be trailing
+    arg: T,
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.stderr
new file mode 100644 (file)
index 0000000..283f665
--- /dev/null
@@ -0,0 +1,19 @@
+error: type parameters with a default must be trailing
+  --> $DIR/wrong-order.rs:3:10
+   |
+LL | struct A<T = u32, const N: usize> {
+   |          ^
+   |
+   = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/wrong-order.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 c6d8b32f276f31930a8f6ca7e9443c19cd5cb518..36272ae86199d68808dd29390d2bf95e7e786ea3 100644 (file)
@@ -1,9 +1,11 @@
+// run-pass
+
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete
 
 #[derive(Debug)]
 struct X<const N: usize> {
-    a: [u32; N], //~ ERROR arrays only have std trait implementations for lengths 0..=32
+    a: [u32; N],
 }
 
 fn main() {}
index a0abbd168946ac634b5bff303c41d6e4954d6d3c..8f7ab822554a2abefc6a545b225378cb127861e2 100644 (file)
@@ -1,5 +1,5 @@
 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:1:12
+  --> $DIR/derive-debug-array-wrapper.rs:3:12
    |
 LL | #![feature(const_generics)]
    |            ^^^^^^^^^^^^^^
@@ -7,17 +7,5 @@ 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[E0277]: arrays only have std trait implementations for lengths 0..=32
-  --> $DIR/derive-debug-array-wrapper.rs:6:5
-   |
-LL |     a: [u32; N],
-   |     ^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[u32; N]`
-   |
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `[u32; N]`
-   = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[u32; N]`
-   = note: required for the cast to the object type `dyn std::fmt::Debug`
-   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error; 1 warning emitted
+warning: 1 warning emitted
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-56445.rs b/src/test/ui/const-generics/issues/issue-56445.rs
new file mode 100644 (file)
index 0000000..2644151
--- /dev/null
@@ -0,0 +1,12 @@
+// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995.
+
+#![feature(const_generics)]
+//~^ WARN: the feature `const_generics` is incomplete
+#![crate_type = "lib"]
+
+use std::marker::PhantomData;
+
+struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
+//~^ ERROR: use of non-static lifetime `'a` in const generic
+
+impl Bug<'_, ""> {}
diff --git a/src/test/ui/const-generics/issues/issue-56445.stderr b/src/test/ui/const-generics/issues/issue-56445.stderr
new file mode 100644 (file)
index 0000000..fba638b
--- /dev/null
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-56445.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
+
+error[E0771]: use of non-static lifetime `'a` in const generic
+  --> $DIR/issue-56445.rs:9:26
+   |
+LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
+   |                          ^^
+   |
+   = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0771`.
index 2a983e426838c683a0b3d3fbabb8ae9ecf8e71e0..795c5154f815551d04c1b0dfa6354c002081a9c1 100644 (file)
@@ -1,7 +1,7 @@
 // build-fail
 
 // Regression test for #66975
-#![warn(const_err)]
+#![warn(const_err, unconditional_panic)]
 #![feature(never_type)]
 
 struct PrintName<T>(T);
@@ -9,6 +9,7 @@
 impl<T> PrintName<T> {
     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
     //~^ WARN any use of this value will cause an error
+
 }
 
 fn f<T>() {
index d78e0da00f5e17723dbd25199aec95b686b6b8b9..33e60dd7c9138c725e43441a8b2dbd677829ed3e 100644 (file)
@@ -9,11 +9,11 @@ LL |     const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
 note: the lint level is defined here
   --> $DIR/index-out-of-bounds-never-type.rs:4:9
    |
-LL | #![warn(const_err)]
+LL | #![warn(const_err, unconditional_panic)]
    |         ^^^^^^^^^
 
 error: erroneous constant encountered
-  --> $DIR/index-out-of-bounds-never-type.rs:15:13
+  --> $DIR/index-out-of-bounds-never-type.rs:16:13
    |
 LL |     let _ = PrintName::<T>::VOID;
    |             ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/issue-73976-monomorphic.rs b/src/test/ui/consts/issue-73976-monomorphic.rs
new file mode 100644 (file)
index 0000000..7706a97
--- /dev/null
@@ -0,0 +1,36 @@
+// check-pass
+//
+// This test is complement to the test in issue-73976-polymorphic.rs.
+// In that test we ensure that polymorphic use of type_id and type_name in patterns
+// will be properly rejected. This test will ensure that monomorphic use of these
+// would not be wrongly rejected in patterns.
+
+#![feature(const_type_id)]
+#![feature(const_type_name)]
+
+use std::any::{self, TypeId};
+
+pub struct GetTypeId<T>(T);
+
+impl<T: 'static> GetTypeId<T> {
+    pub const VALUE: TypeId = TypeId::of::<T>();
+}
+
+const fn check_type_id<T: 'static>() -> bool {
+    matches!(GetTypeId::<T>::VALUE, GetTypeId::<usize>::VALUE)
+}
+
+pub struct GetTypeNameLen<T>(T);
+
+impl<T: 'static> GetTypeNameLen<T> {
+    pub const VALUE: usize = any::type_name::<T>().len();
+}
+
+const fn check_type_name_len<T: 'static>() -> bool {
+    matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<usize>::VALUE)
+}
+
+fn main() {
+    assert!(check_type_id::<usize>());
+    assert!(check_type_name_len::<usize>());
+}
diff --git a/src/test/ui/consts/issue-73976-polymorphic.rs b/src/test/ui/consts/issue-73976-polymorphic.rs
new file mode 100644 (file)
index 0000000..28b8451
--- /dev/null
@@ -0,0 +1,40 @@
+// This test is from #73976. We previously did not check if a type is monomorphized
+// before calculating its type id, which leads to the bizzare behaviour below that
+// TypeId of a generic type does not match itself.
+//
+// This test case should either run-pass or be rejected at compile time.
+// Currently we just disallow this usage and require pattern is monomorphic.
+
+#![feature(const_type_id)]
+#![feature(const_type_name)]
+
+use std::any::{self, TypeId};
+
+pub struct GetTypeId<T>(T);
+
+impl<T: 'static> GetTypeId<T> {
+    pub const VALUE: TypeId = TypeId::of::<T>();
+}
+
+const fn check_type_id<T: 'static>() -> bool {
+    matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
+    //~^ ERROR could not evaluate constant pattern
+    //~| ERROR could not evaluate constant pattern
+}
+
+pub struct GetTypeNameLen<T>(T);
+
+impl<T: 'static> GetTypeNameLen<T> {
+    pub const VALUE: usize = any::type_name::<T>().len();
+}
+
+const fn check_type_name_len<T: 'static>() -> bool {
+    matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
+    //~^ ERROR could not evaluate constant pattern
+    //~| ERROR could not evaluate constant pattern
+}
+
+fn main() {
+    assert!(check_type_id::<usize>());
+    assert!(check_type_name_len::<usize>());
+}
diff --git a/src/test/ui/consts/issue-73976-polymorphic.stderr b/src/test/ui/consts/issue-73976-polymorphic.stderr
new file mode 100644 (file)
index 0000000..c90ce2b
--- /dev/null
@@ -0,0 +1,26 @@
+error: could not evaluate constant pattern
+  --> $DIR/issue-73976-polymorphic.rs:20:37
+   |
+LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
+   |                                     ^^^^^^^^^^^^^^^^^^^^^
+
+error: could not evaluate constant pattern
+  --> $DIR/issue-73976-polymorphic.rs:32:42
+   |
+LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: could not evaluate constant pattern
+  --> $DIR/issue-73976-polymorphic.rs:20:37
+   |
+LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
+   |                                     ^^^^^^^^^^^^^^^^^^^^^
+
+error: could not evaluate constant pattern
+  --> $DIR/issue-73976-polymorphic.rs:32:42
+   |
+LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
index 3ea5f88f07d1e5a9137dcbc39353f99dcdcaf3a3..af494e37349146f91cb3a196a0dc5a1df5d849b0 100644 (file)
@@ -6,7 +6,8 @@ impl<A, B> Foo<A, B> {
     pub fn crash() -> bool {
         [5; Self::HOST_SIZE] == [6; 0]
         //~^ ERROR constant expression depends on a generic parameter
-        //~| ERROR binary operation `==` cannot be applied to type `[{integer}; _]`
+        //~| ERROR constant expression depends on a generic parameter
+        //~| ERROR can't compare `[{integer}; _]` with `[{integer}; 0]`
     }
 }
 
index 8b29c533bcc9344c8319f07332c11d3b0574c0d9..d5816fbb8e4fb46ec06c514b2aa94cf5bfaf59ca 100644 (file)
@@ -6,14 +6,22 @@ LL |         [5; Self::HOST_SIZE] == [6; 0]
    |
    = note: this may fail depending on what value the parameter takes
 
-error[E0369]: binary operation `==` cannot be applied to type `[{integer}; _]`
+error: constant expression depends on a generic parameter
+  --> $DIR/too_generic_eval_ice.rs:7:30
+   |
+LL |         [5; Self::HOST_SIZE] == [6; 0]
+   |                              ^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error[E0277]: can't compare `[{integer}; _]` with `[{integer}; 0]`
   --> $DIR/too_generic_eval_ice.rs:7:30
    |
 LL |         [5; Self::HOST_SIZE] == [6; 0]
-   |         -------------------- ^^ ------ [{integer}; 0]
-   |         |
-   |         [{integer}; _]
+   |                              ^^ no implementation for `[{integer}; _] == [{integer}; 0]`
+   |
+   = help: the trait `std::cmp::PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; _]`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0369`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/error-codes/E0308-2.rs b/src/test/ui/error-codes/E0308-2.rs
new file mode 100644 (file)
index 0000000..157f992
--- /dev/null
@@ -0,0 +1,12 @@
+trait DynEq {}
+
+impl<'a> PartialEq for &'a (dyn DynEq + 'static) {
+    fn eq(&self, _other: &Self) -> bool {
+        true
+    }
+}
+
+impl Eq for &dyn DynEq {} //~ ERROR E0308
+
+fn main() {
+}
diff --git a/src/test/ui/error-codes/E0308-2.stderr b/src/test/ui/error-codes/E0308-2.stderr
new file mode 100644 (file)
index 0000000..e7c5e4b
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/E0308-2.rs:9:6
+   |
+LL | impl Eq for &dyn DynEq {}
+   |      ^^ lifetime mismatch
+   |
+   = note: expected trait `std::cmp::PartialEq`
+              found trait `std::cmp::PartialEq`
+note: the lifetime `'_` as defined on the impl at 9:13...
+  --> $DIR/E0308-2.rs:9:13
+   |
+LL | impl Eq for &dyn DynEq {}
+   |             ^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/error-codes/E0771.rs b/src/test/ui/error-codes/E0771.rs
new file mode 100644 (file)
index 0000000..ba35927
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete
+
+fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0771
+
+fn main() {
+    function_with_str::<"Hello, world!">()
+}
diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr
new file mode 100644 (file)
index 0000000..60220be
--- /dev/null
@@ -0,0 +1,20 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/E0771.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[E0771]: use of non-static lifetime `'a` in const generic
+  --> $DIR/E0771.rs:4:41
+   |
+LL | fn function_with_str<'a, const STRING: &'a str>() {}
+   |                                         ^^
+   |
+   = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0771`.
index 64f01b47792c7629ceaef1142b01d616b59fbebf..2cb15f84f6973922f4cb0087658df1268d93c75d 100644 (file)
@@ -8,7 +8,7 @@ LL |     is_fn(f);
    |           ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
    |
    = help: the trait `std::ops::Fn<()>` is not implemented for `extern "C" fn() {f}`
-   = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
 
 error: aborting due to previous error
 
index c66bbb0c5045f4ef99c4d31cd12e784a6353d5ca..e3272e8849f9b23d805864053c8b5bc7369c70c9 100644 (file)
@@ -52,7 +52,7 @@ LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
    = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
-  --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6
+  --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16
    |
 LL | trait NonObjectSafe1: Sized {}
    |       --------------  ----- ...because it requires `Self: Sized`
@@ -60,7 +60,7 @@ LL | trait NonObjectSafe1: Sized {}
    |       this trait cannot be made into an object...
 ...
 LL | impl Trait for dyn NonObjectSafe1 {}
-   |      ^^^^^ the trait `NonObjectSafe1` cannot be made into an object
+   |                ^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object
 
 error: aborting due to 5 previous errors
 
index 2fab7ffb66050b103e6a3a301dc897edfeb1a626..2fe266b8018ebe81496836921d1c805ff29111fd 100644 (file)
@@ -16,7 +16,7 @@ LL |     type F<'a>: Fn() -> u32;
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
    |
-   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }`
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::ops::Fn<()>> Fun for T {
index 186e142138be2fe93c23b464061d224cac0acef2..e335523778b4703157e040e24be84d36b5ac1a1e 100644 (file)
@@ -16,7 +16,7 @@ LL |     type F<'a>: Fn() -> u32;
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
    |
-   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }`
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::ops::Fn<()>> Fun for T {
index d16bdcbbb6b00d859da406fb85c4247487512801..d7a5bb0ebe5439130f9f5d22eaa43fb6cfb94db6 100644 (file)
@@ -16,7 +16,7 @@ LL |     type F<'a>: Fn() -> u32;
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
    |
-   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }`
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::ops::Fn<()>> Fun for T {
index 72c42917c83c92a53cd953e56ac28ba32510fee9..0670625aa2f1b0abc59e65808aa6760cad20d1a5 100644 (file)
@@ -16,7 +16,7 @@ LL |     type F<'a>: Fn() -> u32;
 LL |     type F<'a> = Self;
    |     ^^^^^^^^^^^^^^^^^^ expected an `Fn<()>` closure, found `T`
    |
-   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }`
 help: consider restricting type parameter `T`
    |
 LL | impl<T: std::ops::Fn<()>> Fun for T {
diff --git a/src/test/ui/hygiene/auxiliary/needs_hygiene.rs b/src/test/ui/hygiene/auxiliary/needs_hygiene.rs
new file mode 100644 (file)
index 0000000..3df6450
--- /dev/null
@@ -0,0 +1,5 @@
+#![feature(decl_macro)]
+macro x() { struct MyStruct; }
+
+x!();
+x!();
diff --git a/src/test/ui/hygiene/auxiliary/nested-dollar-crate.rs b/src/test/ui/hygiene/auxiliary/nested-dollar-crate.rs
new file mode 100644 (file)
index 0000000..e5caa0f
--- /dev/null
@@ -0,0 +1,14 @@
+pub const IN_DEF_CRATE: &str = "In def crate!";
+
+macro_rules! make_it {
+    () => {
+        #[macro_export]
+        macro_rules! inner {
+            () => {
+                $crate::IN_DEF_CRATE
+            }
+        }
+    }
+}
+
+make_it!();
diff --git a/src/test/ui/hygiene/cross_crate_hygiene.rs b/src/test/ui/hygiene/cross_crate_hygiene.rs
new file mode 100644 (file)
index 0000000..7574296
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+// aux-build:needs_hygiene.rs
+
+extern crate needs_hygiene;
+
+use needs_hygiene::*;
+
+fn main() {}
diff --git a/src/test/ui/hygiene/nested-dollar-crate.rs b/src/test/ui/hygiene/nested-dollar-crate.rs
new file mode 100644 (file)
index 0000000..e8703bc
--- /dev/null
@@ -0,0 +1,9 @@
+// aux-build:nested-dollar-crate.rs
+// edition:2018
+// run-pass
+
+extern crate nested_dollar_crate;
+
+fn main() {
+    assert_eq!(nested_dollar_crate::inner!(), "In def crate!");
+}
diff --git a/src/test/ui/hygiene/panic-location.rs b/src/test/ui/hygiene/panic-location.rs
new file mode 100644 (file)
index 0000000..5cf169d
--- /dev/null
@@ -0,0 +1,10 @@
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=0
+//
+// Regression test for issue #70963
+// The captured stderr from this test reports a location
+// inside `VecDeque::with_capacity`, instead of `<::core::macros::panic macros>`
+fn main() {
+    std::collections::VecDeque::<String>::with_capacity(!0);
+}
diff --git a/src/test/ui/hygiene/panic-location.run.stderr b/src/test/ui/hygiene/panic-location.run.stderr
new file mode 100644 (file)
index 0000000..abdccf6
--- /dev/null
@@ -0,0 +1,2 @@
+thread 'main' panicked at 'capacity overflow', $SRC_DIR/liballoc/collections/vec_deque.rs:LL:COL
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
index d4ad706d01bc2359d73e7198f802bf7617d4aacc..89210fdf137e0d169203d61f79f1b6ff982686e0 100644 (file)
@@ -17,7 +17,7 @@ fn static_val<T: StaticTrait>(_: T) {
 }
 
 fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
-    static_val(x); //~ ERROR cannot infer
+    static_val(x); //~ ERROR E0759
 }
 
 fn not_static_val<T: NotStaticTrait>(_: T) {
index 268008c211129e704f6a5412c127a1aa1a9bf573..b3bef677d19c1c84999b011663277607a8f44ec4 100644 (file)
@@ -1,30 +1,17 @@
-error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/dyn-trait.rs:20:16
    |
-LL |     static_val(x);
-   |                ^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26...
-  --> $DIR/dyn-trait.rs:19:26
-   |
 LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
-   |                          ^^
-note: ...so that the expression is assignable
-  --> $DIR/dyn-trait.rs:20:16
-   |
+   |                                 ------------------- this data with lifetime `'a`...
 LL |     static_val(x);
-   |                ^
-   = note: expected `std::boxed::Box<dyn std::fmt::Debug>`
-              found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the types are compatible
+   |                ^ ...is captured here...
+   |
+note: ...and is required to live as long as `'static` here
   --> $DIR/dyn-trait.rs:20:5
    |
 LL |     static_val(x);
    |     ^^^^^^^^^^
-   = note: expected `StaticTrait`
-              found `StaticTrait`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs
new file mode 100644 (file)
index 0000000..dee5a41
--- /dev/null
@@ -0,0 +1,22 @@
+// Regression test for #72911.
+
+pub struct Lint {}
+
+impl Lint {}
+
+pub fn gather_all() -> impl Iterator<Item = Lint> {
+    //~^ ERROR: cannot resolve opaque type
+    lint_files().flat_map(|f| gather_from_file(&f))
+}
+
+fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
+    //~^ ERROR: failed to resolve
+    unimplemented!()
+}
+
+fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+    //~^ ERROR: failed to resolve
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr
new file mode 100644 (file)
index 0000000..b28142b
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0433]: failed to resolve: use of undeclared type or module `foo`
+  --> $DIR/issue-72911.rs:12:33
+   |
+LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
+   |                                 ^^^ use of undeclared type or module `foo`
+
+error[E0433]: failed to resolve: use of undeclared type or module `foo`
+  --> $DIR/issue-72911.rs:17:41
+   |
+LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+   |                                         ^^^ use of undeclared type or module `foo`
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-72911.rs:7:24
+   |
+LL | pub fn gather_all() -> impl Iterator<Item = Lint> {
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
+LL |
+LL |     lint_files().flat_map(|f| gather_from_file(&f))
+   |     -----------------------------------------------
+   |     |
+   |     returning here with type `std::iter::FlatMap<impl std::iter::Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+   |     returning here with type `std::iter::FlatMap<impl std::iter::Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+...
+LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> {
+   |                                                      -------------------------- returning this opaque type `std::iter::FlatMap<impl std::iter::Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+...
+LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> {
+   |                    -------------------------------------- returning this opaque type `std::iter::FlatMap<impl std::iter::Iterator, [type error], [closure@$DIR/issue-72911.rs:9:27: 9:51]>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0433, E0720.
+For more information about an error, try `rustc --explain E0433`.
index 3b339c5c3d7fc69a75c6a1f00338b8b8a748f2f2..4372de245078fc930be3cb4a27dd1f30e337be7d 100644 (file)
@@ -12,7 +12,7 @@ LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                       ^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:32
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |             --                 ^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
@@ -26,7 +26,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                ^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               -                              ^ returning this value requires that `'1` must outlive `'static`
@@ -36,7 +36,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    = help: consider replacing `'1` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |              -- lifetime `'a` defined here            ^ returning this value requires that `'a` must outlive `'static`
@@ -45,7 +45,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/must_outlive_least_region_or_bound.rs:15:41
+  --> $DIR/must_outlive_least_region_or_bound.rs:11:41
    |
 LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
    |               ----                      ^ lifetime `'a` required
@@ -53,7 +53,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
    |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:24
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               -        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
@@ -61,7 +61,7 @@ LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               let's call the lifetime of this reference `'1`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:69
+  --> $DIR/must_outlive_least_region_or_bound.rs:28:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
@@ -70,7 +70,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:42:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:32:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                          --  -- lifetime `'b` defined here  ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
@@ -80,7 +80,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    = help: consider adding the following bound: `'b: 'a`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:47:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:37:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                                   ^^^^^^^^^^^^^^^^^^^^
index 9bf86fa66cdeda4c7ccd2cd6a55d18a2fbdc570a..51f488e45a6f3d14ce6cea95d318c3f06e126ef0 100644 (file)
@@ -1,41 +1,31 @@
 use std::fmt::Debug;
 
-fn elided(x: &i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided(x: &i32) -> impl Copy { x } //~ ERROR E0759
 
-fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit<'a>(x: &'a i32) -> impl Copy { x } //~ ERROR E0759
 
-fn elided2(x: &i32) -> impl Copy + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided2(x: &i32) -> impl Copy + 'static { x } //~ ERROR E0759
 
-fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } //~ ERROR E0759
 
 fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
 //~^ ERROR explicit lifetime required in the type of `x`
 
-fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } //~ ERROR E0759
 
-fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } //~ ERROR E0759
 
-fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
-//~^ ERROR cannot infer an appropriate lifetime
+fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
 
-fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
-//~^ ERROR cannot infer an appropriate lifetime
+fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } //~ ERROR E0759
 
-fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
-//~^ ERROR cannot infer an appropriate lifetime
-//~| ERROR cannot infer an appropriate lifetime
+fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~ ERROR E0759
+//~^ ERROR E0759
 
 trait LifetimeTrait<'a> {}
 impl<'a> LifetimeTrait<'a> for &'a i32 {}
 
-fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-//~^ ERROR cannot infer an appropriate lifetime
+fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~ ERROR E0759
 
 // Tests that a closure type containing 'b cannot be returned from a type where
 // only 'a was expected.
index ffadcaae08e05ed165636b369249098c140a5f37..b040889217e47032e23cfcffbd0b301ce63f31fa 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
@@ -16,8 +16,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:44
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                    -------                 ^ ...is captured here...
@@ -25,7 +25,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                    this data with lifetime `'a`...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+  --> $DIR/must_outlive_least_region_or_bound.rs:5:32
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
    |                                ^^^^^^^^^
@@ -34,8 +34,8 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                          ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:46
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               ----                           ^ ...is captured here...
@@ -43,7 +43,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |               this data with an anonymous lifetime `'_`...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:9:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:7:24
    |
 LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
    |                        ^^^^^^^^^^^^^^^^^^^
@@ -56,8 +56,8 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
    |               ^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:55
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                     -------                           ^ ...is captured here...
@@ -65,7 +65,7 @@ LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                     this data with lifetime `'a`...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:33
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:33
    |
 LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
    |                                 ^^^^^^^^^^^^^^^^^^^
@@ -79,15 +79,15 @@ LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
    |                     ^^^^^^^^^^^^
 
 error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/must_outlive_least_region_or_bound.rs:15:24
+  --> $DIR/must_outlive_least_region_or_bound.rs:11:24
    |
 LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
    |               ----     ^^^^^^^^^^^^^^ lifetime `'a` required
    |               |
    |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:65
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:65
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static`
@@ -101,14 +101,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
    |                                                    ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:69
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:69
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |               ---- this data with an anonymous lifetime `'_`...     ^ ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:30:41
+  --> $DIR/must_outlive_least_region_or_bound.rs:22:41
    |
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
    |                                         ^^^^^^^^^^
@@ -121,14 +121,14 @@ help: to declare that the `impl Trait` captures data from argument `x`, you can
 LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
    |                                                    ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:69
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:28:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |                      ------- this data with lifetime `'a`...        ^ ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/must_outlive_least_region_or_bound.rs:37:34
+  --> $DIR/must_outlive_least_region_or_bound.rs:28:34
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -142,7 +142,7 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x
    |                      ^^^^^^^^^^^^
 
 error[E0623]: lifetime mismatch
-  --> $DIR/must_outlive_least_region_or_bound.rs:42:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:32:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                                                 -------     ^^^^^^^^^^^^^^^^
@@ -151,15 +151,15 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                 this parameter and the return type are declared with different lifetimes...
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:47:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:37:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                 --                ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |                                 |
    |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:14:50
    |
 LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
    |               ----                               ^ ...is captured here, requiring it to live as long as `'static`
@@ -171,8 +171,8 @@ help: to declare that the trait object captures data from argument `x`, you can
 LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
    |                                      ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:21:59
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:16:59
    |
 LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
    |                     -------                               ^ ...is captured here, requiring it to live as long as `'static`
@@ -184,8 +184,8 @@ help: to declare that the trait object captures data from argument `x`, you can
 LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
    |                                               ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:24:60
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:18:60
    |
 LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
    |               ----                                         ^ ...is captured here, requiring it to live as long as `'static`
@@ -201,8 +201,8 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
    |               ^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:27:69
+error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/must_outlive_least_region_or_bound.rs:20:69
    |
 LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
    |                     ------- this data with lifetime `'a`...         ^ ...is captured here, requiring it to live as long as `'static`
index 123ea6af6b019f6e5f171cf54fe57f575a805bac..65178cc9d24c262f3b186f99310df4a36a8c5330 100644 (file)
@@ -12,7 +12,7 @@ LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/static-return-lifetime-infered.rs:10:37
+  --> $DIR/static-return-lifetime-infered.rs:9:37
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                    --               ^^^^^^^^^^^^^^^^^^^^^^^ opaque type requires that `'a` must outlive `'static`
index 96f3652c226ea0b7eb09a02fab91689ee4158f5e..518c52f5de4d7bfb3b26ce59a59d6668a7259ced 100644 (file)
@@ -4,13 +4,11 @@ struct A {
 
 impl A {
     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-        self.x.iter().map(|a| a.0)
+        self.x.iter().map(|a| a.0) //~ ERROR E0759
     }
-    //~^^ ERROR cannot infer an appropriate lifetime
     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-        self.x.iter().map(|a| a.0)
+        self.x.iter().map(|a| a.0) //~ ERROR E0759
     }
-    //~^^ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {}
index df0db6e4fc6df927297d9793d271390de5bc21dd..7c289b388223a4b6ebff083f9f32210745ee7d6c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/static-return-lifetime-infered.rs:7:16
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
@@ -18,8 +18,8 @@ help: to declare that the `impl Trait` captures data from argument `self`, you c
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
-  --> $DIR/static-return-lifetime-infered.rs:11:16
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/static-return-lifetime-infered.rs:10:16
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                        -------- this data with lifetime `'a`...
@@ -29,7 +29,7 @@ LL |         self.x.iter().map(|a| a.0)
    |         ...is captured here...
    |
 note: ...and is required to live as long as `'static` here
-  --> $DIR/static-return-lifetime-infered.rs:10:37
+  --> $DIR/static-return-lifetime-infered.rs:9:37
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issue-74047.rs b/src/test/ui/issue-74047.rs
new file mode 100644 (file)
index 0000000..2e4f3e6
--- /dev/null
@@ -0,0 +1,17 @@
+// edition:2018
+
+use std::convert::{TryFrom, TryInto};
+use std::io;
+
+pub struct MyStream;
+pub struct OtherStream;
+
+pub async fn connect() -> io::Result<MyStream> {
+    let stream: MyStream = OtherStream.try_into()?;
+    Ok(stream)
+}
+
+impl TryFrom<OtherStream> for MyStream {}
+//~^ ERROR: missing
+
+fn main() {}
diff --git a/src/test/ui/issue-74047.stderr b/src/test/ui/issue-74047.stderr
new file mode 100644 (file)
index 0000000..6f477c7
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`, `try_from`
+  --> $DIR/issue-74047.rs:14:1
+   |
+LL | impl TryFrom<OtherStream> for MyStream {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Error`, `try_from` in implementation
+   |
+   = help: implement the missing item: `type Error = Type;`
+   = help: implement the missing item: `fn try_from(_: T) -> std::result::Result<Self, <Self as std::convert::TryFrom<T>>::Error> { todo!() }`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
index 827163ef83cf7cf4c7f3fff461b0d28fce7d2333..f048ccd2427cb052cc465de1b9a3302236334e6e 100644 (file)
@@ -1,8 +1,7 @@
 use std::any::Any;
 
 fn foo<T: Any>(value: &T) -> Box<dyn Any> {
-    Box::new(value) as Box<dyn Any>
-    //~^ ERROR cannot infer an appropriate lifetime
+    Box::new(value) as Box<dyn Any> //~ ERROR E0759
 }
 
 fn main() {
index 919594fc9af4b434967d1975e1a23b41346c5f6e..6decc751321f9abfd3a434d39873dd34af7b6b87 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/issue-16922.rs:4:14
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
index f7e46b25cf82ba3fb929c20402ec718b006ab938..27e5c606a64a408179d7f68b35eea1886dd77b65 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Bound` is not satisfied
-  --> $DIR/issue-21837.rs:8:9
+  --> $DIR/issue-21837.rs:8:20
    |
 LL | pub struct Foo<T: Bound>(T);
    |                   ----- required by this bound in `Foo`
 ...
 LL | impl<T> Trait2 for Foo<T> {}
-   |         ^^^^^^ the trait `Bound` is not implemented for `T`
+   |                    ^^^^^^ the trait `Bound` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
index 19fb080154a4a3bf0a9db0b24ebce5c565a030e4..132880aab11e360feff89af057f3bd162f284eb4 100644 (file)
@@ -5,7 +5,7 @@ LL |         &mut *(ptr as *mut dyn Fn())
    |                ^^^ expected an `Fn<()>` closure, found `()`
    |
    = help: the trait `std::ops::Fn<()>` is not implemented for `()`
-   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
    = note: required for the cast to the object type `dyn std::ops::Fn()`
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs
new file mode 100644 (file)
index 0000000..75632d1
--- /dev/null
@@ -0,0 +1,12 @@
+enum E {
+    A(u8, u8),
+}
+
+fn main() {
+    let e = E::A(2, 3);
+    match e {
+        E::A(x @ ..) => {  //~ ERROR `x @` is not allowed in a tuple
+            x //~ ERROR cannot find value `x` in this scope
+        }
+    };
+}
diff --git a/src/test/ui/issues/issue-74539.stderr b/src/test/ui/issues/issue-74539.stderr
new file mode 100644 (file)
index 0000000..94526dc
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/issue-74539.rs:9:13
+   |
+LL |             x
+   |             ^ help: a local variable with a similar name exists: `e`
+
+error: `x @` is not allowed in a tuple struct
+  --> $DIR/issue-74539.rs:8:14
+   |
+LL |         E::A(x @ ..) => {
+   |              ^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of x, discard the tuple's remaining fields
+   |
+LL |         E::A(..) => {
+   |              ^^
+
+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-74564-if-expr-stack-overflow.rs b/src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs
new file mode 100644 (file)
index 0000000..36e9932
--- /dev/null
@@ -0,0 +1,10419 @@
+// build-pass
+// ignore-tidy-filelength
+#![crate_type = "rlib"]
+
+fn banana(v: &str) -> u32 {
+    if v == "1" {
+        1
+    } else if v == "2" {
+        2
+    } else if v == "3" {
+        3
+    } else if v == "4" {
+        4
+    } else if v == "5" {
+        5
+    } else if v == "6" {
+        6
+    } else if v == "7" {
+        7
+    } else if v == "8" {
+        8
+    } else if v == "9" {
+        9
+    } else if v == "10" {
+        10
+    } else if v == "11" {
+        11
+    } else if v == "12" {
+        12
+    } else if v == "13" {
+        13
+    } else if v == "14" {
+        14
+    } else if v == "15" {
+        15
+    } else if v == "16" {
+        16
+    } else if v == "17" {
+        17
+    } else if v == "18" {
+        18
+    } else if v == "19" {
+        19
+    } else if v == "20" {
+        20
+    } else if v == "21" {
+        21
+    } else if v == "22" {
+        22
+    } else if v == "23" {
+        23
+    } else if v == "24" {
+        24
+    } else if v == "25" {
+        25
+    } else if v == "26" {
+        26
+    } else if v == "27" {
+        27
+    } else if v == "28" {
+        28
+    } else if v == "29" {
+        29
+    } else if v == "30" {
+        30
+    } else if v == "31" {
+        31
+    } else if v == "32" {
+        32
+    } else if v == "33" {
+        33
+    } else if v == "34" {
+        34
+    } else if v == "35" {
+        35
+    } else if v == "36" {
+        36
+    } else if v == "37" {
+        37
+    } else if v == "38" {
+        38
+    } else if v == "39" {
+        39
+    } else if v == "40" {
+        40
+    } else if v == "41" {
+        41
+    } else if v == "42" {
+        42
+    } else if v == "43" {
+        43
+    } else if v == "44" {
+        44
+    } else if v == "45" {
+        45
+    } else if v == "46" {
+        46
+    } else if v == "47" {
+        47
+    } else if v == "48" {
+        48
+    } else if v == "49" {
+        49
+    } else if v == "50" {
+        50
+    } else if v == "51" {
+        51
+    } else if v == "52" {
+        52
+    } else if v == "53" {
+        53
+    } else if v == "54" {
+        54
+    } else if v == "55" {
+        55
+    } else if v == "56" {
+        56
+    } else if v == "57" {
+        57
+    } else if v == "58" {
+        58
+    } else if v == "59" {
+        59
+    } else if v == "60" {
+        60
+    } else if v == "61" {
+        61
+    } else if v == "62" {
+        62
+    } else if v == "63" {
+        63
+    } else if v == "64" {
+        64
+    } else if v == "65" {
+        65
+    } else if v == "66" {
+        66
+    } else if v == "67" {
+        67
+    } else if v == "68" {
+        68
+    } else if v == "69" {
+        69
+    } else if v == "70" {
+        70
+    } else if v == "71" {
+        71
+    } else if v == "72" {
+        72
+    } else if v == "73" {
+        73
+    } else if v == "74" {
+        74
+    } else if v == "75" {
+        75
+    } else if v == "76" {
+        76
+    } else if v == "77" {
+        77
+    } else if v == "78" {
+        78
+    } else if v == "79" {
+        79
+    } else if v == "80" {
+        80
+    } else if v == "81" {
+        81
+    } else if v == "82" {
+        82
+    } else if v == "83" {
+        83
+    } else if v == "84" {
+        84
+    } else if v == "85" {
+        85
+    } else if v == "86" {
+        86
+    } else if v == "87" {
+        87
+    } else if v == "88" {
+        88
+    } else if v == "89" {
+        89
+    } else if v == "90" {
+        90
+    } else if v == "91" {
+        91
+    } else if v == "92" {
+        92
+    } else if v == "93" {
+        93
+    } else if v == "94" {
+        94
+    } else if v == "95" {
+        95
+    } else if v == "96" {
+        96
+    } else if v == "97" {
+        97
+    } else if v == "98" {
+        98
+    } else if v == "99" {
+        99
+    } else if v == "100" {
+        100
+    } else if v == "101" {
+        101
+    } else if v == "102" {
+        102
+    } else if v == "103" {
+        103
+    } else if v == "104" {
+        104
+    } else if v == "105" {
+        105
+    } else if v == "106" {
+        106
+    } else if v == "107" {
+        107
+    } else if v == "108" {
+        108
+    } else if v == "109" {
+        109
+    } else if v == "110" {
+        110
+    } else if v == "111" {
+        111
+    } else if v == "112" {
+        112
+    } else if v == "113" {
+        113
+    } else if v == "114" {
+        114
+    } else if v == "115" {
+        115
+    } else if v == "116" {
+        116
+    } else if v == "117" {
+        117
+    } else if v == "118" {
+        118
+    } else if v == "119" {
+        119
+    } else if v == "120" {
+        120
+    } else if v == "121" {
+        121
+    } else if v == "122" {
+        122
+    } else if v == "123" {
+        123
+    } else if v == "124" {
+        124
+    } else if v == "125" {
+        125
+    } else if v == "126" {
+        126
+    } else if v == "127" {
+        127
+    } else if v == "128" {
+        128
+    } else if v == "129" {
+        129
+    } else if v == "130" {
+        130
+    } else if v == "131" {
+        131
+    } else if v == "132" {
+        132
+    } else if v == "133" {
+        133
+    } else if v == "134" {
+        134
+    } else if v == "135" {
+        135
+    } else if v == "136" {
+        136
+    } else if v == "137" {
+        137
+    } else if v == "138" {
+        138
+    } else if v == "139" {
+        139
+    } else if v == "140" {
+        140
+    } else if v == "141" {
+        141
+    } else if v == "142" {
+        142
+    } else if v == "143" {
+        143
+    } else if v == "144" {
+        144
+    } else if v == "145" {
+        145
+    } else if v == "146" {
+        146
+    } else if v == "147" {
+        147
+    } else if v == "148" {
+        148
+    } else if v == "149" {
+        149
+    } else if v == "150" {
+        150
+    } else if v == "151" {
+        151
+    } else if v == "152" {
+        152
+    } else if v == "153" {
+        153
+    } else if v == "154" {
+        154
+    } else if v == "155" {
+        155
+    } else if v == "156" {
+        156
+    } else if v == "157" {
+        157
+    } else if v == "158" {
+        158
+    } else if v == "159" {
+        159
+    } else if v == "160" {
+        160
+    } else if v == "161" {
+        161
+    } else if v == "162" {
+        162
+    } else if v == "163" {
+        163
+    } else if v == "164" {
+        164
+    } else if v == "165" {
+        165
+    } else if v == "166" {
+        166
+    } else if v == "167" {
+        167
+    } else if v == "168" {
+        168
+    } else if v == "169" {
+        169
+    } else if v == "170" {
+        170
+    } else if v == "171" {
+        171
+    } else if v == "172" {
+        172
+    } else if v == "173" {
+        173
+    } else if v == "174" {
+        174
+    } else if v == "175" {
+        175
+    } else if v == "176" {
+        176
+    } else if v == "177" {
+        177
+    } else if v == "178" {
+        178
+    } else if v == "179" {
+        179
+    } else if v == "180" {
+        180
+    } else if v == "181" {
+        181
+    } else if v == "182" {
+        182
+    } else if v == "183" {
+        183
+    } else if v == "184" {
+        184
+    } else if v == "185" {
+        185
+    } else if v == "186" {
+        186
+    } else if v == "187" {
+        187
+    } else if v == "188" {
+        188
+    } else if v == "189" {
+        189
+    } else if v == "190" {
+        190
+    } else if v == "191" {
+        191
+    } else if v == "192" {
+        192
+    } else if v == "193" {
+        193
+    } else if v == "194" {
+        194
+    } else if v == "195" {
+        195
+    } else if v == "196" {
+        196
+    } else if v == "197" {
+        197
+    } else if v == "198" {
+        198
+    } else if v == "199" {
+        199
+    } else if v == "200" {
+        200
+    } else if v == "201" {
+        201
+    } else if v == "202" {
+        202
+    } else if v == "203" {
+        203
+    } else if v == "204" {
+        204
+    } else if v == "205" {
+        205
+    } else if v == "206" {
+        206
+    } else if v == "207" {
+        207
+    } else if v == "208" {
+        208
+    } else if v == "209" {
+        209
+    } else if v == "210" {
+        210
+    } else if v == "211" {
+        211
+    } else if v == "212" {
+        212
+    } else if v == "213" {
+        213
+    } else if v == "214" {
+        214
+    } else if v == "215" {
+        215
+    } else if v == "216" {
+        216
+    } else if v == "217" {
+        217
+    } else if v == "218" {
+        218
+    } else if v == "219" {
+        219
+    } else if v == "220" {
+        220
+    } else if v == "221" {
+        221
+    } else if v == "222" {
+        222
+    } else if v == "223" {
+        223
+    } else if v == "224" {
+        224
+    } else if v == "225" {
+        225
+    } else if v == "226" {
+        226
+    } else if v == "227" {
+        227
+    } else if v == "228" {
+        228
+    } else if v == "229" {
+        229
+    } else if v == "230" {
+        230
+    } else if v == "231" {
+        231
+    } else if v == "232" {
+        232
+    } else if v == "233" {
+        233
+    } else if v == "234" {
+        234
+    } else if v == "235" {
+        235
+    } else if v == "236" {
+        236
+    } else if v == "237" {
+        237
+    } else if v == "238" {
+        238
+    } else if v == "239" {
+        239
+    } else if v == "240" {
+        240
+    } else if v == "241" {
+        241
+    } else if v == "242" {
+        242
+    } else if v == "243" {
+        243
+    } else if v == "244" {
+        244
+    } else if v == "245" {
+        245
+    } else if v == "246" {
+        246
+    } else if v == "247" {
+        247
+    } else if v == "248" {
+        248
+    } else if v == "249" {
+        249
+    } else if v == "250" {
+        250
+    } else if v == "251" {
+        251
+    } else if v == "252" {
+        252
+    } else if v == "253" {
+        253
+    } else if v == "254" {
+        254
+    } else if v == "255" {
+        255
+    } else if v == "256" {
+        256
+    } else if v == "257" {
+        257
+    } else if v == "258" {
+        258
+    } else if v == "259" {
+        259
+    } else if v == "260" {
+        260
+    } else if v == "261" {
+        261
+    } else if v == "262" {
+        262
+    } else if v == "263" {
+        263
+    } else if v == "264" {
+        264
+    } else if v == "265" {
+        265
+    } else if v == "266" {
+        266
+    } else if v == "267" {
+        267
+    } else if v == "268" {
+        268
+    } else if v == "269" {
+        269
+    } else if v == "270" {
+        270
+    } else if v == "271" {
+        271
+    } else if v == "272" {
+        272
+    } else if v == "273" {
+        273
+    } else if v == "274" {
+        274
+    } else if v == "275" {
+        275
+    } else if v == "276" {
+        276
+    } else if v == "277" {
+        277
+    } else if v == "278" {
+        278
+    } else if v == "279" {
+        279
+    } else if v == "280" {
+        280
+    } else if v == "281" {
+        281
+    } else if v == "282" {
+        282
+    } else if v == "283" {
+        283
+    } else if v == "284" {
+        284
+    } else if v == "285" {
+        285
+    } else if v == "286" {
+        286
+    } else if v == "287" {
+        287
+    } else if v == "288" {
+        288
+    } else if v == "289" {
+        289
+    } else if v == "290" {
+        290
+    } else if v == "291" {
+        291
+    } else if v == "292" {
+        292
+    } else if v == "293" {
+        293
+    } else if v == "294" {
+        294
+    } else if v == "295" {
+        295
+    } else if v == "296" {
+        296
+    } else if v == "297" {
+        297
+    } else if v == "298" {
+        298
+    } else if v == "299" {
+        299
+    } else if v == "300" {
+        300
+    } else if v == "301" {
+        301
+    } else if v == "302" {
+        302
+    } else if v == "303" {
+        303
+    } else if v == "304" {
+        304
+    } else if v == "305" {
+        305
+    } else if v == "306" {
+        306
+    } else if v == "307" {
+        307
+    } else if v == "308" {
+        308
+    } else if v == "309" {
+        309
+    } else if v == "310" {
+        310
+    } else if v == "311" {
+        311
+    } else if v == "312" {
+        312
+    } else if v == "313" {
+        313
+    } else if v == "314" {
+        314
+    } else if v == "315" {
+        315
+    } else if v == "316" {
+        316
+    } else if v == "317" {
+        317
+    } else if v == "318" {
+        318
+    } else if v == "319" {
+        319
+    } else if v == "320" {
+        320
+    } else if v == "321" {
+        321
+    } else if v == "322" {
+        322
+    } else if v == "323" {
+        323
+    } else if v == "324" {
+        324
+    } else if v == "325" {
+        325
+    } else if v == "326" {
+        326
+    } else if v == "327" {
+        327
+    } else if v == "328" {
+        328
+    } else if v == "329" {
+        329
+    } else if v == "330" {
+        330
+    } else if v == "331" {
+        331
+    } else if v == "332" {
+        332
+    } else if v == "333" {
+        333
+    } else if v == "334" {
+        334
+    } else if v == "335" {
+        335
+    } else if v == "336" {
+        336
+    } else if v == "337" {
+        337
+    } else if v == "338" {
+        338
+    } else if v == "339" {
+        339
+    } else if v == "340" {
+        340
+    } else if v == "341" {
+        341
+    } else if v == "342" {
+        342
+    } else if v == "343" {
+        343
+    } else if v == "344" {
+        344
+    } else if v == "345" {
+        345
+    } else if v == "346" {
+        346
+    } else if v == "347" {
+        347
+    } else if v == "348" {
+        348
+    } else if v == "349" {
+        349
+    } else if v == "350" {
+        350
+    } else if v == "351" {
+        351
+    } else if v == "352" {
+        352
+    } else if v == "353" {
+        353
+    } else if v == "354" {
+        354
+    } else if v == "355" {
+        355
+    } else if v == "356" {
+        356
+    } else if v == "357" {
+        357
+    } else if v == "358" {
+        358
+    } else if v == "359" {
+        359
+    } else if v == "360" {
+        360
+    } else if v == "361" {
+        361
+    } else if v == "362" {
+        362
+    } else if v == "363" {
+        363
+    } else if v == "364" {
+        364
+    } else if v == "365" {
+        365
+    } else if v == "366" {
+        366
+    } else if v == "367" {
+        367
+    } else if v == "368" {
+        368
+    } else if v == "369" {
+        369
+    } else if v == "370" {
+        370
+    } else if v == "371" {
+        371
+    } else if v == "372" {
+        372
+    } else if v == "373" {
+        373
+    } else if v == "374" {
+        374
+    } else if v == "375" {
+        375
+    } else if v == "376" {
+        376
+    } else if v == "377" {
+        377
+    } else if v == "378" {
+        378
+    } else if v == "379" {
+        379
+    } else if v == "380" {
+        380
+    } else if v == "381" {
+        381
+    } else if v == "382" {
+        382
+    } else if v == "383" {
+        383
+    } else if v == "384" {
+        384
+    } else if v == "385" {
+        385
+    } else if v == "386" {
+        386
+    } else if v == "387" {
+        387
+    } else if v == "388" {
+        388
+    } else if v == "389" {
+        389
+    } else if v == "390" {
+        390
+    } else if v == "391" {
+        391
+    } else if v == "392" {
+        392
+    } else if v == "393" {
+        393
+    } else if v == "394" {
+        394
+    } else if v == "395" {
+        395
+    } else if v == "396" {
+        396
+    } else if v == "397" {
+        397
+    } else if v == "398" {
+        398
+    } else if v == "399" {
+        399
+    } else if v == "400" {
+        400
+    } else if v == "401" {
+        401
+    } else if v == "402" {
+        402
+    } else if v == "403" {
+        403
+    } else if v == "404" {
+        404
+    } else if v == "405" {
+        405
+    } else if v == "406" {
+        406
+    } else if v == "407" {
+        407
+    } else if v == "408" {
+        408
+    } else if v == "409" {
+        409
+    } else if v == "410" {
+        410
+    } else if v == "411" {
+        411
+    } else if v == "412" {
+        412
+    } else if v == "413" {
+        413
+    } else if v == "414" {
+        414
+    } else if v == "415" {
+        415
+    } else if v == "416" {
+        416
+    } else if v == "417" {
+        417
+    } else if v == "418" {
+        418
+    } else if v == "419" {
+        419
+    } else if v == "420" {
+        420
+    } else if v == "421" {
+        421
+    } else if v == "422" {
+        422
+    } else if v == "423" {
+        423
+    } else if v == "424" {
+        424
+    } else if v == "425" {
+        425
+    } else if v == "426" {
+        426
+    } else if v == "427" {
+        427
+    } else if v == "428" {
+        428
+    } else if v == "429" {
+        429
+    } else if v == "430" {
+        430
+    } else if v == "431" {
+        431
+    } else if v == "432" {
+        432
+    } else if v == "433" {
+        433
+    } else if v == "434" {
+        434
+    } else if v == "435" {
+        435
+    } else if v == "436" {
+        436
+    } else if v == "437" {
+        437
+    } else if v == "438" {
+        438
+    } else if v == "439" {
+        439
+    } else if v == "440" {
+        440
+    } else if v == "441" {
+        441
+    } else if v == "442" {
+        442
+    } else if v == "443" {
+        443
+    } else if v == "444" {
+        444
+    } else if v == "445" {
+        445
+    } else if v == "446" {
+        446
+    } else if v == "447" {
+        447
+    } else if v == "448" {
+        448
+    } else if v == "449" {
+        449
+    } else if v == "450" {
+        450
+    } else if v == "451" {
+        451
+    } else if v == "452" {
+        452
+    } else if v == "453" {
+        453
+    } else if v == "454" {
+        454
+    } else if v == "455" {
+        455
+    } else if v == "456" {
+        456
+    } else if v == "457" {
+        457
+    } else if v == "458" {
+        458
+    } else if v == "459" {
+        459
+    } else if v == "460" {
+        460
+    } else if v == "461" {
+        461
+    } else if v == "462" {
+        462
+    } else if v == "463" {
+        463
+    } else if v == "464" {
+        464
+    } else if v == "465" {
+        465
+    } else if v == "466" {
+        466
+    } else if v == "467" {
+        467
+    } else if v == "468" {
+        468
+    } else if v == "469" {
+        469
+    } else if v == "470" {
+        470
+    } else if v == "471" {
+        471
+    } else if v == "472" {
+        472
+    } else if v == "473" {
+        473
+    } else if v == "474" {
+        474
+    } else if v == "475" {
+        475
+    } else if v == "476" {
+        476
+    } else if v == "477" {
+        477
+    } else if v == "478" {
+        478
+    } else if v == "479" {
+        479
+    } else if v == "480" {
+        480
+    } else if v == "481" {
+        481
+    } else if v == "482" {
+        482
+    } else if v == "483" {
+        483
+    } else if v == "484" {
+        484
+    } else if v == "485" {
+        485
+    } else if v == "486" {
+        486
+    } else if v == "487" {
+        487
+    } else if v == "488" {
+        488
+    } else if v == "489" {
+        489
+    } else if v == "490" {
+        490
+    } else if v == "491" {
+        491
+    } else if v == "492" {
+        492
+    } else if v == "493" {
+        493
+    } else if v == "494" {
+        494
+    } else if v == "495" {
+        495
+    } else if v == "496" {
+        496
+    } else if v == "497" {
+        497
+    } else if v == "498" {
+        498
+    } else if v == "499" {
+        499
+    } else if v == "500" {
+        500
+    } else if v == "501" {
+        501
+    } else if v == "502" {
+        502
+    } else if v == "503" {
+        503
+    } else if v == "504" {
+        504
+    } else if v == "505" {
+        505
+    } else if v == "506" {
+        506
+    } else if v == "507" {
+        507
+    } else if v == "508" {
+        508
+    } else if v == "509" {
+        509
+    } else if v == "510" {
+        510
+    } else if v == "511" {
+        511
+    } else if v == "512" {
+        512
+    } else if v == "513" {
+        513
+    } else if v == "514" {
+        514
+    } else if v == "515" {
+        515
+    } else if v == "516" {
+        516
+    } else if v == "517" {
+        517
+    } else if v == "518" {
+        518
+    } else if v == "519" {
+        519
+    } else if v == "520" {
+        520
+    } else if v == "521" {
+        521
+    } else if v == "522" {
+        522
+    } else if v == "523" {
+        523
+    } else if v == "524" {
+        524
+    } else if v == "525" {
+        525
+    } else if v == "526" {
+        526
+    } else if v == "527" {
+        527
+    } else if v == "528" {
+        528
+    } else if v == "529" {
+        529
+    } else if v == "530" {
+        530
+    } else if v == "531" {
+        531
+    } else if v == "532" {
+        532
+    } else if v == "533" {
+        533
+    } else if v == "534" {
+        534
+    } else if v == "535" {
+        535
+    } else if v == "536" {
+        536
+    } else if v == "537" {
+        537
+    } else if v == "538" {
+        538
+    } else if v == "539" {
+        539
+    } else if v == "540" {
+        540
+    } else if v == "541" {
+        541
+    } else if v == "542" {
+        542
+    } else if v == "543" {
+        543
+    } else if v == "544" {
+        544
+    } else if v == "545" {
+        545
+    } else if v == "546" {
+        546
+    } else if v == "547" {
+        547
+    } else if v == "548" {
+        548
+    } else if v == "549" {
+        549
+    } else if v == "550" {
+        550
+    } else if v == "551" {
+        551
+    } else if v == "552" {
+        552
+    } else if v == "553" {
+        553
+    } else if v == "554" {
+        554
+    } else if v == "555" {
+        555
+    } else if v == "556" {
+        556
+    } else if v == "557" {
+        557
+    } else if v == "558" {
+        558
+    } else if v == "559" {
+        559
+    } else if v == "560" {
+        560
+    } else if v == "561" {
+        561
+    } else if v == "562" {
+        562
+    } else if v == "563" {
+        563
+    } else if v == "564" {
+        564
+    } else if v == "565" {
+        565
+    } else if v == "566" {
+        566
+    } else if v == "567" {
+        567
+    } else if v == "568" {
+        568
+    } else if v == "569" {
+        569
+    } else if v == "570" {
+        570
+    } else if v == "571" {
+        571
+    } else if v == "572" {
+        572
+    } else if v == "573" {
+        573
+    } else if v == "574" {
+        574
+    } else if v == "575" {
+        575
+    } else if v == "576" {
+        576
+    } else if v == "577" {
+        577
+    } else if v == "578" {
+        578
+    } else if v == "579" {
+        579
+    } else if v == "580" {
+        580
+    } else if v == "581" {
+        581
+    } else if v == "582" {
+        582
+    } else if v == "583" {
+        583
+    } else if v == "584" {
+        584
+    } else if v == "585" {
+        585
+    } else if v == "586" {
+        586
+    } else if v == "587" {
+        587
+    } else if v == "588" {
+        588
+    } else if v == "589" {
+        589
+    } else if v == "590" {
+        590
+    } else if v == "591" {
+        591
+    } else if v == "592" {
+        592
+    } else if v == "593" {
+        593
+    } else if v == "594" {
+        594
+    } else if v == "595" {
+        595
+    } else if v == "596" {
+        596
+    } else if v == "597" {
+        597
+    } else if v == "598" {
+        598
+    } else if v == "599" {
+        599
+    } else if v == "600" {
+        600
+    } else if v == "601" {
+        601
+    } else if v == "602" {
+        602
+    } else if v == "603" {
+        603
+    } else if v == "604" {
+        604
+    } else if v == "605" {
+        605
+    } else if v == "606" {
+        606
+    } else if v == "607" {
+        607
+    } else if v == "608" {
+        608
+    } else if v == "609" {
+        609
+    } else if v == "610" {
+        610
+    } else if v == "611" {
+        611
+    } else if v == "612" {
+        612
+    } else if v == "613" {
+        613
+    } else if v == "614" {
+        614
+    } else if v == "615" {
+        615
+    } else if v == "616" {
+        616
+    } else if v == "617" {
+        617
+    } else if v == "618" {
+        618
+    } else if v == "619" {
+        619
+    } else if v == "620" {
+        620
+    } else if v == "621" {
+        621
+    } else if v == "622" {
+        622
+    } else if v == "623" {
+        623
+    } else if v == "624" {
+        624
+    } else if v == "625" {
+        625
+    } else if v == "626" {
+        626
+    } else if v == "627" {
+        627
+    } else if v == "628" {
+        628
+    } else if v == "629" {
+        629
+    } else if v == "630" {
+        630
+    } else if v == "631" {
+        631
+    } else if v == "632" {
+        632
+    } else if v == "633" {
+        633
+    } else if v == "634" {
+        634
+    } else if v == "635" {
+        635
+    } else if v == "636" {
+        636
+    } else if v == "637" {
+        637
+    } else if v == "638" {
+        638
+    } else if v == "639" {
+        639
+    } else if v == "640" {
+        640
+    } else if v == "641" {
+        641
+    } else if v == "642" {
+        642
+    } else if v == "643" {
+        643
+    } else if v == "644" {
+        644
+    } else if v == "645" {
+        645
+    } else if v == "646" {
+        646
+    } else if v == "647" {
+        647
+    } else if v == "648" {
+        648
+    } else if v == "649" {
+        649
+    } else if v == "650" {
+        650
+    } else if v == "651" {
+        651
+    } else if v == "652" {
+        652
+    } else if v == "653" {
+        653
+    } else if v == "654" {
+        654
+    } else if v == "655" {
+        655
+    } else if v == "656" {
+        656
+    } else if v == "657" {
+        657
+    } else if v == "658" {
+        658
+    } else if v == "659" {
+        659
+    } else if v == "660" {
+        660
+    } else if v == "661" {
+        661
+    } else if v == "662" {
+        662
+    } else if v == "663" {
+        663
+    } else if v == "664" {
+        664
+    } else if v == "665" {
+        665
+    } else if v == "666" {
+        666
+    } else if v == "667" {
+        667
+    } else if v == "668" {
+        668
+    } else if v == "669" {
+        669
+    } else if v == "670" {
+        670
+    } else if v == "671" {
+        671
+    } else if v == "672" {
+        672
+    } else if v == "673" {
+        673
+    } else if v == "674" {
+        674
+    } else if v == "675" {
+        675
+    } else if v == "676" {
+        676
+    } else if v == "677" {
+        677
+    } else if v == "678" {
+        678
+    } else if v == "679" {
+        679
+    } else if v == "680" {
+        680
+    } else if v == "681" {
+        681
+    } else if v == "682" {
+        682
+    } else if v == "683" {
+        683
+    } else if v == "684" {
+        684
+    } else if v == "685" {
+        685
+    } else if v == "686" {
+        686
+    } else if v == "687" {
+        687
+    } else if v == "688" {
+        688
+    } else if v == "689" {
+        689
+    } else if v == "690" {
+        690
+    } else if v == "691" {
+        691
+    } else if v == "692" {
+        692
+    } else if v == "693" {
+        693
+    } else if v == "694" {
+        694
+    } else if v == "695" {
+        695
+    } else if v == "696" {
+        696
+    } else if v == "697" {
+        697
+    } else if v == "698" {
+        698
+    } else if v == "699" {
+        699
+    } else if v == "700" {
+        700
+    } else if v == "701" {
+        701
+    } else if v == "702" {
+        702
+    } else if v == "703" {
+        703
+    } else if v == "704" {
+        704
+    } else if v == "705" {
+        705
+    } else if v == "706" {
+        706
+    } else if v == "707" {
+        707
+    } else if v == "708" {
+        708
+    } else if v == "709" {
+        709
+    } else if v == "710" {
+        710
+    } else if v == "711" {
+        711
+    } else if v == "712" {
+        712
+    } else if v == "713" {
+        713
+    } else if v == "714" {
+        714
+    } else if v == "715" {
+        715
+    } else if v == "716" {
+        716
+    } else if v == "717" {
+        717
+    } else if v == "718" {
+        718
+    } else if v == "719" {
+        719
+    } else if v == "720" {
+        720
+    } else if v == "721" {
+        721
+    } else if v == "722" {
+        722
+    } else if v == "723" {
+        723
+    } else if v == "724" {
+        724
+    } else if v == "725" {
+        725
+    } else if v == "726" {
+        726
+    } else if v == "727" {
+        727
+    } else if v == "728" {
+        728
+    } else if v == "729" {
+        729
+    } else if v == "730" {
+        730
+    } else if v == "731" {
+        731
+    } else if v == "732" {
+        732
+    } else if v == "733" {
+        733
+    } else if v == "734" {
+        734
+    } else if v == "735" {
+        735
+    } else if v == "736" {
+        736
+    } else if v == "737" {
+        737
+    } else if v == "738" {
+        738
+    } else if v == "739" {
+        739
+    } else if v == "740" {
+        740
+    } else if v == "741" {
+        741
+    } else if v == "742" {
+        742
+    } else if v == "743" {
+        743
+    } else if v == "744" {
+        744
+    } else if v == "745" {
+        745
+    } else if v == "746" {
+        746
+    } else if v == "747" {
+        747
+    } else if v == "748" {
+        748
+    } else if v == "749" {
+        749
+    } else if v == "750" {
+        750
+    } else if v == "751" {
+        751
+    } else if v == "752" {
+        752
+    } else if v == "753" {
+        753
+    } else if v == "754" {
+        754
+    } else if v == "755" {
+        755
+    } else if v == "756" {
+        756
+    } else if v == "757" {
+        757
+    } else if v == "758" {
+        758
+    } else if v == "759" {
+        759
+    } else if v == "760" {
+        760
+    } else if v == "761" {
+        761
+    } else if v == "762" {
+        762
+    } else if v == "763" {
+        763
+    } else if v == "764" {
+        764
+    } else if v == "765" {
+        765
+    } else if v == "766" {
+        766
+    } else if v == "767" {
+        767
+    } else if v == "768" {
+        768
+    } else if v == "769" {
+        769
+    } else if v == "770" {
+        770
+    } else if v == "771" {
+        771
+    } else if v == "772" {
+        772
+    } else if v == "773" {
+        773
+    } else if v == "774" {
+        774
+    } else if v == "775" {
+        775
+    } else if v == "776" {
+        776
+    } else if v == "777" {
+        777
+    } else if v == "778" {
+        778
+    } else if v == "779" {
+        779
+    } else if v == "780" {
+        780
+    } else if v == "781" {
+        781
+    } else if v == "782" {
+        782
+    } else if v == "783" {
+        783
+    } else if v == "784" {
+        784
+    } else if v == "785" {
+        785
+    } else if v == "786" {
+        786
+    } else if v == "787" {
+        787
+    } else if v == "788" {
+        788
+    } else if v == "789" {
+        789
+    } else if v == "790" {
+        790
+    } else if v == "791" {
+        791
+    } else if v == "792" {
+        792
+    } else if v == "793" {
+        793
+    } else if v == "794" {
+        794
+    } else if v == "795" {
+        795
+    } else if v == "796" {
+        796
+    } else if v == "797" {
+        797
+    } else if v == "798" {
+        798
+    } else if v == "799" {
+        799
+    } else if v == "800" {
+        800
+    } else if v == "801" {
+        801
+    } else if v == "802" {
+        802
+    } else if v == "803" {
+        803
+    } else if v == "804" {
+        804
+    } else if v == "805" {
+        805
+    } else if v == "806" {
+        806
+    } else if v == "807" {
+        807
+    } else if v == "808" {
+        808
+    } else if v == "809" {
+        809
+    } else if v == "810" {
+        810
+    } else if v == "811" {
+        811
+    } else if v == "812" {
+        812
+    } else if v == "813" {
+        813
+    } else if v == "814" {
+        814
+    } else if v == "815" {
+        815
+    } else if v == "816" {
+        816
+    } else if v == "817" {
+        817
+    } else if v == "818" {
+        818
+    } else if v == "819" {
+        819
+    } else if v == "820" {
+        820
+    } else if v == "821" {
+        821
+    } else if v == "822" {
+        822
+    } else if v == "823" {
+        823
+    } else if v == "824" {
+        824
+    } else if v == "825" {
+        825
+    } else if v == "826" {
+        826
+    } else if v == "827" {
+        827
+    } else if v == "828" {
+        828
+    } else if v == "829" {
+        829
+    } else if v == "830" {
+        830
+    } else if v == "831" {
+        831
+    } else if v == "832" {
+        832
+    } else if v == "833" {
+        833
+    } else if v == "834" {
+        834
+    } else if v == "835" {
+        835
+    } else if v == "836" {
+        836
+    } else if v == "837" {
+        837
+    } else if v == "838" {
+        838
+    } else if v == "839" {
+        839
+    } else if v == "840" {
+        840
+    } else if v == "841" {
+        841
+    } else if v == "842" {
+        842
+    } else if v == "843" {
+        843
+    } else if v == "844" {
+        844
+    } else if v == "845" {
+        845
+    } else if v == "846" {
+        846
+    } else if v == "847" {
+        847
+    } else if v == "848" {
+        848
+    } else if v == "849" {
+        849
+    } else if v == "850" {
+        850
+    } else if v == "851" {
+        851
+    } else if v == "852" {
+        852
+    } else if v == "853" {
+        853
+    } else if v == "854" {
+        854
+    } else if v == "855" {
+        855
+    } else if v == "856" {
+        856
+    } else if v == "857" {
+        857
+    } else if v == "858" {
+        858
+    } else if v == "859" {
+        859
+    } else if v == "860" {
+        860
+    } else if v == "861" {
+        861
+    } else if v == "862" {
+        862
+    } else if v == "863" {
+        863
+    } else if v == "864" {
+        864
+    } else if v == "865" {
+        865
+    } else if v == "866" {
+        866
+    } else if v == "867" {
+        867
+    } else if v == "868" {
+        868
+    } else if v == "869" {
+        869
+    } else if v == "870" {
+        870
+    } else if v == "871" {
+        871
+    } else if v == "872" {
+        872
+    } else if v == "873" {
+        873
+    } else if v == "874" {
+        874
+    } else if v == "875" {
+        875
+    } else if v == "876" {
+        876
+    } else if v == "877" {
+        877
+    } else if v == "878" {
+        878
+    } else if v == "879" {
+        879
+    } else if v == "880" {
+        880
+    } else if v == "881" {
+        881
+    } else if v == "882" {
+        882
+    } else if v == "883" {
+        883
+    } else if v == "884" {
+        884
+    } else if v == "885" {
+        885
+    } else if v == "886" {
+        886
+    } else if v == "887" {
+        887
+    } else if v == "888" {
+        888
+    } else if v == "889" {
+        889
+    } else if v == "890" {
+        890
+    } else if v == "891" {
+        891
+    } else if v == "892" {
+        892
+    } else if v == "893" {
+        893
+    } else if v == "894" {
+        894
+    } else if v == "895" {
+        895
+    } else if v == "896" {
+        896
+    } else if v == "897" {
+        897
+    } else if v == "898" {
+        898
+    } else if v == "899" {
+        899
+    } else if v == "900" {
+        900
+    } else if v == "901" {
+        901
+    } else if v == "902" {
+        902
+    } else if v == "903" {
+        903
+    } else if v == "904" {
+        904
+    } else if v == "905" {
+        905
+    } else if v == "906" {
+        906
+    } else if v == "907" {
+        907
+    } else if v == "908" {
+        908
+    } else if v == "909" {
+        909
+    } else if v == "910" {
+        910
+    } else if v == "911" {
+        911
+    } else if v == "912" {
+        912
+    } else if v == "913" {
+        913
+    } else if v == "914" {
+        914
+    } else if v == "915" {
+        915
+    } else if v == "916" {
+        916
+    } else if v == "917" {
+        917
+    } else if v == "918" {
+        918
+    } else if v == "919" {
+        919
+    } else if v == "920" {
+        920
+    } else if v == "921" {
+        921
+    } else if v == "922" {
+        922
+    } else if v == "923" {
+        923
+    } else if v == "924" {
+        924
+    } else if v == "925" {
+        925
+    } else if v == "926" {
+        926
+    } else if v == "927" {
+        927
+    } else if v == "928" {
+        928
+    } else if v == "929" {
+        929
+    } else if v == "930" {
+        930
+    } else if v == "931" {
+        931
+    } else if v == "932" {
+        932
+    } else if v == "933" {
+        933
+    } else if v == "934" {
+        934
+    } else if v == "935" {
+        935
+    } else if v == "936" {
+        936
+    } else if v == "937" {
+        937
+    } else if v == "938" {
+        938
+    } else if v == "939" {
+        939
+    } else if v == "940" {
+        940
+    } else if v == "941" {
+        941
+    } else if v == "942" {
+        942
+    } else if v == "943" {
+        943
+    } else if v == "944" {
+        944
+    } else if v == "945" {
+        945
+    } else if v == "946" {
+        946
+    } else if v == "947" {
+        947
+    } else if v == "948" {
+        948
+    } else if v == "949" {
+        949
+    } else if v == "950" {
+        950
+    } else if v == "951" {
+        951
+    } else if v == "952" {
+        952
+    } else if v == "953" {
+        953
+    } else if v == "954" {
+        954
+    } else if v == "955" {
+        955
+    } else if v == "956" {
+        956
+    } else if v == "957" {
+        957
+    } else if v == "958" {
+        958
+    } else if v == "959" {
+        959
+    } else if v == "960" {
+        960
+    } else if v == "961" {
+        961
+    } else if v == "962" {
+        962
+    } else if v == "963" {
+        963
+    } else if v == "964" {
+        964
+    } else if v == "965" {
+        965
+    } else if v == "966" {
+        966
+    } else if v == "967" {
+        967
+    } else if v == "968" {
+        968
+    } else if v == "969" {
+        969
+    } else if v == "970" {
+        970
+    } else if v == "971" {
+        971
+    } else if v == "972" {
+        972
+    } else if v == "973" {
+        973
+    } else if v == "974" {
+        974
+    } else if v == "975" {
+        975
+    } else if v == "976" {
+        976
+    } else if v == "977" {
+        977
+    } else if v == "978" {
+        978
+    } else if v == "979" {
+        979
+    } else if v == "980" {
+        980
+    } else if v == "981" {
+        981
+    } else if v == "982" {
+        982
+    } else if v == "983" {
+        983
+    } else if v == "984" {
+        984
+    } else if v == "985" {
+        985
+    } else if v == "986" {
+        986
+    } else if v == "987" {
+        987
+    } else if v == "988" {
+        988
+    } else if v == "989" {
+        989
+    } else if v == "990" {
+        990
+    } else if v == "991" {
+        991
+    } else if v == "992" {
+        992
+    } else if v == "993" {
+        993
+    } else if v == "994" {
+        994
+    } else if v == "995" {
+        995
+    } else if v == "996" {
+        996
+    } else if v == "997" {
+        997
+    } else if v == "998" {
+        998
+    } else if v == "999" {
+        999
+    } else if v == "1000" {
+        1000
+    } else if v == "1001" {
+        1001
+    } else if v == "1002" {
+        1002
+    } else if v == "1003" {
+        1003
+    } else if v == "1004" {
+        1004
+    } else if v == "1005" {
+        1005
+    } else if v == "1006" {
+        1006
+    } else if v == "1007" {
+        1007
+    } else if v == "1008" {
+        1008
+    } else if v == "1009" {
+        1009
+    } else if v == "1010" {
+        1010
+    } else if v == "1011" {
+        1011
+    } else if v == "1012" {
+        1012
+    } else if v == "1013" {
+        1013
+    } else if v == "1014" {
+        1014
+    } else if v == "1015" {
+        1015
+    } else if v == "1016" {
+        1016
+    } else if v == "1017" {
+        1017
+    } else if v == "1018" {
+        1018
+    } else if v == "1019" {
+        1019
+    } else if v == "1020" {
+        1020
+    } else if v == "1021" {
+        1021
+    } else if v == "1022" {
+        1022
+    } else if v == "1023" {
+        1023
+    } else if v == "1024" {
+        1024
+    } else if v == "1025" {
+        1025
+    } else if v == "1026" {
+        1026
+    } else if v == "1027" {
+        1027
+    } else if v == "1028" {
+        1028
+    } else if v == "1029" {
+        1029
+    } else if v == "1030" {
+        1030
+    } else if v == "1031" {
+        1031
+    } else if v == "1032" {
+        1032
+    } else if v == "1033" {
+        1033
+    } else if v == "1034" {
+        1034
+    } else if v == "1035" {
+        1035
+    } else if v == "1036" {
+        1036
+    } else if v == "1037" {
+        1037
+    } else if v == "1038" {
+        1038
+    } else if v == "1039" {
+        1039
+    } else if v == "1040" {
+        1040
+    } else if v == "1041" {
+        1041
+    } else if v == "1042" {
+        1042
+    } else if v == "1043" {
+        1043
+    } else if v == "1044" {
+        1044
+    } else if v == "1045" {
+        1045
+    } else if v == "1046" {
+        1046
+    } else if v == "1047" {
+        1047
+    } else if v == "1048" {
+        1048
+    } else if v == "1049" {
+        1049
+    } else if v == "1050" {
+        1050
+    } else if v == "1051" {
+        1051
+    } else if v == "1052" {
+        1052
+    } else if v == "1053" {
+        1053
+    } else if v == "1054" {
+        1054
+    } else if v == "1055" {
+        1055
+    } else if v == "1056" {
+        1056
+    } else if v == "1057" {
+        1057
+    } else if v == "1058" {
+        1058
+    } else if v == "1059" {
+        1059
+    } else if v == "1060" {
+        1060
+    } else if v == "1061" {
+        1061
+    } else if v == "1062" {
+        1062
+    } else if v == "1063" {
+        1063
+    } else if v == "1064" {
+        1064
+    } else if v == "1065" {
+        1065
+    } else if v == "1066" {
+        1066
+    } else if v == "1067" {
+        1067
+    } else if v == "1068" {
+        1068
+    } else if v == "1069" {
+        1069
+    } else if v == "1070" {
+        1070
+    } else if v == "1071" {
+        1071
+    } else if v == "1072" {
+        1072
+    } else if v == "1073" {
+        1073
+    } else if v == "1074" {
+        1074
+    } else if v == "1075" {
+        1075
+    } else if v == "1076" {
+        1076
+    } else if v == "1077" {
+        1077
+    } else if v == "1078" {
+        1078
+    } else if v == "1079" {
+        1079
+    } else if v == "1080" {
+        1080
+    } else if v == "1081" {
+        1081
+    } else if v == "1082" {
+        1082
+    } else if v == "1083" {
+        1083
+    } else if v == "1084" {
+        1084
+    } else if v == "1085" {
+        1085
+    } else if v == "1086" {
+        1086
+    } else if v == "1087" {
+        1087
+    } else if v == "1088" {
+        1088
+    } else if v == "1089" {
+        1089
+    } else if v == "1090" {
+        1090
+    } else if v == "1091" {
+        1091
+    } else if v == "1092" {
+        1092
+    } else if v == "1093" {
+        1093
+    } else if v == "1094" {
+        1094
+    } else if v == "1095" {
+        1095
+    } else if v == "1096" {
+        1096
+    } else if v == "1097" {
+        1097
+    } else if v == "1098" {
+        1098
+    } else if v == "1099" {
+        1099
+    } else if v == "1100" {
+        1100
+    } else if v == "1101" {
+        1101
+    } else if v == "1102" {
+        1102
+    } else if v == "1103" {
+        1103
+    } else if v == "1104" {
+        1104
+    } else if v == "1105" {
+        1105
+    } else if v == "1106" {
+        1106
+    } else if v == "1107" {
+        1107
+    } else if v == "1108" {
+        1108
+    } else if v == "1109" {
+        1109
+    } else if v == "1110" {
+        1110
+    } else if v == "1111" {
+        1111
+    } else if v == "1112" {
+        1112
+    } else if v == "1113" {
+        1113
+    } else if v == "1114" {
+        1114
+    } else if v == "1115" {
+        1115
+    } else if v == "1116" {
+        1116
+    } else if v == "1117" {
+        1117
+    } else if v == "1118" {
+        1118
+    } else if v == "1119" {
+        1119
+    } else if v == "1120" {
+        1120
+    } else if v == "1121" {
+        1121
+    } else if v == "1122" {
+        1122
+    } else if v == "1123" {
+        1123
+    } else if v == "1124" {
+        1124
+    } else if v == "1125" {
+        1125
+    } else if v == "1126" {
+        1126
+    } else if v == "1127" {
+        1127
+    } else if v == "1128" {
+        1128
+    } else if v == "1129" {
+        1129
+    } else if v == "1130" {
+        1130
+    } else if v == "1131" {
+        1131
+    } else if v == "1132" {
+        1132
+    } else if v == "1133" {
+        1133
+    } else if v == "1134" {
+        1134
+    } else if v == "1135" {
+        1135
+    } else if v == "1136" {
+        1136
+    } else if v == "1137" {
+        1137
+    } else if v == "1138" {
+        1138
+    } else if v == "1139" {
+        1139
+    } else if v == "1140" {
+        1140
+    } else if v == "1141" {
+        1141
+    } else if v == "1142" {
+        1142
+    } else if v == "1143" {
+        1143
+    } else if v == "1144" {
+        1144
+    } else if v == "1145" {
+        1145
+    } else if v == "1146" {
+        1146
+    } else if v == "1147" {
+        1147
+    } else if v == "1148" {
+        1148
+    } else if v == "1149" {
+        1149
+    } else if v == "1150" {
+        1150
+    } else if v == "1151" {
+        1151
+    } else if v == "1152" {
+        1152
+    } else if v == "1153" {
+        1153
+    } else if v == "1154" {
+        1154
+    } else if v == "1155" {
+        1155
+    } else if v == "1156" {
+        1156
+    } else if v == "1157" {
+        1157
+    } else if v == "1158" {
+        1158
+    } else if v == "1159" {
+        1159
+    } else if v == "1160" {
+        1160
+    } else if v == "1161" {
+        1161
+    } else if v == "1162" {
+        1162
+    } else if v == "1163" {
+        1163
+    } else if v == "1164" {
+        1164
+    } else if v == "1165" {
+        1165
+    } else if v == "1166" {
+        1166
+    } else if v == "1167" {
+        1167
+    } else if v == "1168" {
+        1168
+    } else if v == "1169" {
+        1169
+    } else if v == "1170" {
+        1170
+    } else if v == "1171" {
+        1171
+    } else if v == "1172" {
+        1172
+    } else if v == "1173" {
+        1173
+    } else if v == "1174" {
+        1174
+    } else if v == "1175" {
+        1175
+    } else if v == "1176" {
+        1176
+    } else if v == "1177" {
+        1177
+    } else if v == "1178" {
+        1178
+    } else if v == "1179" {
+        1179
+    } else if v == "1180" {
+        1180
+    } else if v == "1181" {
+        1181
+    } else if v == "1182" {
+        1182
+    } else if v == "1183" {
+        1183
+    } else if v == "1184" {
+        1184
+    } else if v == "1185" {
+        1185
+    } else if v == "1186" {
+        1186
+    } else if v == "1187" {
+        1187
+    } else if v == "1188" {
+        1188
+    } else if v == "1189" {
+        1189
+    } else if v == "1190" {
+        1190
+    } else if v == "1191" {
+        1191
+    } else if v == "1192" {
+        1192
+    } else if v == "1193" {
+        1193
+    } else if v == "1194" {
+        1194
+    } else if v == "1195" {
+        1195
+    } else if v == "1196" {
+        1196
+    } else if v == "1197" {
+        1197
+    } else if v == "1198" {
+        1198
+    } else if v == "1199" {
+        1199
+    } else if v == "1200" {
+        1200
+    } else if v == "1201" {
+        1201
+    } else if v == "1202" {
+        1202
+    } else if v == "1203" {
+        1203
+    } else if v == "1204" {
+        1204
+    } else if v == "1205" {
+        1205
+    } else if v == "1206" {
+        1206
+    } else if v == "1207" {
+        1207
+    } else if v == "1208" {
+        1208
+    } else if v == "1209" {
+        1209
+    } else if v == "1210" {
+        1210
+    } else if v == "1211" {
+        1211
+    } else if v == "1212" {
+        1212
+    } else if v == "1213" {
+        1213
+    } else if v == "1214" {
+        1214
+    } else if v == "1215" {
+        1215
+    } else if v == "1216" {
+        1216
+    } else if v == "1217" {
+        1217
+    } else if v == "1218" {
+        1218
+    } else if v == "1219" {
+        1219
+    } else if v == "1220" {
+        1220
+    } else if v == "1221" {
+        1221
+    } else if v == "1222" {
+        1222
+    } else if v == "1223" {
+        1223
+    } else if v == "1224" {
+        1224
+    } else if v == "1225" {
+        1225
+    } else if v == "1226" {
+        1226
+    } else if v == "1227" {
+        1227
+    } else if v == "1228" {
+        1228
+    } else if v == "1229" {
+        1229
+    } else if v == "1230" {
+        1230
+    } else if v == "1231" {
+        1231
+    } else if v == "1232" {
+        1232
+    } else if v == "1233" {
+        1233
+    } else if v == "1234" {
+        1234
+    } else if v == "1235" {
+        1235
+    } else if v == "1236" {
+        1236
+    } else if v == "1237" {
+        1237
+    } else if v == "1238" {
+        1238
+    } else if v == "1239" {
+        1239
+    } else if v == "1240" {
+        1240
+    } else if v == "1241" {
+        1241
+    } else if v == "1242" {
+        1242
+    } else if v == "1243" {
+        1243
+    } else if v == "1244" {
+        1244
+    } else if v == "1245" {
+        1245
+    } else if v == "1246" {
+        1246
+    } else if v == "1247" {
+        1247
+    } else if v == "1248" {
+        1248
+    } else if v == "1249" {
+        1249
+    } else if v == "1250" {
+        1250
+    } else if v == "1251" {
+        1251
+    } else if v == "1252" {
+        1252
+    } else if v == "1253" {
+        1253
+    } else if v == "1254" {
+        1254
+    } else if v == "1255" {
+        1255
+    } else if v == "1256" {
+        1256
+    } else if v == "1257" {
+        1257
+    } else if v == "1258" {
+        1258
+    } else if v == "1259" {
+        1259
+    } else if v == "1260" {
+        1260
+    } else if v == "1261" {
+        1261
+    } else if v == "1262" {
+        1262
+    } else if v == "1263" {
+        1263
+    } else if v == "1264" {
+        1264
+    } else if v == "1265" {
+        1265
+    } else if v == "1266" {
+        1266
+    } else if v == "1267" {
+        1267
+    } else if v == "1268" {
+        1268
+    } else if v == "1269" {
+        1269
+    } else if v == "1270" {
+        1270
+    } else if v == "1271" {
+        1271
+    } else if v == "1272" {
+        1272
+    } else if v == "1273" {
+        1273
+    } else if v == "1274" {
+        1274
+    } else if v == "1275" {
+        1275
+    } else if v == "1276" {
+        1276
+    } else if v == "1277" {
+        1277
+    } else if v == "1278" {
+        1278
+    } else if v == "1279" {
+        1279
+    } else if v == "1280" {
+        1280
+    } else if v == "1281" {
+        1281
+    } else if v == "1282" {
+        1282
+    } else if v == "1283" {
+        1283
+    } else if v == "1284" {
+        1284
+    } else if v == "1285" {
+        1285
+    } else if v == "1286" {
+        1286
+    } else if v == "1287" {
+        1287
+    } else if v == "1288" {
+        1288
+    } else if v == "1289" {
+        1289
+    } else if v == "1290" {
+        1290
+    } else if v == "1291" {
+        1291
+    } else if v == "1292" {
+        1292
+    } else if v == "1293" {
+        1293
+    } else if v == "1294" {
+        1294
+    } else if v == "1295" {
+        1295
+    } else if v == "1296" {
+        1296
+    } else if v == "1297" {
+        1297
+    } else if v == "1298" {
+        1298
+    } else if v == "1299" {
+        1299
+    } else if v == "1300" {
+        1300
+    } else if v == "1301" {
+        1301
+    } else if v == "1302" {
+        1302
+    } else if v == "1303" {
+        1303
+    } else if v == "1304" {
+        1304
+    } else if v == "1305" {
+        1305
+    } else if v == "1306" {
+        1306
+    } else if v == "1307" {
+        1307
+    } else if v == "1308" {
+        1308
+    } else if v == "1309" {
+        1309
+    } else if v == "1310" {
+        1310
+    } else if v == "1311" {
+        1311
+    } else if v == "1312" {
+        1312
+    } else if v == "1313" {
+        1313
+    } else if v == "1314" {
+        1314
+    } else if v == "1315" {
+        1315
+    } else if v == "1316" {
+        1316
+    } else if v == "1317" {
+        1317
+    } else if v == "1318" {
+        1318
+    } else if v == "1319" {
+        1319
+    } else if v == "1320" {
+        1320
+    } else if v == "1321" {
+        1321
+    } else if v == "1322" {
+        1322
+    } else if v == "1323" {
+        1323
+    } else if v == "1324" {
+        1324
+    } else if v == "1325" {
+        1325
+    } else if v == "1326" {
+        1326
+    } else if v == "1327" {
+        1327
+    } else if v == "1328" {
+        1328
+    } else if v == "1329" {
+        1329
+    } else if v == "1330" {
+        1330
+    } else if v == "1331" {
+        1331
+    } else if v == "1332" {
+        1332
+    } else if v == "1333" {
+        1333
+    } else if v == "1334" {
+        1334
+    } else if v == "1335" {
+        1335
+    } else if v == "1336" {
+        1336
+    } else if v == "1337" {
+        1337
+    } else if v == "1338" {
+        1338
+    } else if v == "1339" {
+        1339
+    } else if v == "1340" {
+        1340
+    } else if v == "1341" {
+        1341
+    } else if v == "1342" {
+        1342
+    } else if v == "1343" {
+        1343
+    } else if v == "1344" {
+        1344
+    } else if v == "1345" {
+        1345
+    } else if v == "1346" {
+        1346
+    } else if v == "1347" {
+        1347
+    } else if v == "1348" {
+        1348
+    } else if v == "1349" {
+        1349
+    } else if v == "1350" {
+        1350
+    } else if v == "1351" {
+        1351
+    } else if v == "1352" {
+        1352
+    } else if v == "1353" {
+        1353
+    } else if v == "1354" {
+        1354
+    } else if v == "1355" {
+        1355
+    } else if v == "1356" {
+        1356
+    } else if v == "1357" {
+        1357
+    } else if v == "1358" {
+        1358
+    } else if v == "1359" {
+        1359
+    } else if v == "1360" {
+        1360
+    } else if v == "1361" {
+        1361
+    } else if v == "1362" {
+        1362
+    } else if v == "1363" {
+        1363
+    } else if v == "1364" {
+        1364
+    } else if v == "1365" {
+        1365
+    } else if v == "1366" {
+        1366
+    } else if v == "1367" {
+        1367
+    } else if v == "1368" {
+        1368
+    } else if v == "1369" {
+        1369
+    } else if v == "1370" {
+        1370
+    } else if v == "1371" {
+        1371
+    } else if v == "1372" {
+        1372
+    } else if v == "1373" {
+        1373
+    } else if v == "1374" {
+        1374
+    } else if v == "1375" {
+        1375
+    } else if v == "1376" {
+        1376
+    } else if v == "1377" {
+        1377
+    } else if v == "1378" {
+        1378
+    } else if v == "1379" {
+        1379
+    } else if v == "1380" {
+        1380
+    } else if v == "1381" {
+        1381
+    } else if v == "1382" {
+        1382
+    } else if v == "1383" {
+        1383
+    } else if v == "1384" {
+        1384
+    } else if v == "1385" {
+        1385
+    } else if v == "1386" {
+        1386
+    } else if v == "1387" {
+        1387
+    } else if v == "1388" {
+        1388
+    } else if v == "1389" {
+        1389
+    } else if v == "1390" {
+        1390
+    } else if v == "1391" {
+        1391
+    } else if v == "1392" {
+        1392
+    } else if v == "1393" {
+        1393
+    } else if v == "1394" {
+        1394
+    } else if v == "1395" {
+        1395
+    } else if v == "1396" {
+        1396
+    } else if v == "1397" {
+        1397
+    } else if v == "1398" {
+        1398
+    } else if v == "1399" {
+        1399
+    } else if v == "1400" {
+        1400
+    } else if v == "1401" {
+        1401
+    } else if v == "1402" {
+        1402
+    } else if v == "1403" {
+        1403
+    } else if v == "1404" {
+        1404
+    } else if v == "1405" {
+        1405
+    } else if v == "1406" {
+        1406
+    } else if v == "1407" {
+        1407
+    } else if v == "1408" {
+        1408
+    } else if v == "1409" {
+        1409
+    } else if v == "1410" {
+        1410
+    } else if v == "1411" {
+        1411
+    } else if v == "1412" {
+        1412
+    } else if v == "1413" {
+        1413
+    } else if v == "1414" {
+        1414
+    } else if v == "1415" {
+        1415
+    } else if v == "1416" {
+        1416
+    } else if v == "1417" {
+        1417
+    } else if v == "1418" {
+        1418
+    } else if v == "1419" {
+        1419
+    } else if v == "1420" {
+        1420
+    } else if v == "1421" {
+        1421
+    } else if v == "1422" {
+        1422
+    } else if v == "1423" {
+        1423
+    } else if v == "1424" {
+        1424
+    } else if v == "1425" {
+        1425
+    } else if v == "1426" {
+        1426
+    } else if v == "1427" {
+        1427
+    } else if v == "1428" {
+        1428
+    } else if v == "1429" {
+        1429
+    } else if v == "1430" {
+        1430
+    } else if v == "1431" {
+        1431
+    } else if v == "1432" {
+        1432
+    } else if v == "1433" {
+        1433
+    } else if v == "1434" {
+        1434
+    } else if v == "1435" {
+        1435
+    } else if v == "1436" {
+        1436
+    } else if v == "1437" {
+        1437
+    } else if v == "1438" {
+        1438
+    } else if v == "1439" {
+        1439
+    } else if v == "1440" {
+        1440
+    } else if v == "1441" {
+        1441
+    } else if v == "1442" {
+        1442
+    } else if v == "1443" {
+        1443
+    } else if v == "1444" {
+        1444
+    } else if v == "1445" {
+        1445
+    } else if v == "1446" {
+        1446
+    } else if v == "1447" {
+        1447
+    } else if v == "1448" {
+        1448
+    } else if v == "1449" {
+        1449
+    } else if v == "1450" {
+        1450
+    } else if v == "1451" {
+        1451
+    } else if v == "1452" {
+        1452
+    } else if v == "1453" {
+        1453
+    } else if v == "1454" {
+        1454
+    } else if v == "1455" {
+        1455
+    } else if v == "1456" {
+        1456
+    } else if v == "1457" {
+        1457
+    } else if v == "1458" {
+        1458
+    } else if v == "1459" {
+        1459
+    } else if v == "1460" {
+        1460
+    } else if v == "1461" {
+        1461
+    } else if v == "1462" {
+        1462
+    } else if v == "1463" {
+        1463
+    } else if v == "1464" {
+        1464
+    } else if v == "1465" {
+        1465
+    } else if v == "1466" {
+        1466
+    } else if v == "1467" {
+        1467
+    } else if v == "1468" {
+        1468
+    } else if v == "1469" {
+        1469
+    } else if v == "1470" {
+        1470
+    } else if v == "1471" {
+        1471
+    } else if v == "1472" {
+        1472
+    } else if v == "1473" {
+        1473
+    } else if v == "1474" {
+        1474
+    } else if v == "1475" {
+        1475
+    } else if v == "1476" {
+        1476
+    } else if v == "1477" {
+        1477
+    } else if v == "1478" {
+        1478
+    } else if v == "1479" {
+        1479
+    } else if v == "1480" {
+        1480
+    } else if v == "1481" {
+        1481
+    } else if v == "1482" {
+        1482
+    } else if v == "1483" {
+        1483
+    } else if v == "1484" {
+        1484
+    } else if v == "1485" {
+        1485
+    } else if v == "1486" {
+        1486
+    } else if v == "1487" {
+        1487
+    } else if v == "1488" {
+        1488
+    } else if v == "1489" {
+        1489
+    } else if v == "1490" {
+        1490
+    } else if v == "1491" {
+        1491
+    } else if v == "1492" {
+        1492
+    } else if v == "1493" {
+        1493
+    } else if v == "1494" {
+        1494
+    } else if v == "1495" {
+        1495
+    } else if v == "1496" {
+        1496
+    } else if v == "1497" {
+        1497
+    } else if v == "1498" {
+        1498
+    } else if v == "1499" {
+        1499
+    } else if v == "1500" {
+        1500
+    } else if v == "1501" {
+        1501
+    } else if v == "1502" {
+        1502
+    } else if v == "1503" {
+        1503
+    } else if v == "1504" {
+        1504
+    } else if v == "1505" {
+        1505
+    } else if v == "1506" {
+        1506
+    } else if v == "1507" {
+        1507
+    } else if v == "1508" {
+        1508
+    } else if v == "1509" {
+        1509
+    } else if v == "1510" {
+        1510
+    } else if v == "1511" {
+        1511
+    } else if v == "1512" {
+        1512
+    } else if v == "1513" {
+        1513
+    } else if v == "1514" {
+        1514
+    } else if v == "1515" {
+        1515
+    } else if v == "1516" {
+        1516
+    } else if v == "1517" {
+        1517
+    } else if v == "1518" {
+        1518
+    } else if v == "1519" {
+        1519
+    } else if v == "1520" {
+        1520
+    } else if v == "1521" {
+        1521
+    } else if v == "1522" {
+        1522
+    } else if v == "1523" {
+        1523
+    } else if v == "1524" {
+        1524
+    } else if v == "1525" {
+        1525
+    } else if v == "1526" {
+        1526
+    } else if v == "1527" {
+        1527
+    } else if v == "1528" {
+        1528
+    } else if v == "1529" {
+        1529
+    } else if v == "1530" {
+        1530
+    } else if v == "1531" {
+        1531
+    } else if v == "1532" {
+        1532
+    } else if v == "1533" {
+        1533
+    } else if v == "1534" {
+        1534
+    } else if v == "1535" {
+        1535
+    } else if v == "1536" {
+        1536
+    } else if v == "1537" {
+        1537
+    } else if v == "1538" {
+        1538
+    } else if v == "1539" {
+        1539
+    } else if v == "1540" {
+        1540
+    } else if v == "1541" {
+        1541
+    } else if v == "1542" {
+        1542
+    } else if v == "1543" {
+        1543
+    } else if v == "1544" {
+        1544
+    } else if v == "1545" {
+        1545
+    } else if v == "1546" {
+        1546
+    } else if v == "1547" {
+        1547
+    } else if v == "1548" {
+        1548
+    } else if v == "1549" {
+        1549
+    } else if v == "1550" {
+        1550
+    } else if v == "1551" {
+        1551
+    } else if v == "1552" {
+        1552
+    } else if v == "1553" {
+        1553
+    } else if v == "1554" {
+        1554
+    } else if v == "1555" {
+        1555
+    } else if v == "1556" {
+        1556
+    } else if v == "1557" {
+        1557
+    } else if v == "1558" {
+        1558
+    } else if v == "1559" {
+        1559
+    } else if v == "1560" {
+        1560
+    } else if v == "1561" {
+        1561
+    } else if v == "1562" {
+        1562
+    } else if v == "1563" {
+        1563
+    } else if v == "1564" {
+        1564
+    } else if v == "1565" {
+        1565
+    } else if v == "1566" {
+        1566
+    } else if v == "1567" {
+        1567
+    } else if v == "1568" {
+        1568
+    } else if v == "1569" {
+        1569
+    } else if v == "1570" {
+        1570
+    } else if v == "1571" {
+        1571
+    } else if v == "1572" {
+        1572
+    } else if v == "1573" {
+        1573
+    } else if v == "1574" {
+        1574
+    } else if v == "1575" {
+        1575
+    } else if v == "1576" {
+        1576
+    } else if v == "1577" {
+        1577
+    } else if v == "1578" {
+        1578
+    } else if v == "1579" {
+        1579
+    } else if v == "1580" {
+        1580
+    } else if v == "1581" {
+        1581
+    } else if v == "1582" {
+        1582
+    } else if v == "1583" {
+        1583
+    } else if v == "1584" {
+        1584
+    } else if v == "1585" {
+        1585
+    } else if v == "1586" {
+        1586
+    } else if v == "1587" {
+        1587
+    } else if v == "1588" {
+        1588
+    } else if v == "1589" {
+        1589
+    } else if v == "1590" {
+        1590
+    } else if v == "1591" {
+        1591
+    } else if v == "1592" {
+        1592
+    } else if v == "1593" {
+        1593
+    } else if v == "1594" {
+        1594
+    } else if v == "1595" {
+        1595
+    } else if v == "1596" {
+        1596
+    } else if v == "1597" {
+        1597
+    } else if v == "1598" {
+        1598
+    } else if v == "1599" {
+        1599
+    } else if v == "1600" {
+        1600
+    } else if v == "1601" {
+        1601
+    } else if v == "1602" {
+        1602
+    } else if v == "1603" {
+        1603
+    } else if v == "1604" {
+        1604
+    } else if v == "1605" {
+        1605
+    } else if v == "1606" {
+        1606
+    } else if v == "1607" {
+        1607
+    } else if v == "1608" {
+        1608
+    } else if v == "1609" {
+        1609
+    } else if v == "1610" {
+        1610
+    } else if v == "1611" {
+        1611
+    } else if v == "1612" {
+        1612
+    } else if v == "1613" {
+        1613
+    } else if v == "1614" {
+        1614
+    } else if v == "1615" {
+        1615
+    } else if v == "1616" {
+        1616
+    } else if v == "1617" {
+        1617
+    } else if v == "1618" {
+        1618
+    } else if v == "1619" {
+        1619
+    } else if v == "1620" {
+        1620
+    } else if v == "1621" {
+        1621
+    } else if v == "1622" {
+        1622
+    } else if v == "1623" {
+        1623
+    } else if v == "1624" {
+        1624
+    } else if v == "1625" {
+        1625
+    } else if v == "1626" {
+        1626
+    } else if v == "1627" {
+        1627
+    } else if v == "1628" {
+        1628
+    } else if v == "1629" {
+        1629
+    } else if v == "1630" {
+        1630
+    } else if v == "1631" {
+        1631
+    } else if v == "1632" {
+        1632
+    } else if v == "1633" {
+        1633
+    } else if v == "1634" {
+        1634
+    } else if v == "1635" {
+        1635
+    } else if v == "1636" {
+        1636
+    } else if v == "1637" {
+        1637
+    } else if v == "1638" {
+        1638
+    } else if v == "1639" {
+        1639
+    } else if v == "1640" {
+        1640
+    } else if v == "1641" {
+        1641
+    } else if v == "1642" {
+        1642
+    } else if v == "1643" {
+        1643
+    } else if v == "1644" {
+        1644
+    } else if v == "1645" {
+        1645
+    } else if v == "1646" {
+        1646
+    } else if v == "1647" {
+        1647
+    } else if v == "1648" {
+        1648
+    } else if v == "1649" {
+        1649
+    } else if v == "1650" {
+        1650
+    } else if v == "1651" {
+        1651
+    } else if v == "1652" {
+        1652
+    } else if v == "1653" {
+        1653
+    } else if v == "1654" {
+        1654
+    } else if v == "1655" {
+        1655
+    } else if v == "1656" {
+        1656
+    } else if v == "1657" {
+        1657
+    } else if v == "1658" {
+        1658
+    } else if v == "1659" {
+        1659
+    } else if v == "1660" {
+        1660
+    } else if v == "1661" {
+        1661
+    } else if v == "1662" {
+        1662
+    } else if v == "1663" {
+        1663
+    } else if v == "1664" {
+        1664
+    } else if v == "1665" {
+        1665
+    } else if v == "1666" {
+        1666
+    } else if v == "1667" {
+        1667
+    } else if v == "1668" {
+        1668
+    } else if v == "1669" {
+        1669
+    } else if v == "1670" {
+        1670
+    } else if v == "1671" {
+        1671
+    } else if v == "1672" {
+        1672
+    } else if v == "1673" {
+        1673
+    } else if v == "1674" {
+        1674
+    } else if v == "1675" {
+        1675
+    } else if v == "1676" {
+        1676
+    } else if v == "1677" {
+        1677
+    } else if v == "1678" {
+        1678
+    } else if v == "1679" {
+        1679
+    } else if v == "1680" {
+        1680
+    } else if v == "1681" {
+        1681
+    } else if v == "1682" {
+        1682
+    } else if v == "1683" {
+        1683
+    } else if v == "1684" {
+        1684
+    } else if v == "1685" {
+        1685
+    } else if v == "1686" {
+        1686
+    } else if v == "1687" {
+        1687
+    } else if v == "1688" {
+        1688
+    } else if v == "1689" {
+        1689
+    } else if v == "1690" {
+        1690
+    } else if v == "1691" {
+        1691
+    } else if v == "1692" {
+        1692
+    } else if v == "1693" {
+        1693
+    } else if v == "1694" {
+        1694
+    } else if v == "1695" {
+        1695
+    } else if v == "1696" {
+        1696
+    } else if v == "1697" {
+        1697
+    } else if v == "1698" {
+        1698
+    } else if v == "1699" {
+        1699
+    } else if v == "1700" {
+        1700
+    } else if v == "1701" {
+        1701
+    } else if v == "1702" {
+        1702
+    } else if v == "1703" {
+        1703
+    } else if v == "1704" {
+        1704
+    } else if v == "1705" {
+        1705
+    } else if v == "1706" {
+        1706
+    } else if v == "1707" {
+        1707
+    } else if v == "1708" {
+        1708
+    } else if v == "1709" {
+        1709
+    } else if v == "1710" {
+        1710
+    } else if v == "1711" {
+        1711
+    } else if v == "1712" {
+        1712
+    } else if v == "1713" {
+        1713
+    } else if v == "1714" {
+        1714
+    } else if v == "1715" {
+        1715
+    } else if v == "1716" {
+        1716
+    } else if v == "1717" {
+        1717
+    } else if v == "1718" {
+        1718
+    } else if v == "1719" {
+        1719
+    } else if v == "1720" {
+        1720
+    } else if v == "1721" {
+        1721
+    } else if v == "1722" {
+        1722
+    } else if v == "1723" {
+        1723
+    } else if v == "1724" {
+        1724
+    } else if v == "1725" {
+        1725
+    } else if v == "1726" {
+        1726
+    } else if v == "1727" {
+        1727
+    } else if v == "1728" {
+        1728
+    } else if v == "1729" {
+        1729
+    } else if v == "1730" {
+        1730
+    } else if v == "1731" {
+        1731
+    } else if v == "1732" {
+        1732
+    } else if v == "1733" {
+        1733
+    } else if v == "1734" {
+        1734
+    } else if v == "1735" {
+        1735
+    } else if v == "1736" {
+        1736
+    } else if v == "1737" {
+        1737
+    } else if v == "1738" {
+        1738
+    } else if v == "1739" {
+        1739
+    } else if v == "1740" {
+        1740
+    } else if v == "1741" {
+        1741
+    } else if v == "1742" {
+        1742
+    } else if v == "1743" {
+        1743
+    } else if v == "1744" {
+        1744
+    } else if v == "1745" {
+        1745
+    } else if v == "1746" {
+        1746
+    } else if v == "1747" {
+        1747
+    } else if v == "1748" {
+        1748
+    } else if v == "1749" {
+        1749
+    } else if v == "1750" {
+        1750
+    } else if v == "1751" {
+        1751
+    } else if v == "1752" {
+        1752
+    } else if v == "1753" {
+        1753
+    } else if v == "1754" {
+        1754
+    } else if v == "1755" {
+        1755
+    } else if v == "1756" {
+        1756
+    } else if v == "1757" {
+        1757
+    } else if v == "1758" {
+        1758
+    } else if v == "1759" {
+        1759
+    } else if v == "1760" {
+        1760
+    } else if v == "1761" {
+        1761
+    } else if v == "1762" {
+        1762
+    } else if v == "1763" {
+        1763
+    } else if v == "1764" {
+        1764
+    } else if v == "1765" {
+        1765
+    } else if v == "1766" {
+        1766
+    } else if v == "1767" {
+        1767
+    } else if v == "1768" {
+        1768
+    } else if v == "1769" {
+        1769
+    } else if v == "1770" {
+        1770
+    } else if v == "1771" {
+        1771
+    } else if v == "1772" {
+        1772
+    } else if v == "1773" {
+        1773
+    } else if v == "1774" {
+        1774
+    } else if v == "1775" {
+        1775
+    } else if v == "1776" {
+        1776
+    } else if v == "1777" {
+        1777
+    } else if v == "1778" {
+        1778
+    } else if v == "1779" {
+        1779
+    } else if v == "1780" {
+        1780
+    } else if v == "1781" {
+        1781
+    } else if v == "1782" {
+        1782
+    } else if v == "1783" {
+        1783
+    } else if v == "1784" {
+        1784
+    } else if v == "1785" {
+        1785
+    } else if v == "1786" {
+        1786
+    } else if v == "1787" {
+        1787
+    } else if v == "1788" {
+        1788
+    } else if v == "1789" {
+        1789
+    } else if v == "1790" {
+        1790
+    } else if v == "1791" {
+        1791
+    } else if v == "1792" {
+        1792
+    } else if v == "1793" {
+        1793
+    } else if v == "1794" {
+        1794
+    } else if v == "1795" {
+        1795
+    } else if v == "1796" {
+        1796
+    } else if v == "1797" {
+        1797
+    } else if v == "1798" {
+        1798
+    } else if v == "1799" {
+        1799
+    } else if v == "1800" {
+        1800
+    } else if v == "1801" {
+        1801
+    } else if v == "1802" {
+        1802
+    } else if v == "1803" {
+        1803
+    } else if v == "1804" {
+        1804
+    } else if v == "1805" {
+        1805
+    } else if v == "1806" {
+        1806
+    } else if v == "1807" {
+        1807
+    } else if v == "1808" {
+        1808
+    } else if v == "1809" {
+        1809
+    } else if v == "1810" {
+        1810
+    } else if v == "1811" {
+        1811
+    } else if v == "1812" {
+        1812
+    } else if v == "1813" {
+        1813
+    } else if v == "1814" {
+        1814
+    } else if v == "1815" {
+        1815
+    } else if v == "1816" {
+        1816
+    } else if v == "1817" {
+        1817
+    } else if v == "1818" {
+        1818
+    } else if v == "1819" {
+        1819
+    } else if v == "1820" {
+        1820
+    } else if v == "1821" {
+        1821
+    } else if v == "1822" {
+        1822
+    } else if v == "1823" {
+        1823
+    } else if v == "1824" {
+        1824
+    } else if v == "1825" {
+        1825
+    } else if v == "1826" {
+        1826
+    } else if v == "1827" {
+        1827
+    } else if v == "1828" {
+        1828
+    } else if v == "1829" {
+        1829
+    } else if v == "1830" {
+        1830
+    } else if v == "1831" {
+        1831
+    } else if v == "1832" {
+        1832
+    } else if v == "1833" {
+        1833
+    } else if v == "1834" {
+        1834
+    } else if v == "1835" {
+        1835
+    } else if v == "1836" {
+        1836
+    } else if v == "1837" {
+        1837
+    } else if v == "1838" {
+        1838
+    } else if v == "1839" {
+        1839
+    } else if v == "1840" {
+        1840
+    } else if v == "1841" {
+        1841
+    } else if v == "1842" {
+        1842
+    } else if v == "1843" {
+        1843
+    } else if v == "1844" {
+        1844
+    } else if v == "1845" {
+        1845
+    } else if v == "1846" {
+        1846
+    } else if v == "1847" {
+        1847
+    } else if v == "1848" {
+        1848
+    } else if v == "1849" {
+        1849
+    } else if v == "1850" {
+        1850
+    } else if v == "1851" {
+        1851
+    } else if v == "1852" {
+        1852
+    } else if v == "1853" {
+        1853
+    } else if v == "1854" {
+        1854
+    } else if v == "1855" {
+        1855
+    } else if v == "1856" {
+        1856
+    } else if v == "1857" {
+        1857
+    } else if v == "1858" {
+        1858
+    } else if v == "1859" {
+        1859
+    } else if v == "1860" {
+        1860
+    } else if v == "1861" {
+        1861
+    } else if v == "1862" {
+        1862
+    } else if v == "1863" {
+        1863
+    } else if v == "1864" {
+        1864
+    } else if v == "1865" {
+        1865
+    } else if v == "1866" {
+        1866
+    } else if v == "1867" {
+        1867
+    } else if v == "1868" {
+        1868
+    } else if v == "1869" {
+        1869
+    } else if v == "1870" {
+        1870
+    } else if v == "1871" {
+        1871
+    } else if v == "1872" {
+        1872
+    } else if v == "1873" {
+        1873
+    } else if v == "1874" {
+        1874
+    } else if v == "1875" {
+        1875
+    } else if v == "1876" {
+        1876
+    } else if v == "1877" {
+        1877
+    } else if v == "1878" {
+        1878
+    } else if v == "1879" {
+        1879
+    } else if v == "1880" {
+        1880
+    } else if v == "1881" {
+        1881
+    } else if v == "1882" {
+        1882
+    } else if v == "1883" {
+        1883
+    } else if v == "1884" {
+        1884
+    } else if v == "1885" {
+        1885
+    } else if v == "1886" {
+        1886
+    } else if v == "1887" {
+        1887
+    } else if v == "1888" {
+        1888
+    } else if v == "1889" {
+        1889
+    } else if v == "1890" {
+        1890
+    } else if v == "1891" {
+        1891
+    } else if v == "1892" {
+        1892
+    } else if v == "1893" {
+        1893
+    } else if v == "1894" {
+        1894
+    } else if v == "1895" {
+        1895
+    } else if v == "1896" {
+        1896
+    } else if v == "1897" {
+        1897
+    } else if v == "1898" {
+        1898
+    } else if v == "1899" {
+        1899
+    } else if v == "1900" {
+        1900
+    } else if v == "1901" {
+        1901
+    } else if v == "1902" {
+        1902
+    } else if v == "1903" {
+        1903
+    } else if v == "1904" {
+        1904
+    } else if v == "1905" {
+        1905
+    } else if v == "1906" {
+        1906
+    } else if v == "1907" {
+        1907
+    } else if v == "1908" {
+        1908
+    } else if v == "1909" {
+        1909
+    } else if v == "1910" {
+        1910
+    } else if v == "1911" {
+        1911
+    } else if v == "1912" {
+        1912
+    } else if v == "1913" {
+        1913
+    } else if v == "1914" {
+        1914
+    } else if v == "1915" {
+        1915
+    } else if v == "1916" {
+        1916
+    } else if v == "1917" {
+        1917
+    } else if v == "1918" {
+        1918
+    } else if v == "1919" {
+        1919
+    } else if v == "1920" {
+        1920
+    } else if v == "1921" {
+        1921
+    } else if v == "1922" {
+        1922
+    } else if v == "1923" {
+        1923
+    } else if v == "1924" {
+        1924
+    } else if v == "1925" {
+        1925
+    } else if v == "1926" {
+        1926
+    } else if v == "1927" {
+        1927
+    } else if v == "1928" {
+        1928
+    } else if v == "1929" {
+        1929
+    } else if v == "1930" {
+        1930
+    } else if v == "1931" {
+        1931
+    } else if v == "1932" {
+        1932
+    } else if v == "1933" {
+        1933
+    } else if v == "1934" {
+        1934
+    } else if v == "1935" {
+        1935
+    } else if v == "1936" {
+        1936
+    } else if v == "1937" {
+        1937
+    } else if v == "1938" {
+        1938
+    } else if v == "1939" {
+        1939
+    } else if v == "1940" {
+        1940
+    } else if v == "1941" {
+        1941
+    } else if v == "1942" {
+        1942
+    } else if v == "1943" {
+        1943
+    } else if v == "1944" {
+        1944
+    } else if v == "1945" {
+        1945
+    } else if v == "1946" {
+        1946
+    } else if v == "1947" {
+        1947
+    } else if v == "1948" {
+        1948
+    } else if v == "1949" {
+        1949
+    } else if v == "1950" {
+        1950
+    } else if v == "1951" {
+        1951
+    } else if v == "1952" {
+        1952
+    } else if v == "1953" {
+        1953
+    } else if v == "1954" {
+        1954
+    } else if v == "1955" {
+        1955
+    } else if v == "1956" {
+        1956
+    } else if v == "1957" {
+        1957
+    } else if v == "1958" {
+        1958
+    } else if v == "1959" {
+        1959
+    } else if v == "1960" {
+        1960
+    } else if v == "1961" {
+        1961
+    } else if v == "1962" {
+        1962
+    } else if v == "1963" {
+        1963
+    } else if v == "1964" {
+        1964
+    } else if v == "1965" {
+        1965
+    } else if v == "1966" {
+        1966
+    } else if v == "1967" {
+        1967
+    } else if v == "1968" {
+        1968
+    } else if v == "1969" {
+        1969
+    } else if v == "1970" {
+        1970
+    } else if v == "1971" {
+        1971
+    } else if v == "1972" {
+        1972
+    } else if v == "1973" {
+        1973
+    } else if v == "1974" {
+        1974
+    } else if v == "1975" {
+        1975
+    } else if v == "1976" {
+        1976
+    } else if v == "1977" {
+        1977
+    } else if v == "1978" {
+        1978
+    } else if v == "1979" {
+        1979
+    } else if v == "1980" {
+        1980
+    } else if v == "1981" {
+        1981
+    } else if v == "1982" {
+        1982
+    } else if v == "1983" {
+        1983
+    } else if v == "1984" {
+        1984
+    } else if v == "1985" {
+        1985
+    } else if v == "1986" {
+        1986
+    } else if v == "1987" {
+        1987
+    } else if v == "1988" {
+        1988
+    } else if v == "1989" {
+        1989
+    } else if v == "1990" {
+        1990
+    } else if v == "1991" {
+        1991
+    } else if v == "1992" {
+        1992
+    } else if v == "1993" {
+        1993
+    } else if v == "1994" {
+        1994
+    } else if v == "1995" {
+        1995
+    } else if v == "1996" {
+        1996
+    } else if v == "1997" {
+        1997
+    } else if v == "1998" {
+        1998
+    } else if v == "1999" {
+        1999
+    } else if v == "2000" {
+        2000
+    } else if v == "2001" {
+        2001
+    } else if v == "2002" {
+        2002
+    } else if v == "2003" {
+        2003
+    } else if v == "2004" {
+        2004
+    } else if v == "2005" {
+        2005
+    } else if v == "2006" {
+        2006
+    } else if v == "2007" {
+        2007
+    } else if v == "2008" {
+        2008
+    } else if v == "2009" {
+        2009
+    } else if v == "2010" {
+        2010
+    } else if v == "2011" {
+        2011
+    } else if v == "2012" {
+        2012
+    } else if v == "2013" {
+        2013
+    } else if v == "2014" {
+        2014
+    } else if v == "2015" {
+        2015
+    } else if v == "2016" {
+        2016
+    } else if v == "2017" {
+        2017
+    } else if v == "2018" {
+        2018
+    } else if v == "2019" {
+        2019
+    } else if v == "2020" {
+        2020
+    } else if v == "2021" {
+        2021
+    } else if v == "2022" {
+        2022
+    } else if v == "2023" {
+        2023
+    } else if v == "2024" {
+        2024
+    } else if v == "2025" {
+        2025
+    } else if v == "2026" {
+        2026
+    } else if v == "2027" {
+        2027
+    } else if v == "2028" {
+        2028
+    } else if v == "2029" {
+        2029
+    } else if v == "2030" {
+        2030
+    } else if v == "2031" {
+        2031
+    } else if v == "2032" {
+        2032
+    } else if v == "2033" {
+        2033
+    } else if v == "2034" {
+        2034
+    } else if v == "2035" {
+        2035
+    } else if v == "2036" {
+        2036
+    } else if v == "2037" {
+        2037
+    } else if v == "2038" {
+        2038
+    } else if v == "2039" {
+        2039
+    } else if v == "2040" {
+        2040
+    } else if v == "2041" {
+        2041
+    } else if v == "2042" {
+        2042
+    } else if v == "2043" {
+        2043
+    } else if v == "2044" {
+        2044
+    } else if v == "2045" {
+        2045
+    } else if v == "2046" {
+        2046
+    } else if v == "2047" {
+        2047
+    } else if v == "2048" {
+        2048
+    } else if v == "2049" {
+        2049
+    } else if v == "2050" {
+        2050
+    } else if v == "2051" {
+        2051
+    } else if v == "2052" {
+        2052
+    } else if v == "2053" {
+        2053
+    } else if v == "2054" {
+        2054
+    } else if v == "2055" {
+        2055
+    } else if v == "2056" {
+        2056
+    } else if v == "2057" {
+        2057
+    } else if v == "2058" {
+        2058
+    } else if v == "2059" {
+        2059
+    } else if v == "2060" {
+        2060
+    } else if v == "2061" {
+        2061
+    } else if v == "2062" {
+        2062
+    } else if v == "2063" {
+        2063
+    } else if v == "2064" {
+        2064
+    } else if v == "2065" {
+        2065
+    } else if v == "2066" {
+        2066
+    } else if v == "2067" {
+        2067
+    } else if v == "2068" {
+        2068
+    } else if v == "2069" {
+        2069
+    } else if v == "2070" {
+        2070
+    } else if v == "2071" {
+        2071
+    } else if v == "2072" {
+        2072
+    } else if v == "2073" {
+        2073
+    } else if v == "2074" {
+        2074
+    } else if v == "2075" {
+        2075
+    } else if v == "2076" {
+        2076
+    } else if v == "2077" {
+        2077
+    } else if v == "2078" {
+        2078
+    } else if v == "2079" {
+        2079
+    } else if v == "2080" {
+        2080
+    } else if v == "2081" {
+        2081
+    } else if v == "2082" {
+        2082
+    } else if v == "2083" {
+        2083
+    } else if v == "2084" {
+        2084
+    } else if v == "2085" {
+        2085
+    } else if v == "2086" {
+        2086
+    } else if v == "2087" {
+        2087
+    } else if v == "2088" {
+        2088
+    } else if v == "2089" {
+        2089
+    } else if v == "2090" {
+        2090
+    } else if v == "2091" {
+        2091
+    } else if v == "2092" {
+        2092
+    } else if v == "2093" {
+        2093
+    } else if v == "2094" {
+        2094
+    } else if v == "2095" {
+        2095
+    } else if v == "2096" {
+        2096
+    } else if v == "2097" {
+        2097
+    } else if v == "2098" {
+        2098
+    } else if v == "2099" {
+        2099
+    } else if v == "2100" {
+        2100
+    } else if v == "2101" {
+        2101
+    } else if v == "2102" {
+        2102
+    } else if v == "2103" {
+        2103
+    } else if v == "2104" {
+        2104
+    } else if v == "2105" {
+        2105
+    } else if v == "2106" {
+        2106
+    } else if v == "2107" {
+        2107
+    } else if v == "2108" {
+        2108
+    } else if v == "2109" {
+        2109
+    } else if v == "2110" {
+        2110
+    } else if v == "2111" {
+        2111
+    } else if v == "2112" {
+        2112
+    } else if v == "2113" {
+        2113
+    } else if v == "2114" {
+        2114
+    } else if v == "2115" {
+        2115
+    } else if v == "2116" {
+        2116
+    } else if v == "2117" {
+        2117
+    } else if v == "2118" {
+        2118
+    } else if v == "2119" {
+        2119
+    } else if v == "2120" {
+        2120
+    } else if v == "2121" {
+        2121
+    } else if v == "2122" {
+        2122
+    } else if v == "2123" {
+        2123
+    } else if v == "2124" {
+        2124
+    } else if v == "2125" {
+        2125
+    } else if v == "2126" {
+        2126
+    } else if v == "2127" {
+        2127
+    } else if v == "2128" {
+        2128
+    } else if v == "2129" {
+        2129
+    } else if v == "2130" {
+        2130
+    } else if v == "2131" {
+        2131
+    } else if v == "2132" {
+        2132
+    } else if v == "2133" {
+        2133
+    } else if v == "2134" {
+        2134
+    } else if v == "2135" {
+        2135
+    } else if v == "2136" {
+        2136
+    } else if v == "2137" {
+        2137
+    } else if v == "2138" {
+        2138
+    } else if v == "2139" {
+        2139
+    } else if v == "2140" {
+        2140
+    } else if v == "2141" {
+        2141
+    } else if v == "2142" {
+        2142
+    } else if v == "2143" {
+        2143
+    } else if v == "2144" {
+        2144
+    } else if v == "2145" {
+        2145
+    } else if v == "2146" {
+        2146
+    } else if v == "2147" {
+        2147
+    } else if v == "2148" {
+        2148
+    } else if v == "2149" {
+        2149
+    } else if v == "2150" {
+        2150
+    } else if v == "2151" {
+        2151
+    } else if v == "2152" {
+        2152
+    } else if v == "2153" {
+        2153
+    } else if v == "2154" {
+        2154
+    } else if v == "2155" {
+        2155
+    } else if v == "2156" {
+        2156
+    } else if v == "2157" {
+        2157
+    } else if v == "2158" {
+        2158
+    } else if v == "2159" {
+        2159
+    } else if v == "2160" {
+        2160
+    } else if v == "2161" {
+        2161
+    } else if v == "2162" {
+        2162
+    } else if v == "2163" {
+        2163
+    } else if v == "2164" {
+        2164
+    } else if v == "2165" {
+        2165
+    } else if v == "2166" {
+        2166
+    } else if v == "2167" {
+        2167
+    } else if v == "2168" {
+        2168
+    } else if v == "2169" {
+        2169
+    } else if v == "2170" {
+        2170
+    } else if v == "2171" {
+        2171
+    } else if v == "2172" {
+        2172
+    } else if v == "2173" {
+        2173
+    } else if v == "2174" {
+        2174
+    } else if v == "2175" {
+        2175
+    } else if v == "2176" {
+        2176
+    } else if v == "2177" {
+        2177
+    } else if v == "2178" {
+        2178
+    } else if v == "2179" {
+        2179
+    } else if v == "2180" {
+        2180
+    } else if v == "2181" {
+        2181
+    } else if v == "2182" {
+        2182
+    } else if v == "2183" {
+        2183
+    } else if v == "2184" {
+        2184
+    } else if v == "2185" {
+        2185
+    } else if v == "2186" {
+        2186
+    } else if v == "2187" {
+        2187
+    } else if v == "2188" {
+        2188
+    } else if v == "2189" {
+        2189
+    } else if v == "2190" {
+        2190
+    } else if v == "2191" {
+        2191
+    } else if v == "2192" {
+        2192
+    } else if v == "2193" {
+        2193
+    } else if v == "2194" {
+        2194
+    } else if v == "2195" {
+        2195
+    } else if v == "2196" {
+        2196
+    } else if v == "2197" {
+        2197
+    } else if v == "2198" {
+        2198
+    } else if v == "2199" {
+        2199
+    } else if v == "2200" {
+        2200
+    } else if v == "2201" {
+        2201
+    } else if v == "2202" {
+        2202
+    } else if v == "2203" {
+        2203
+    } else if v == "2204" {
+        2204
+    } else if v == "2205" {
+        2205
+    } else if v == "2206" {
+        2206
+    } else if v == "2207" {
+        2207
+    } else if v == "2208" {
+        2208
+    } else if v == "2209" {
+        2209
+    } else if v == "2210" {
+        2210
+    } else if v == "2211" {
+        2211
+    } else if v == "2212" {
+        2212
+    } else if v == "2213" {
+        2213
+    } else if v == "2214" {
+        2214
+    } else if v == "2215" {
+        2215
+    } else if v == "2216" {
+        2216
+    } else if v == "2217" {
+        2217
+    } else if v == "2218" {
+        2218
+    } else if v == "2219" {
+        2219
+    } else if v == "2220" {
+        2220
+    } else if v == "2221" {
+        2221
+    } else if v == "2222" {
+        2222
+    } else if v == "2223" {
+        2223
+    } else if v == "2224" {
+        2224
+    } else if v == "2225" {
+        2225
+    } else if v == "2226" {
+        2226
+    } else if v == "2227" {
+        2227
+    } else if v == "2228" {
+        2228
+    } else if v == "2229" {
+        2229
+    } else if v == "2230" {
+        2230
+    } else if v == "2231" {
+        2231
+    } else if v == "2232" {
+        2232
+    } else if v == "2233" {
+        2233
+    } else if v == "2234" {
+        2234
+    } else if v == "2235" {
+        2235
+    } else if v == "2236" {
+        2236
+    } else if v == "2237" {
+        2237
+    } else if v == "2238" {
+        2238
+    } else if v == "2239" {
+        2239
+    } else if v == "2240" {
+        2240
+    } else if v == "2241" {
+        2241
+    } else if v == "2242" {
+        2242
+    } else if v == "2243" {
+        2243
+    } else if v == "2244" {
+        2244
+    } else if v == "2245" {
+        2245
+    } else if v == "2246" {
+        2246
+    } else if v == "2247" {
+        2247
+    } else if v == "2248" {
+        2248
+    } else if v == "2249" {
+        2249
+    } else if v == "2250" {
+        2250
+    } else if v == "2251" {
+        2251
+    } else if v == "2252" {
+        2252
+    } else if v == "2253" {
+        2253
+    } else if v == "2254" {
+        2254
+    } else if v == "2255" {
+        2255
+    } else if v == "2256" {
+        2256
+    } else if v == "2257" {
+        2257
+    } else if v == "2258" {
+        2258
+    } else if v == "2259" {
+        2259
+    } else if v == "2260" {
+        2260
+    } else if v == "2261" {
+        2261
+    } else if v == "2262" {
+        2262
+    } else if v == "2263" {
+        2263
+    } else if v == "2264" {
+        2264
+    } else if v == "2265" {
+        2265
+    } else if v == "2266" {
+        2266
+    } else if v == "2267" {
+        2267
+    } else if v == "2268" {
+        2268
+    } else if v == "2269" {
+        2269
+    } else if v == "2270" {
+        2270
+    } else if v == "2271" {
+        2271
+    } else if v == "2272" {
+        2272
+    } else if v == "2273" {
+        2273
+    } else if v == "2274" {
+        2274
+    } else if v == "2275" {
+        2275
+    } else if v == "2276" {
+        2276
+    } else if v == "2277" {
+        2277
+    } else if v == "2278" {
+        2278
+    } else if v == "2279" {
+        2279
+    } else if v == "2280" {
+        2280
+    } else if v == "2281" {
+        2281
+    } else if v == "2282" {
+        2282
+    } else if v == "2283" {
+        2283
+    } else if v == "2284" {
+        2284
+    } else if v == "2285" {
+        2285
+    } else if v == "2286" {
+        2286
+    } else if v == "2287" {
+        2287
+    } else if v == "2288" {
+        2288
+    } else if v == "2289" {
+        2289
+    } else if v == "2290" {
+        2290
+    } else if v == "2291" {
+        2291
+    } else if v == "2292" {
+        2292
+    } else if v == "2293" {
+        2293
+    } else if v == "2294" {
+        2294
+    } else if v == "2295" {
+        2295
+    } else if v == "2296" {
+        2296
+    } else if v == "2297" {
+        2297
+    } else if v == "2298" {
+        2298
+    } else if v == "2299" {
+        2299
+    } else if v == "2300" {
+        2300
+    } else if v == "2301" {
+        2301
+    } else if v == "2302" {
+        2302
+    } else if v == "2303" {
+        2303
+    } else if v == "2304" {
+        2304
+    } else if v == "2305" {
+        2305
+    } else if v == "2306" {
+        2306
+    } else if v == "2307" {
+        2307
+    } else if v == "2308" {
+        2308
+    } else if v == "2309" {
+        2309
+    } else if v == "2310" {
+        2310
+    } else if v == "2311" {
+        2311
+    } else if v == "2312" {
+        2312
+    } else if v == "2313" {
+        2313
+    } else if v == "2314" {
+        2314
+    } else if v == "2315" {
+        2315
+    } else if v == "2316" {
+        2316
+    } else if v == "2317" {
+        2317
+    } else if v == "2318" {
+        2318
+    } else if v == "2319" {
+        2319
+    } else if v == "2320" {
+        2320
+    } else if v == "2321" {
+        2321
+    } else if v == "2322" {
+        2322
+    } else if v == "2323" {
+        2323
+    } else if v == "2324" {
+        2324
+    } else if v == "2325" {
+        2325
+    } else if v == "2326" {
+        2326
+    } else if v == "2327" {
+        2327
+    } else if v == "2328" {
+        2328
+    } else if v == "2329" {
+        2329
+    } else if v == "2330" {
+        2330
+    } else if v == "2331" {
+        2331
+    } else if v == "2332" {
+        2332
+    } else if v == "2333" {
+        2333
+    } else if v == "2334" {
+        2334
+    } else if v == "2335" {
+        2335
+    } else if v == "2336" {
+        2336
+    } else if v == "2337" {
+        2337
+    } else if v == "2338" {
+        2338
+    } else if v == "2339" {
+        2339
+    } else if v == "2340" {
+        2340
+    } else if v == "2341" {
+        2341
+    } else if v == "2342" {
+        2342
+    } else if v == "2343" {
+        2343
+    } else if v == "2344" {
+        2344
+    } else if v == "2345" {
+        2345
+    } else if v == "2346" {
+        2346
+    } else if v == "2347" {
+        2347
+    } else if v == "2348" {
+        2348
+    } else if v == "2349" {
+        2349
+    } else if v == "2350" {
+        2350
+    } else if v == "2351" {
+        2351
+    } else if v == "2352" {
+        2352
+    } else if v == "2353" {
+        2353
+    } else if v == "2354" {
+        2354
+    } else if v == "2355" {
+        2355
+    } else if v == "2356" {
+        2356
+    } else if v == "2357" {
+        2357
+    } else if v == "2358" {
+        2358
+    } else if v == "2359" {
+        2359
+    } else if v == "2360" {
+        2360
+    } else if v == "2361" {
+        2361
+    } else if v == "2362" {
+        2362
+    } else if v == "2363" {
+        2363
+    } else if v == "2364" {
+        2364
+    } else if v == "2365" {
+        2365
+    } else if v == "2366" {
+        2366
+    } else if v == "2367" {
+        2367
+    } else if v == "2368" {
+        2368
+    } else if v == "2369" {
+        2369
+    } else if v == "2370" {
+        2370
+    } else if v == "2371" {
+        2371
+    } else if v == "2372" {
+        2372
+    } else if v == "2373" {
+        2373
+    } else if v == "2374" {
+        2374
+    } else if v == "2375" {
+        2375
+    } else if v == "2376" {
+        2376
+    } else if v == "2377" {
+        2377
+    } else if v == "2378" {
+        2378
+    } else if v == "2379" {
+        2379
+    } else if v == "2380" {
+        2380
+    } else if v == "2381" {
+        2381
+    } else if v == "2382" {
+        2382
+    } else if v == "2383" {
+        2383
+    } else if v == "2384" {
+        2384
+    } else if v == "2385" {
+        2385
+    } else if v == "2386" {
+        2386
+    } else if v == "2387" {
+        2387
+    } else if v == "2388" {
+        2388
+    } else if v == "2389" {
+        2389
+    } else if v == "2390" {
+        2390
+    } else if v == "2391" {
+        2391
+    } else if v == "2392" {
+        2392
+    } else if v == "2393" {
+        2393
+    } else if v == "2394" {
+        2394
+    } else if v == "2395" {
+        2395
+    } else if v == "2396" {
+        2396
+    } else if v == "2397" {
+        2397
+    } else if v == "2398" {
+        2398
+    } else if v == "2399" {
+        2399
+    } else if v == "2400" {
+        2400
+    } else if v == "2401" {
+        2401
+    } else if v == "2402" {
+        2402
+    } else if v == "2403" {
+        2403
+    } else if v == "2404" {
+        2404
+    } else if v == "2405" {
+        2405
+    } else if v == "2406" {
+        2406
+    } else if v == "2407" {
+        2407
+    } else if v == "2408" {
+        2408
+    } else if v == "2409" {
+        2409
+    } else if v == "2410" {
+        2410
+    } else if v == "2411" {
+        2411
+    } else if v == "2412" {
+        2412
+    } else if v == "2413" {
+        2413
+    } else if v == "2414" {
+        2414
+    } else if v == "2415" {
+        2415
+    } else if v == "2416" {
+        2416
+    } else if v == "2417" {
+        2417
+    } else if v == "2418" {
+        2418
+    } else if v == "2419" {
+        2419
+    } else if v == "2420" {
+        2420
+    } else if v == "2421" {
+        2421
+    } else if v == "2422" {
+        2422
+    } else if v == "2423" {
+        2423
+    } else if v == "2424" {
+        2424
+    } else if v == "2425" {
+        2425
+    } else if v == "2426" {
+        2426
+    } else if v == "2427" {
+        2427
+    } else if v == "2428" {
+        2428
+    } else if v == "2429" {
+        2429
+    } else if v == "2430" {
+        2430
+    } else if v == "2431" {
+        2431
+    } else if v == "2432" {
+        2432
+    } else if v == "2433" {
+        2433
+    } else if v == "2434" {
+        2434
+    } else if v == "2435" {
+        2435
+    } else if v == "2436" {
+        2436
+    } else if v == "2437" {
+        2437
+    } else if v == "2438" {
+        2438
+    } else if v == "2439" {
+        2439
+    } else if v == "2440" {
+        2440
+    } else if v == "2441" {
+        2441
+    } else if v == "2442" {
+        2442
+    } else if v == "2443" {
+        2443
+    } else if v == "2444" {
+        2444
+    } else if v == "2445" {
+        2445
+    } else if v == "2446" {
+        2446
+    } else if v == "2447" {
+        2447
+    } else if v == "2448" {
+        2448
+    } else if v == "2449" {
+        2449
+    } else if v == "2450" {
+        2450
+    } else if v == "2451" {
+        2451
+    } else if v == "2452" {
+        2452
+    } else if v == "2453" {
+        2453
+    } else if v == "2454" {
+        2454
+    } else if v == "2455" {
+        2455
+    } else if v == "2456" {
+        2456
+    } else if v == "2457" {
+        2457
+    } else if v == "2458" {
+        2458
+    } else if v == "2459" {
+        2459
+    } else if v == "2460" {
+        2460
+    } else if v == "2461" {
+        2461
+    } else if v == "2462" {
+        2462
+    } else if v == "2463" {
+        2463
+    } else if v == "2464" {
+        2464
+    } else if v == "2465" {
+        2465
+    } else if v == "2466" {
+        2466
+    } else if v == "2467" {
+        2467
+    } else if v == "2468" {
+        2468
+    } else if v == "2469" {
+        2469
+    } else if v == "2470" {
+        2470
+    } else if v == "2471" {
+        2471
+    } else if v == "2472" {
+        2472
+    } else if v == "2473" {
+        2473
+    } else if v == "2474" {
+        2474
+    } else if v == "2475" {
+        2475
+    } else if v == "2476" {
+        2476
+    } else if v == "2477" {
+        2477
+    } else if v == "2478" {
+        2478
+    } else if v == "2479" {
+        2479
+    } else if v == "2480" {
+        2480
+    } else if v == "2481" {
+        2481
+    } else if v == "2482" {
+        2482
+    } else if v == "2483" {
+        2483
+    } else if v == "2484" {
+        2484
+    } else if v == "2485" {
+        2485
+    } else if v == "2486" {
+        2486
+    } else if v == "2487" {
+        2487
+    } else if v == "2488" {
+        2488
+    } else if v == "2489" {
+        2489
+    } else if v == "2490" {
+        2490
+    } else if v == "2491" {
+        2491
+    } else if v == "2492" {
+        2492
+    } else if v == "2493" {
+        2493
+    } else if v == "2494" {
+        2494
+    } else if v == "2495" {
+        2495
+    } else if v == "2496" {
+        2496
+    } else if v == "2497" {
+        2497
+    } else if v == "2498" {
+        2498
+    } else if v == "2499" {
+        2499
+    } else if v == "2500" {
+        2500
+    } else if v == "2501" {
+        2501
+    } else if v == "2502" {
+        2502
+    } else if v == "2503" {
+        2503
+    } else if v == "2504" {
+        2504
+    } else if v == "2505" {
+        2505
+    } else if v == "2506" {
+        2506
+    } else if v == "2507" {
+        2507
+    } else if v == "2508" {
+        2508
+    } else if v == "2509" {
+        2509
+    } else if v == "2510" {
+        2510
+    } else if v == "2511" {
+        2511
+    } else if v == "2512" {
+        2512
+    } else if v == "2513" {
+        2513
+    } else if v == "2514" {
+        2514
+    } else if v == "2515" {
+        2515
+    } else if v == "2516" {
+        2516
+    } else if v == "2517" {
+        2517
+    } else if v == "2518" {
+        2518
+    } else if v == "2519" {
+        2519
+    } else if v == "2520" {
+        2520
+    } else if v == "2521" {
+        2521
+    } else if v == "2522" {
+        2522
+    } else if v == "2523" {
+        2523
+    } else if v == "2524" {
+        2524
+    } else if v == "2525" {
+        2525
+    } else if v == "2526" {
+        2526
+    } else if v == "2527" {
+        2527
+    } else if v == "2528" {
+        2528
+    } else if v == "2529" {
+        2529
+    } else if v == "2530" {
+        2530
+    } else if v == "2531" {
+        2531
+    } else if v == "2532" {
+        2532
+    } else if v == "2533" {
+        2533
+    } else if v == "2534" {
+        2534
+    } else if v == "2535" {
+        2535
+    } else if v == "2536" {
+        2536
+    } else if v == "2537" {
+        2537
+    } else if v == "2538" {
+        2538
+    } else if v == "2539" {
+        2539
+    } else if v == "2540" {
+        2540
+    } else if v == "2541" {
+        2541
+    } else if v == "2542" {
+        2542
+    } else if v == "2543" {
+        2543
+    } else if v == "2544" {
+        2544
+    } else if v == "2545" {
+        2545
+    } else if v == "2546" {
+        2546
+    } else if v == "2547" {
+        2547
+    } else if v == "2548" {
+        2548
+    } else if v == "2549" {
+        2549
+    } else if v == "2550" {
+        2550
+    } else if v == "2551" {
+        2551
+    } else if v == "2552" {
+        2552
+    } else if v == "2553" {
+        2553
+    } else if v == "2554" {
+        2554
+    } else if v == "2555" {
+        2555
+    } else if v == "2556" {
+        2556
+    } else if v == "2557" {
+        2557
+    } else if v == "2558" {
+        2558
+    } else if v == "2559" {
+        2559
+    } else if v == "2560" {
+        2560
+    } else if v == "2561" {
+        2561
+    } else if v == "2562" {
+        2562
+    } else if v == "2563" {
+        2563
+    } else if v == "2564" {
+        2564
+    } else if v == "2565" {
+        2565
+    } else if v == "2566" {
+        2566
+    } else if v == "2567" {
+        2567
+    } else if v == "2568" {
+        2568
+    } else if v == "2569" {
+        2569
+    } else if v == "2570" {
+        2570
+    } else if v == "2571" {
+        2571
+    } else if v == "2572" {
+        2572
+    } else if v == "2573" {
+        2573
+    } else if v == "2574" {
+        2574
+    } else if v == "2575" {
+        2575
+    } else if v == "2576" {
+        2576
+    } else if v == "2577" {
+        2577
+    } else if v == "2578" {
+        2578
+    } else if v == "2579" {
+        2579
+    } else if v == "2580" {
+        2580
+    } else if v == "2581" {
+        2581
+    } else if v == "2582" {
+        2582
+    } else if v == "2583" {
+        2583
+    } else if v == "2584" {
+        2584
+    } else if v == "2585" {
+        2585
+    } else if v == "2586" {
+        2586
+    } else if v == "2587" {
+        2587
+    } else if v == "2588" {
+        2588
+    } else if v == "2589" {
+        2589
+    } else if v == "2590" {
+        2590
+    } else if v == "2591" {
+        2591
+    } else if v == "2592" {
+        2592
+    } else if v == "2593" {
+        2593
+    } else if v == "2594" {
+        2594
+    } else if v == "2595" {
+        2595
+    } else if v == "2596" {
+        2596
+    } else if v == "2597" {
+        2597
+    } else if v == "2598" {
+        2598
+    } else if v == "2599" {
+        2599
+    } else if v == "2600" {
+        2600
+    } else if v == "2601" {
+        2601
+    } else if v == "2602" {
+        2602
+    } else if v == "2603" {
+        2603
+    } else if v == "2604" {
+        2604
+    } else if v == "2605" {
+        2605
+    } else if v == "2606" {
+        2606
+    } else if v == "2607" {
+        2607
+    } else if v == "2608" {
+        2608
+    } else if v == "2609" {
+        2609
+    } else if v == "2610" {
+        2610
+    } else if v == "2611" {
+        2611
+    } else if v == "2612" {
+        2612
+    } else if v == "2613" {
+        2613
+    } else if v == "2614" {
+        2614
+    } else if v == "2615" {
+        2615
+    } else if v == "2616" {
+        2616
+    } else if v == "2617" {
+        2617
+    } else if v == "2618" {
+        2618
+    } else if v == "2619" {
+        2619
+    } else if v == "2620" {
+        2620
+    } else if v == "2621" {
+        2621
+    } else if v == "2622" {
+        2622
+    } else if v == "2623" {
+        2623
+    } else if v == "2624" {
+        2624
+    } else if v == "2625" {
+        2625
+    } else if v == "2626" {
+        2626
+    } else if v == "2627" {
+        2627
+    } else if v == "2628" {
+        2628
+    } else if v == "2629" {
+        2629
+    } else if v == "2630" {
+        2630
+    } else if v == "2631" {
+        2631
+    } else if v == "2632" {
+        2632
+    } else if v == "2633" {
+        2633
+    } else if v == "2634" {
+        2634
+    } else if v == "2635" {
+        2635
+    } else if v == "2636" {
+        2636
+    } else if v == "2637" {
+        2637
+    } else if v == "2638" {
+        2638
+    } else if v == "2639" {
+        2639
+    } else if v == "2640" {
+        2640
+    } else if v == "2641" {
+        2641
+    } else if v == "2642" {
+        2642
+    } else if v == "2643" {
+        2643
+    } else if v == "2644" {
+        2644
+    } else if v == "2645" {
+        2645
+    } else if v == "2646" {
+        2646
+    } else if v == "2647" {
+        2647
+    } else if v == "2648" {
+        2648
+    } else if v == "2649" {
+        2649
+    } else if v == "2650" {
+        2650
+    } else if v == "2651" {
+        2651
+    } else if v == "2652" {
+        2652
+    } else if v == "2653" {
+        2653
+    } else if v == "2654" {
+        2654
+    } else if v == "2655" {
+        2655
+    } else if v == "2656" {
+        2656
+    } else if v == "2657" {
+        2657
+    } else if v == "2658" {
+        2658
+    } else if v == "2659" {
+        2659
+    } else if v == "2660" {
+        2660
+    } else if v == "2661" {
+        2661
+    } else if v == "2662" {
+        2662
+    } else if v == "2663" {
+        2663
+    } else if v == "2664" {
+        2664
+    } else if v == "2665" {
+        2665
+    } else if v == "2666" {
+        2666
+    } else if v == "2667" {
+        2667
+    } else if v == "2668" {
+        2668
+    } else if v == "2669" {
+        2669
+    } else if v == "2670" {
+        2670
+    } else if v == "2671" {
+        2671
+    } else if v == "2672" {
+        2672
+    } else if v == "2673" {
+        2673
+    } else if v == "2674" {
+        2674
+    } else if v == "2675" {
+        2675
+    } else if v == "2676" {
+        2676
+    } else if v == "2677" {
+        2677
+    } else if v == "2678" {
+        2678
+    } else if v == "2679" {
+        2679
+    } else if v == "2680" {
+        2680
+    } else if v == "2681" {
+        2681
+    } else if v == "2682" {
+        2682
+    } else if v == "2683" {
+        2683
+    } else if v == "2684" {
+        2684
+    } else if v == "2685" {
+        2685
+    } else if v == "2686" {
+        2686
+    } else if v == "2687" {
+        2687
+    } else if v == "2688" {
+        2688
+    } else if v == "2689" {
+        2689
+    } else if v == "2690" {
+        2690
+    } else if v == "2691" {
+        2691
+    } else if v == "2692" {
+        2692
+    } else if v == "2693" {
+        2693
+    } else if v == "2694" {
+        2694
+    } else if v == "2695" {
+        2695
+    } else if v == "2696" {
+        2696
+    } else if v == "2697" {
+        2697
+    } else if v == "2698" {
+        2698
+    } else if v == "2699" {
+        2699
+    } else if v == "2700" {
+        2700
+    } else if v == "2701" {
+        2701
+    } else if v == "2702" {
+        2702
+    } else if v == "2703" {
+        2703
+    } else if v == "2704" {
+        2704
+    } else if v == "2705" {
+        2705
+    } else if v == "2706" {
+        2706
+    } else if v == "2707" {
+        2707
+    } else if v == "2708" {
+        2708
+    } else if v == "2709" {
+        2709
+    } else if v == "2710" {
+        2710
+    } else if v == "2711" {
+        2711
+    } else if v == "2712" {
+        2712
+    } else if v == "2713" {
+        2713
+    } else if v == "2714" {
+        2714
+    } else if v == "2715" {
+        2715
+    } else if v == "2716" {
+        2716
+    } else if v == "2717" {
+        2717
+    } else if v == "2718" {
+        2718
+    } else if v == "2719" {
+        2719
+    } else if v == "2720" {
+        2720
+    } else if v == "2721" {
+        2721
+    } else if v == "2722" {
+        2722
+    } else if v == "2723" {
+        2723
+    } else if v == "2724" {
+        2724
+    } else if v == "2725" {
+        2725
+    } else if v == "2726" {
+        2726
+    } else if v == "2727" {
+        2727
+    } else if v == "2728" {
+        2728
+    } else if v == "2729" {
+        2729
+    } else if v == "2730" {
+        2730
+    } else if v == "2731" {
+        2731
+    } else if v == "2732" {
+        2732
+    } else if v == "2733" {
+        2733
+    } else if v == "2734" {
+        2734
+    } else if v == "2735" {
+        2735
+    } else if v == "2736" {
+        2736
+    } else if v == "2737" {
+        2737
+    } else if v == "2738" {
+        2738
+    } else if v == "2739" {
+        2739
+    } else if v == "2740" {
+        2740
+    } else if v == "2741" {
+        2741
+    } else if v == "2742" {
+        2742
+    } else if v == "2743" {
+        2743
+    } else if v == "2744" {
+        2744
+    } else if v == "2745" {
+        2745
+    } else if v == "2746" {
+        2746
+    } else if v == "2747" {
+        2747
+    } else if v == "2748" {
+        2748
+    } else if v == "2749" {
+        2749
+    } else if v == "2750" {
+        2750
+    } else if v == "2751" {
+        2751
+    } else if v == "2752" {
+        2752
+    } else if v == "2753" {
+        2753
+    } else if v == "2754" {
+        2754
+    } else if v == "2755" {
+        2755
+    } else if v == "2756" {
+        2756
+    } else if v == "2757" {
+        2757
+    } else if v == "2758" {
+        2758
+    } else if v == "2759" {
+        2759
+    } else if v == "2760" {
+        2760
+    } else if v == "2761" {
+        2761
+    } else if v == "2762" {
+        2762
+    } else if v == "2763" {
+        2763
+    } else if v == "2764" {
+        2764
+    } else if v == "2765" {
+        2765
+    } else if v == "2766" {
+        2766
+    } else if v == "2767" {
+        2767
+    } else if v == "2768" {
+        2768
+    } else if v == "2769" {
+        2769
+    } else if v == "2770" {
+        2770
+    } else if v == "2771" {
+        2771
+    } else if v == "2772" {
+        2772
+    } else if v == "2773" {
+        2773
+    } else if v == "2774" {
+        2774
+    } else if v == "2775" {
+        2775
+    } else if v == "2776" {
+        2776
+    } else if v == "2777" {
+        2777
+    } else if v == "2778" {
+        2778
+    } else if v == "2779" {
+        2779
+    } else if v == "2780" {
+        2780
+    } else if v == "2781" {
+        2781
+    } else if v == "2782" {
+        2782
+    } else if v == "2783" {
+        2783
+    } else if v == "2784" {
+        2784
+    } else if v == "2785" {
+        2785
+    } else if v == "2786" {
+        2786
+    } else if v == "2787" {
+        2787
+    } else if v == "2788" {
+        2788
+    } else if v == "2789" {
+        2789
+    } else if v == "2790" {
+        2790
+    } else if v == "2791" {
+        2791
+    } else if v == "2792" {
+        2792
+    } else if v == "2793" {
+        2793
+    } else if v == "2794" {
+        2794
+    } else if v == "2795" {
+        2795
+    } else if v == "2796" {
+        2796
+    } else if v == "2797" {
+        2797
+    } else if v == "2798" {
+        2798
+    } else if v == "2799" {
+        2799
+    } else if v == "2800" {
+        2800
+    } else if v == "2801" {
+        2801
+    } else if v == "2802" {
+        2802
+    } else if v == "2803" {
+        2803
+    } else if v == "2804" {
+        2804
+    } else if v == "2805" {
+        2805
+    } else if v == "2806" {
+        2806
+    } else if v == "2807" {
+        2807
+    } else if v == "2808" {
+        2808
+    } else if v == "2809" {
+        2809
+    } else if v == "2810" {
+        2810
+    } else if v == "2811" {
+        2811
+    } else if v == "2812" {
+        2812
+    } else if v == "2813" {
+        2813
+    } else if v == "2814" {
+        2814
+    } else if v == "2815" {
+        2815
+    } else if v == "2816" {
+        2816
+    } else if v == "2817" {
+        2817
+    } else if v == "2818" {
+        2818
+    } else if v == "2819" {
+        2819
+    } else if v == "2820" {
+        2820
+    } else if v == "2821" {
+        2821
+    } else if v == "2822" {
+        2822
+    } else if v == "2823" {
+        2823
+    } else if v == "2824" {
+        2824
+    } else if v == "2825" {
+        2825
+    } else if v == "2826" {
+        2826
+    } else if v == "2827" {
+        2827
+    } else if v == "2828" {
+        2828
+    } else if v == "2829" {
+        2829
+    } else if v == "2830" {
+        2830
+    } else if v == "2831" {
+        2831
+    } else if v == "2832" {
+        2832
+    } else if v == "2833" {
+        2833
+    } else if v == "2834" {
+        2834
+    } else if v == "2835" {
+        2835
+    } else if v == "2836" {
+        2836
+    } else if v == "2837" {
+        2837
+    } else if v == "2838" {
+        2838
+    } else if v == "2839" {
+        2839
+    } else if v == "2840" {
+        2840
+    } else if v == "2841" {
+        2841
+    } else if v == "2842" {
+        2842
+    } else if v == "2843" {
+        2843
+    } else if v == "2844" {
+        2844
+    } else if v == "2845" {
+        2845
+    } else if v == "2846" {
+        2846
+    } else if v == "2847" {
+        2847
+    } else if v == "2848" {
+        2848
+    } else if v == "2849" {
+        2849
+    } else if v == "2850" {
+        2850
+    } else if v == "2851" {
+        2851
+    } else if v == "2852" {
+        2852
+    } else if v == "2853" {
+        2853
+    } else if v == "2854" {
+        2854
+    } else if v == "2855" {
+        2855
+    } else if v == "2856" {
+        2856
+    } else if v == "2857" {
+        2857
+    } else if v == "2858" {
+        2858
+    } else if v == "2859" {
+        2859
+    } else if v == "2860" {
+        2860
+    } else if v == "2861" {
+        2861
+    } else if v == "2862" {
+        2862
+    } else if v == "2863" {
+        2863
+    } else if v == "2864" {
+        2864
+    } else if v == "2865" {
+        2865
+    } else if v == "2866" {
+        2866
+    } else if v == "2867" {
+        2867
+    } else if v == "2868" {
+        2868
+    } else if v == "2869" {
+        2869
+    } else if v == "2870" {
+        2870
+    } else if v == "2871" {
+        2871
+    } else if v == "2872" {
+        2872
+    } else if v == "2873" {
+        2873
+    } else if v == "2874" {
+        2874
+    } else if v == "2875" {
+        2875
+    } else if v == "2876" {
+        2876
+    } else if v == "2877" {
+        2877
+    } else if v == "2878" {
+        2878
+    } else if v == "2879" {
+        2879
+    } else if v == "2880" {
+        2880
+    } else if v == "2881" {
+        2881
+    } else if v == "2882" {
+        2882
+    } else if v == "2883" {
+        2883
+    } else if v == "2884" {
+        2884
+    } else if v == "2885" {
+        2885
+    } else if v == "2886" {
+        2886
+    } else if v == "2887" {
+        2887
+    } else if v == "2888" {
+        2888
+    } else if v == "2889" {
+        2889
+    } else if v == "2890" {
+        2890
+    } else if v == "2891" {
+        2891
+    } else if v == "2892" {
+        2892
+    } else if v == "2893" {
+        2893
+    } else if v == "2894" {
+        2894
+    } else if v == "2895" {
+        2895
+    } else if v == "2896" {
+        2896
+    } else if v == "2897" {
+        2897
+    } else if v == "2898" {
+        2898
+    } else if v == "2899" {
+        2899
+    } else if v == "2900" {
+        2900
+    } else if v == "2901" {
+        2901
+    } else if v == "2902" {
+        2902
+    } else if v == "2903" {
+        2903
+    } else if v == "2904" {
+        2904
+    } else if v == "2905" {
+        2905
+    } else if v == "2906" {
+        2906
+    } else if v == "2907" {
+        2907
+    } else if v == "2908" {
+        2908
+    } else if v == "2909" {
+        2909
+    } else if v == "2910" {
+        2910
+    } else if v == "2911" {
+        2911
+    } else if v == "2912" {
+        2912
+    } else if v == "2913" {
+        2913
+    } else if v == "2914" {
+        2914
+    } else if v == "2915" {
+        2915
+    } else if v == "2916" {
+        2916
+    } else if v == "2917" {
+        2917
+    } else if v == "2918" {
+        2918
+    } else if v == "2919" {
+        2919
+    } else if v == "2920" {
+        2920
+    } else if v == "2921" {
+        2921
+    } else if v == "2922" {
+        2922
+    } else if v == "2923" {
+        2923
+    } else if v == "2924" {
+        2924
+    } else if v == "2925" {
+        2925
+    } else if v == "2926" {
+        2926
+    } else if v == "2927" {
+        2927
+    } else if v == "2928" {
+        2928
+    } else if v == "2929" {
+        2929
+    } else if v == "2930" {
+        2930
+    } else if v == "2931" {
+        2931
+    } else if v == "2932" {
+        2932
+    } else if v == "2933" {
+        2933
+    } else if v == "2934" {
+        2934
+    } else if v == "2935" {
+        2935
+    } else if v == "2936" {
+        2936
+    } else if v == "2937" {
+        2937
+    } else if v == "2938" {
+        2938
+    } else if v == "2939" {
+        2939
+    } else if v == "2940" {
+        2940
+    } else if v == "2941" {
+        2941
+    } else if v == "2942" {
+        2942
+    } else if v == "2943" {
+        2943
+    } else if v == "2944" {
+        2944
+    } else if v == "2945" {
+        2945
+    } else if v == "2946" {
+        2946
+    } else if v == "2947" {
+        2947
+    } else if v == "2948" {
+        2948
+    } else if v == "2949" {
+        2949
+    } else if v == "2950" {
+        2950
+    } else if v == "2951" {
+        2951
+    } else if v == "2952" {
+        2952
+    } else if v == "2953" {
+        2953
+    } else if v == "2954" {
+        2954
+    } else if v == "2955" {
+        2955
+    } else if v == "2956" {
+        2956
+    } else if v == "2957" {
+        2957
+    } else if v == "2958" {
+        2958
+    } else if v == "2959" {
+        2959
+    } else if v == "2960" {
+        2960
+    } else if v == "2961" {
+        2961
+    } else if v == "2962" {
+        2962
+    } else if v == "2963" {
+        2963
+    } else if v == "2964" {
+        2964
+    } else if v == "2965" {
+        2965
+    } else if v == "2966" {
+        2966
+    } else if v == "2967" {
+        2967
+    } else if v == "2968" {
+        2968
+    } else if v == "2969" {
+        2969
+    } else if v == "2970" {
+        2970
+    } else if v == "2971" {
+        2971
+    } else if v == "2972" {
+        2972
+    } else if v == "2973" {
+        2973
+    } else if v == "2974" {
+        2974
+    } else if v == "2975" {
+        2975
+    } else if v == "2976" {
+        2976
+    } else if v == "2977" {
+        2977
+    } else if v == "2978" {
+        2978
+    } else if v == "2979" {
+        2979
+    } else if v == "2980" {
+        2980
+    } else if v == "2981" {
+        2981
+    } else if v == "2982" {
+        2982
+    } else if v == "2983" {
+        2983
+    } else if v == "2984" {
+        2984
+    } else if v == "2985" {
+        2985
+    } else if v == "2986" {
+        2986
+    } else if v == "2987" {
+        2987
+    } else if v == "2988" {
+        2988
+    } else if v == "2989" {
+        2989
+    } else if v == "2990" {
+        2990
+    } else if v == "2991" {
+        2991
+    } else if v == "2992" {
+        2992
+    } else if v == "2993" {
+        2993
+    } else if v == "2994" {
+        2994
+    } else if v == "2995" {
+        2995
+    } else if v == "2996" {
+        2996
+    } else if v == "2997" {
+        2997
+    } else if v == "2998" {
+        2998
+    } else if v == "2999" {
+        2999
+    } else if v == "3000" {
+        3000
+    } else if v == "3001" {
+        3001
+    } else if v == "3002" {
+        3002
+    } else if v == "3003" {
+        3003
+    } else if v == "3004" {
+        3004
+    } else if v == "3005" {
+        3005
+    } else if v == "3006" {
+        3006
+    } else if v == "3007" {
+        3007
+    } else if v == "3008" {
+        3008
+    } else if v == "3009" {
+        3009
+    } else if v == "3010" {
+        3010
+    } else if v == "3011" {
+        3011
+    } else if v == "3012" {
+        3012
+    } else if v == "3013" {
+        3013
+    } else if v == "3014" {
+        3014
+    } else if v == "3015" {
+        3015
+    } else if v == "3016" {
+        3016
+    } else if v == "3017" {
+        3017
+    } else if v == "3018" {
+        3018
+    } else if v == "3019" {
+        3019
+    } else if v == "3020" {
+        3020
+    } else if v == "3021" {
+        3021
+    } else if v == "3022" {
+        3022
+    } else if v == "3023" {
+        3023
+    } else if v == "3024" {
+        3024
+    } else if v == "3025" {
+        3025
+    } else if v == "3026" {
+        3026
+    } else if v == "3027" {
+        3027
+    } else if v == "3028" {
+        3028
+    } else if v == "3029" {
+        3029
+    } else if v == "3030" {
+        3030
+    } else if v == "3031" {
+        3031
+    } else if v == "3032" {
+        3032
+    } else if v == "3033" {
+        3033
+    } else if v == "3034" {
+        3034
+    } else if v == "3035" {
+        3035
+    } else if v == "3036" {
+        3036
+    } else if v == "3037" {
+        3037
+    } else if v == "3038" {
+        3038
+    } else if v == "3039" {
+        3039
+    } else if v == "3040" {
+        3040
+    } else if v == "3041" {
+        3041
+    } else if v == "3042" {
+        3042
+    } else if v == "3043" {
+        3043
+    } else if v == "3044" {
+        3044
+    } else if v == "3045" {
+        3045
+    } else if v == "3046" {
+        3046
+    } else if v == "3047" {
+        3047
+    } else if v == "3048" {
+        3048
+    } else if v == "3049" {
+        3049
+    } else if v == "3050" {
+        3050
+    } else if v == "3051" {
+        3051
+    } else if v == "3052" {
+        3052
+    } else if v == "3053" {
+        3053
+    } else if v == "3054" {
+        3054
+    } else if v == "3055" {
+        3055
+    } else if v == "3056" {
+        3056
+    } else if v == "3057" {
+        3057
+    } else if v == "3058" {
+        3058
+    } else if v == "3059" {
+        3059
+    } else if v == "3060" {
+        3060
+    } else if v == "3061" {
+        3061
+    } else if v == "3062" {
+        3062
+    } else if v == "3063" {
+        3063
+    } else if v == "3064" {
+        3064
+    } else if v == "3065" {
+        3065
+    } else if v == "3066" {
+        3066
+    } else if v == "3067" {
+        3067
+    } else if v == "3068" {
+        3068
+    } else if v == "3069" {
+        3069
+    } else if v == "3070" {
+        3070
+    } else if v == "3071" {
+        3071
+    } else if v == "3072" {
+        3072
+    } else if v == "3073" {
+        3073
+    } else if v == "3074" {
+        3074
+    } else if v == "3075" {
+        3075
+    } else if v == "3076" {
+        3076
+    } else if v == "3077" {
+        3077
+    } else if v == "3078" {
+        3078
+    } else if v == "3079" {
+        3079
+    } else if v == "3080" {
+        3080
+    } else if v == "3081" {
+        3081
+    } else if v == "3082" {
+        3082
+    } else if v == "3083" {
+        3083
+    } else if v == "3084" {
+        3084
+    } else if v == "3085" {
+        3085
+    } else if v == "3086" {
+        3086
+    } else if v == "3087" {
+        3087
+    } else if v == "3088" {
+        3088
+    } else if v == "3089" {
+        3089
+    } else if v == "3090" {
+        3090
+    } else if v == "3091" {
+        3091
+    } else if v == "3092" {
+        3092
+    } else if v == "3093" {
+        3093
+    } else if v == "3094" {
+        3094
+    } else if v == "3095" {
+        3095
+    } else if v == "3096" {
+        3096
+    } else if v == "3097" {
+        3097
+    } else if v == "3098" {
+        3098
+    } else if v == "3099" {
+        3099
+    } else if v == "3100" {
+        3100
+    } else if v == "3101" {
+        3101
+    } else if v == "3102" {
+        3102
+    } else if v == "3103" {
+        3103
+    } else if v == "3104" {
+        3104
+    } else if v == "3105" {
+        3105
+    } else if v == "3106" {
+        3106
+    } else if v == "3107" {
+        3107
+    } else if v == "3108" {
+        3108
+    } else if v == "3109" {
+        3109
+    } else if v == "3110" {
+        3110
+    } else if v == "3111" {
+        3111
+    } else if v == "3112" {
+        3112
+    } else if v == "3113" {
+        3113
+    } else if v == "3114" {
+        3114
+    } else if v == "3115" {
+        3115
+    } else if v == "3116" {
+        3116
+    } else if v == "3117" {
+        3117
+    } else if v == "3118" {
+        3118
+    } else if v == "3119" {
+        3119
+    } else if v == "3120" {
+        3120
+    } else if v == "3121" {
+        3121
+    } else if v == "3122" {
+        3122
+    } else if v == "3123" {
+        3123
+    } else if v == "3124" {
+        3124
+    } else if v == "3125" {
+        3125
+    } else if v == "3126" {
+        3126
+    } else if v == "3127" {
+        3127
+    } else if v == "3128" {
+        3128
+    } else if v == "3129" {
+        3129
+    } else if v == "3130" {
+        3130
+    } else if v == "3131" {
+        3131
+    } else if v == "3132" {
+        3132
+    } else if v == "3133" {
+        3133
+    } else if v == "3134" {
+        3134
+    } else if v == "3135" {
+        3135
+    } else if v == "3136" {
+        3136
+    } else if v == "3137" {
+        3137
+    } else if v == "3138" {
+        3138
+    } else if v == "3139" {
+        3139
+    } else if v == "3140" {
+        3140
+    } else if v == "3141" {
+        3141
+    } else if v == "3142" {
+        3142
+    } else if v == "3143" {
+        3143
+    } else if v == "3144" {
+        3144
+    } else if v == "3145" {
+        3145
+    } else if v == "3146" {
+        3146
+    } else if v == "3147" {
+        3147
+    } else if v == "3148" {
+        3148
+    } else if v == "3149" {
+        3149
+    } else if v == "3150" {
+        3150
+    } else if v == "3151" {
+        3151
+    } else if v == "3152" {
+        3152
+    } else if v == "3153" {
+        3153
+    } else if v == "3154" {
+        3154
+    } else if v == "3155" {
+        3155
+    } else if v == "3156" {
+        3156
+    } else if v == "3157" {
+        3157
+    } else if v == "3158" {
+        3158
+    } else if v == "3159" {
+        3159
+    } else if v == "3160" {
+        3160
+    } else if v == "3161" {
+        3161
+    } else if v == "3162" {
+        3162
+    } else if v == "3163" {
+        3163
+    } else if v == "3164" {
+        3164
+    } else if v == "3165" {
+        3165
+    } else if v == "3166" {
+        3166
+    } else if v == "3167" {
+        3167
+    } else if v == "3168" {
+        3168
+    } else if v == "3169" {
+        3169
+    } else if v == "3170" {
+        3170
+    } else if v == "3171" {
+        3171
+    } else if v == "3172" {
+        3172
+    } else if v == "3173" {
+        3173
+    } else if v == "3174" {
+        3174
+    } else if v == "3175" {
+        3175
+    } else if v == "3176" {
+        3176
+    } else if v == "3177" {
+        3177
+    } else if v == "3178" {
+        3178
+    } else if v == "3179" {
+        3179
+    } else if v == "3180" {
+        3180
+    } else if v == "3181" {
+        3181
+    } else if v == "3182" {
+        3182
+    } else if v == "3183" {
+        3183
+    } else if v == "3184" {
+        3184
+    } else if v == "3185" {
+        3185
+    } else if v == "3186" {
+        3186
+    } else if v == "3187" {
+        3187
+    } else if v == "3188" {
+        3188
+    } else if v == "3189" {
+        3189
+    } else if v == "3190" {
+        3190
+    } else if v == "3191" {
+        3191
+    } else if v == "3192" {
+        3192
+    } else if v == "3193" {
+        3193
+    } else if v == "3194" {
+        3194
+    } else if v == "3195" {
+        3195
+    } else if v == "3196" {
+        3196
+    } else if v == "3197" {
+        3197
+    } else if v == "3198" {
+        3198
+    } else if v == "3199" {
+        3199
+    } else if v == "3200" {
+        3200
+    } else if v == "3201" {
+        3201
+    } else if v == "3202" {
+        3202
+    } else if v == "3203" {
+        3203
+    } else if v == "3204" {
+        3204
+    } else if v == "3205" {
+        3205
+    } else if v == "3206" {
+        3206
+    } else if v == "3207" {
+        3207
+    } else if v == "3208" {
+        3208
+    } else if v == "3209" {
+        3209
+    } else if v == "3210" {
+        3210
+    } else if v == "3211" {
+        3211
+    } else if v == "3212" {
+        3212
+    } else if v == "3213" {
+        3213
+    } else if v == "3214" {
+        3214
+    } else if v == "3215" {
+        3215
+    } else if v == "3216" {
+        3216
+    } else if v == "3217" {
+        3217
+    } else if v == "3218" {
+        3218
+    } else if v == "3219" {
+        3219
+    } else if v == "3220" {
+        3220
+    } else if v == "3221" {
+        3221
+    } else if v == "3222" {
+        3222
+    } else if v == "3223" {
+        3223
+    } else if v == "3224" {
+        3224
+    } else if v == "3225" {
+        3225
+    } else if v == "3226" {
+        3226
+    } else if v == "3227" {
+        3227
+    } else if v == "3228" {
+        3228
+    } else if v == "3229" {
+        3229
+    } else if v == "3230" {
+        3230
+    } else if v == "3231" {
+        3231
+    } else if v == "3232" {
+        3232
+    } else if v == "3233" {
+        3233
+    } else if v == "3234" {
+        3234
+    } else if v == "3235" {
+        3235
+    } else if v == "3236" {
+        3236
+    } else if v == "3237" {
+        3237
+    } else if v == "3238" {
+        3238
+    } else if v == "3239" {
+        3239
+    } else if v == "3240" {
+        3240
+    } else if v == "3241" {
+        3241
+    } else if v == "3242" {
+        3242
+    } else if v == "3243" {
+        3243
+    } else if v == "3244" {
+        3244
+    } else if v == "3245" {
+        3245
+    } else if v == "3246" {
+        3246
+    } else if v == "3247" {
+        3247
+    } else if v == "3248" {
+        3248
+    } else if v == "3249" {
+        3249
+    } else if v == "3250" {
+        3250
+    } else if v == "3251" {
+        3251
+    } else if v == "3252" {
+        3252
+    } else if v == "3253" {
+        3253
+    } else if v == "3254" {
+        3254
+    } else if v == "3255" {
+        3255
+    } else if v == "3256" {
+        3256
+    } else if v == "3257" {
+        3257
+    } else if v == "3258" {
+        3258
+    } else if v == "3259" {
+        3259
+    } else if v == "3260" {
+        3260
+    } else if v == "3261" {
+        3261
+    } else if v == "3262" {
+        3262
+    } else if v == "3263" {
+        3263
+    } else if v == "3264" {
+        3264
+    } else if v == "3265" {
+        3265
+    } else if v == "3266" {
+        3266
+    } else if v == "3267" {
+        3267
+    } else if v == "3268" {
+        3268
+    } else if v == "3269" {
+        3269
+    } else if v == "3270" {
+        3270
+    } else if v == "3271" {
+        3271
+    } else if v == "3272" {
+        3272
+    } else if v == "3273" {
+        3273
+    } else if v == "3274" {
+        3274
+    } else if v == "3275" {
+        3275
+    } else if v == "3276" {
+        3276
+    } else if v == "3277" {
+        3277
+    } else if v == "3278" {
+        3278
+    } else if v == "3279" {
+        3279
+    } else if v == "3280" {
+        3280
+    } else if v == "3281" {
+        3281
+    } else if v == "3282" {
+        3282
+    } else if v == "3283" {
+        3283
+    } else if v == "3284" {
+        3284
+    } else if v == "3285" {
+        3285
+    } else if v == "3286" {
+        3286
+    } else if v == "3287" {
+        3287
+    } else if v == "3288" {
+        3288
+    } else if v == "3289" {
+        3289
+    } else if v == "3290" {
+        3290
+    } else if v == "3291" {
+        3291
+    } else if v == "3292" {
+        3292
+    } else if v == "3293" {
+        3293
+    } else if v == "3294" {
+        3294
+    } else if v == "3295" {
+        3295
+    } else if v == "3296" {
+        3296
+    } else if v == "3297" {
+        3297
+    } else if v == "3298" {
+        3298
+    } else if v == "3299" {
+        3299
+    } else if v == "3300" {
+        3300
+    } else if v == "3301" {
+        3301
+    } else if v == "3302" {
+        3302
+    } else if v == "3303" {
+        3303
+    } else if v == "3304" {
+        3304
+    } else if v == "3305" {
+        3305
+    } else if v == "3306" {
+        3306
+    } else if v == "3307" {
+        3307
+    } else if v == "3308" {
+        3308
+    } else if v == "3309" {
+        3309
+    } else if v == "3310" {
+        3310
+    } else if v == "3311" {
+        3311
+    } else if v == "3312" {
+        3312
+    } else if v == "3313" {
+        3313
+    } else if v == "3314" {
+        3314
+    } else if v == "3315" {
+        3315
+    } else if v == "3316" {
+        3316
+    } else if v == "3317" {
+        3317
+    } else if v == "3318" {
+        3318
+    } else if v == "3319" {
+        3319
+    } else if v == "3320" {
+        3320
+    } else if v == "3321" {
+        3321
+    } else if v == "3322" {
+        3322
+    } else if v == "3323" {
+        3323
+    } else if v == "3324" {
+        3324
+    } else if v == "3325" {
+        3325
+    } else if v == "3326" {
+        3326
+    } else if v == "3327" {
+        3327
+    } else if v == "3328" {
+        3328
+    } else if v == "3329" {
+        3329
+    } else if v == "3330" {
+        3330
+    } else if v == "3331" {
+        3331
+    } else if v == "3332" {
+        3332
+    } else if v == "3333" {
+        3333
+    } else if v == "3334" {
+        3334
+    } else if v == "3335" {
+        3335
+    } else if v == "3336" {
+        3336
+    } else if v == "3337" {
+        3337
+    } else if v == "3338" {
+        3338
+    } else if v == "3339" {
+        3339
+    } else if v == "3340" {
+        3340
+    } else if v == "3341" {
+        3341
+    } else if v == "3342" {
+        3342
+    } else if v == "3343" {
+        3343
+    } else if v == "3344" {
+        3344
+    } else if v == "3345" {
+        3345
+    } else if v == "3346" {
+        3346
+    } else if v == "3347" {
+        3347
+    } else if v == "3348" {
+        3348
+    } else if v == "3349" {
+        3349
+    } else if v == "3350" {
+        3350
+    } else if v == "3351" {
+        3351
+    } else if v == "3352" {
+        3352
+    } else if v == "3353" {
+        3353
+    } else if v == "3354" {
+        3354
+    } else if v == "3355" {
+        3355
+    } else if v == "3356" {
+        3356
+    } else if v == "3357" {
+        3357
+    } else if v == "3358" {
+        3358
+    } else if v == "3359" {
+        3359
+    } else if v == "3360" {
+        3360
+    } else if v == "3361" {
+        3361
+    } else if v == "3362" {
+        3362
+    } else if v == "3363" {
+        3363
+    } else if v == "3364" {
+        3364
+    } else if v == "3365" {
+        3365
+    } else if v == "3366" {
+        3366
+    } else if v == "3367" {
+        3367
+    } else if v == "3368" {
+        3368
+    } else if v == "3369" {
+        3369
+    } else if v == "3370" {
+        3370
+    } else if v == "3371" {
+        3371
+    } else if v == "3372" {
+        3372
+    } else if v == "3373" {
+        3373
+    } else if v == "3374" {
+        3374
+    } else if v == "3375" {
+        3375
+    } else if v == "3376" {
+        3376
+    } else if v == "3377" {
+        3377
+    } else if v == "3378" {
+        3378
+    } else if v == "3379" {
+        3379
+    } else if v == "3380" {
+        3380
+    } else if v == "3381" {
+        3381
+    } else if v == "3382" {
+        3382
+    } else if v == "3383" {
+        3383
+    } else if v == "3384" {
+        3384
+    } else if v == "3385" {
+        3385
+    } else if v == "3386" {
+        3386
+    } else if v == "3387" {
+        3387
+    } else if v == "3388" {
+        3388
+    } else if v == "3389" {
+        3389
+    } else if v == "3390" {
+        3390
+    } else if v == "3391" {
+        3391
+    } else if v == "3392" {
+        3392
+    } else if v == "3393" {
+        3393
+    } else if v == "3394" {
+        3394
+    } else if v == "3395" {
+        3395
+    } else if v == "3396" {
+        3396
+    } else if v == "3397" {
+        3397
+    } else if v == "3398" {
+        3398
+    } else if v == "3399" {
+        3399
+    } else if v == "3400" {
+        3400
+    } else if v == "3401" {
+        3401
+    } else if v == "3402" {
+        3402
+    } else if v == "3403" {
+        3403
+    } else if v == "3404" {
+        3404
+    } else if v == "3405" {
+        3405
+    } else if v == "3406" {
+        3406
+    } else if v == "3407" {
+        3407
+    } else if v == "3408" {
+        3408
+    } else if v == "3409" {
+        3409
+    } else if v == "3410" {
+        3410
+    } else if v == "3411" {
+        3411
+    } else if v == "3412" {
+        3412
+    } else if v == "3413" {
+        3413
+    } else if v == "3414" {
+        3414
+    } else if v == "3415" {
+        3415
+    } else if v == "3416" {
+        3416
+    } else if v == "3417" {
+        3417
+    } else if v == "3418" {
+        3418
+    } else if v == "3419" {
+        3419
+    } else if v == "3420" {
+        3420
+    } else if v == "3421" {
+        3421
+    } else if v == "3422" {
+        3422
+    } else if v == "3423" {
+        3423
+    } else if v == "3424" {
+        3424
+    } else if v == "3425" {
+        3425
+    } else if v == "3426" {
+        3426
+    } else if v == "3427" {
+        3427
+    } else if v == "3428" {
+        3428
+    } else if v == "3429" {
+        3429
+    } else if v == "3430" {
+        3430
+    } else if v == "3431" {
+        3431
+    } else if v == "3432" {
+        3432
+    } else if v == "3433" {
+        3433
+    } else if v == "3434" {
+        3434
+    } else if v == "3435" {
+        3435
+    } else if v == "3436" {
+        3436
+    } else if v == "3437" {
+        3437
+    } else if v == "3438" {
+        3438
+    } else if v == "3439" {
+        3439
+    } else if v == "3440" {
+        3440
+    } else if v == "3441" {
+        3441
+    } else if v == "3442" {
+        3442
+    } else if v == "3443" {
+        3443
+    } else if v == "3444" {
+        3444
+    } else if v == "3445" {
+        3445
+    } else if v == "3446" {
+        3446
+    } else if v == "3447" {
+        3447
+    } else if v == "3448" {
+        3448
+    } else if v == "3449" {
+        3449
+    } else if v == "3450" {
+        3450
+    } else if v == "3451" {
+        3451
+    } else if v == "3452" {
+        3452
+    } else if v == "3453" {
+        3453
+    } else if v == "3454" {
+        3454
+    } else if v == "3455" {
+        3455
+    } else if v == "3456" {
+        3456
+    } else if v == "3457" {
+        3457
+    } else if v == "3458" {
+        3458
+    } else if v == "3459" {
+        3459
+    } else if v == "3460" {
+        3460
+    } else if v == "3461" {
+        3461
+    } else if v == "3462" {
+        3462
+    } else if v == "3463" {
+        3463
+    } else if v == "3464" {
+        3464
+    } else if v == "3465" {
+        3465
+    } else if v == "3466" {
+        3466
+    } else if v == "3467" {
+        3467
+    } else if v == "3468" {
+        3468
+    } else if v == "3469" {
+        3469
+    } else if v == "3470" {
+        3470
+    } else if v == "3471" {
+        3471
+    } else if v == "3472" {
+        3472
+    } else if v == "3473" {
+        3473
+    } else if v == "3474" {
+        3474
+    } else if v == "3475" {
+        3475
+    } else if v == "3476" {
+        3476
+    } else if v == "3477" {
+        3477
+    } else if v == "3478" {
+        3478
+    } else if v == "3479" {
+        3479
+    } else if v == "3480" {
+        3480
+    } else if v == "3481" {
+        3481
+    } else if v == "3482" {
+        3482
+    } else if v == "3483" {
+        3483
+    } else if v == "3484" {
+        3484
+    } else if v == "3485" {
+        3485
+    } else if v == "3486" {
+        3486
+    } else if v == "3487" {
+        3487
+    } else if v == "3488" {
+        3488
+    } else if v == "3489" {
+        3489
+    } else if v == "3490" {
+        3490
+    } else if v == "3491" {
+        3491
+    } else if v == "3492" {
+        3492
+    } else if v == "3493" {
+        3493
+    } else if v == "3494" {
+        3494
+    } else if v == "3495" {
+        3495
+    } else if v == "3496" {
+        3496
+    } else if v == "3497" {
+        3497
+    } else if v == "3498" {
+        3498
+    } else if v == "3499" {
+        3499
+    } else if v == "3500" {
+        3500
+    } else if v == "3501" {
+        3501
+    } else if v == "3502" {
+        3502
+    } else if v == "3503" {
+        3503
+    } else if v == "3504" {
+        3504
+    } else if v == "3505" {
+        3505
+    } else if v == "3506" {
+        3506
+    } else if v == "3507" {
+        3507
+    } else if v == "3508" {
+        3508
+    } else if v == "3509" {
+        3509
+    } else if v == "3510" {
+        3510
+    } else if v == "3511" {
+        3511
+    } else if v == "3512" {
+        3512
+    } else if v == "3513" {
+        3513
+    } else if v == "3514" {
+        3514
+    } else if v == "3515" {
+        3515
+    } else if v == "3516" {
+        3516
+    } else if v == "3517" {
+        3517
+    } else if v == "3518" {
+        3518
+    } else if v == "3519" {
+        3519
+    } else if v == "3520" {
+        3520
+    } else if v == "3521" {
+        3521
+    } else if v == "3522" {
+        3522
+    } else if v == "3523" {
+        3523
+    } else if v == "3524" {
+        3524
+    } else if v == "3525" {
+        3525
+    } else if v == "3526" {
+        3526
+    } else if v == "3527" {
+        3527
+    } else if v == "3528" {
+        3528
+    } else if v == "3529" {
+        3529
+    } else if v == "3530" {
+        3530
+    } else if v == "3531" {
+        3531
+    } else if v == "3532" {
+        3532
+    } else if v == "3533" {
+        3533
+    } else if v == "3534" {
+        3534
+    } else if v == "3535" {
+        3535
+    } else if v == "3536" {
+        3536
+    } else if v == "3537" {
+        3537
+    } else if v == "3538" {
+        3538
+    } else if v == "3539" {
+        3539
+    } else if v == "3540" {
+        3540
+    } else if v == "3541" {
+        3541
+    } else if v == "3542" {
+        3542
+    } else if v == "3543" {
+        3543
+    } else if v == "3544" {
+        3544
+    } else if v == "3545" {
+        3545
+    } else if v == "3546" {
+        3546
+    } else if v == "3547" {
+        3547
+    } else if v == "3548" {
+        3548
+    } else if v == "3549" {
+        3549
+    } else if v == "3550" {
+        3550
+    } else if v == "3551" {
+        3551
+    } else if v == "3552" {
+        3552
+    } else if v == "3553" {
+        3553
+    } else if v == "3554" {
+        3554
+    } else if v == "3555" {
+        3555
+    } else if v == "3556" {
+        3556
+    } else if v == "3557" {
+        3557
+    } else if v == "3558" {
+        3558
+    } else if v == "3559" {
+        3559
+    } else if v == "3560" {
+        3560
+    } else if v == "3561" {
+        3561
+    } else if v == "3562" {
+        3562
+    } else if v == "3563" {
+        3563
+    } else if v == "3564" {
+        3564
+    } else if v == "3565" {
+        3565
+    } else if v == "3566" {
+        3566
+    } else if v == "3567" {
+        3567
+    } else if v == "3568" {
+        3568
+    } else if v == "3569" {
+        3569
+    } else if v == "3570" {
+        3570
+    } else if v == "3571" {
+        3571
+    } else if v == "3572" {
+        3572
+    } else if v == "3573" {
+        3573
+    } else if v == "3574" {
+        3574
+    } else if v == "3575" {
+        3575
+    } else if v == "3576" {
+        3576
+    } else if v == "3577" {
+        3577
+    } else if v == "3578" {
+        3578
+    } else if v == "3579" {
+        3579
+    } else if v == "3580" {
+        3580
+    } else if v == "3581" {
+        3581
+    } else if v == "3582" {
+        3582
+    } else if v == "3583" {
+        3583
+    } else if v == "3584" {
+        3584
+    } else if v == "3585" {
+        3585
+    } else if v == "3586" {
+        3586
+    } else if v == "3587" {
+        3587
+    } else if v == "3588" {
+        3588
+    } else if v == "3589" {
+        3589
+    } else if v == "3590" {
+        3590
+    } else if v == "3591" {
+        3591
+    } else if v == "3592" {
+        3592
+    } else if v == "3593" {
+        3593
+    } else if v == "3594" {
+        3594
+    } else if v == "3595" {
+        3595
+    } else if v == "3596" {
+        3596
+    } else if v == "3597" {
+        3597
+    } else if v == "3598" {
+        3598
+    } else if v == "3599" {
+        3599
+    } else if v == "3600" {
+        3600
+    } else if v == "3601" {
+        3601
+    } else if v == "3602" {
+        3602
+    } else if v == "3603" {
+        3603
+    } else if v == "3604" {
+        3604
+    } else if v == "3605" {
+        3605
+    } else if v == "3606" {
+        3606
+    } else if v == "3607" {
+        3607
+    } else if v == "3608" {
+        3608
+    } else if v == "3609" {
+        3609
+    } else if v == "3610" {
+        3610
+    } else if v == "3611" {
+        3611
+    } else if v == "3612" {
+        3612
+    } else if v == "3613" {
+        3613
+    } else if v == "3614" {
+        3614
+    } else if v == "3615" {
+        3615
+    } else if v == "3616" {
+        3616
+    } else if v == "3617" {
+        3617
+    } else if v == "3618" {
+        3618
+    } else if v == "3619" {
+        3619
+    } else if v == "3620" {
+        3620
+    } else if v == "3621" {
+        3621
+    } else if v == "3622" {
+        3622
+    } else if v == "3623" {
+        3623
+    } else if v == "3624" {
+        3624
+    } else if v == "3625" {
+        3625
+    } else if v == "3626" {
+        3626
+    } else if v == "3627" {
+        3627
+    } else if v == "3628" {
+        3628
+    } else if v == "3629" {
+        3629
+    } else if v == "3630" {
+        3630
+    } else if v == "3631" {
+        3631
+    } else if v == "3632" {
+        3632
+    } else if v == "3633" {
+        3633
+    } else if v == "3634" {
+        3634
+    } else if v == "3635" {
+        3635
+    } else if v == "3636" {
+        3636
+    } else if v == "3637" {
+        3637
+    } else if v == "3638" {
+        3638
+    } else if v == "3639" {
+        3639
+    } else if v == "3640" {
+        3640
+    } else if v == "3641" {
+        3641
+    } else if v == "3642" {
+        3642
+    } else if v == "3643" {
+        3643
+    } else if v == "3644" {
+        3644
+    } else if v == "3645" {
+        3645
+    } else if v == "3646" {
+        3646
+    } else if v == "3647" {
+        3647
+    } else if v == "3648" {
+        3648
+    } else if v == "3649" {
+        3649
+    } else if v == "3650" {
+        3650
+    } else if v == "3651" {
+        3651
+    } else if v == "3652" {
+        3652
+    } else if v == "3653" {
+        3653
+    } else if v == "3654" {
+        3654
+    } else if v == "3655" {
+        3655
+    } else if v == "3656" {
+        3656
+    } else if v == "3657" {
+        3657
+    } else if v == "3658" {
+        3658
+    } else if v == "3659" {
+        3659
+    } else if v == "3660" {
+        3660
+    } else if v == "3661" {
+        3661
+    } else if v == "3662" {
+        3662
+    } else if v == "3663" {
+        3663
+    } else if v == "3664" {
+        3664
+    } else if v == "3665" {
+        3665
+    } else if v == "3666" {
+        3666
+    } else if v == "3667" {
+        3667
+    } else if v == "3668" {
+        3668
+    } else if v == "3669" {
+        3669
+    } else if v == "3670" {
+        3670
+    } else if v == "3671" {
+        3671
+    } else if v == "3672" {
+        3672
+    } else if v == "3673" {
+        3673
+    } else if v == "3674" {
+        3674
+    } else if v == "3675" {
+        3675
+    } else if v == "3676" {
+        3676
+    } else if v == "3677" {
+        3677
+    } else if v == "3678" {
+        3678
+    } else if v == "3679" {
+        3679
+    } else if v == "3680" {
+        3680
+    } else if v == "3681" {
+        3681
+    } else if v == "3682" {
+        3682
+    } else if v == "3683" {
+        3683
+    } else if v == "3684" {
+        3684
+    } else if v == "3685" {
+        3685
+    } else if v == "3686" {
+        3686
+    } else if v == "3687" {
+        3687
+    } else if v == "3688" {
+        3688
+    } else if v == "3689" {
+        3689
+    } else if v == "3690" {
+        3690
+    } else if v == "3691" {
+        3691
+    } else if v == "3692" {
+        3692
+    } else if v == "3693" {
+        3693
+    } else if v == "3694" {
+        3694
+    } else if v == "3695" {
+        3695
+    } else if v == "3696" {
+        3696
+    } else if v == "3697" {
+        3697
+    } else if v == "3698" {
+        3698
+    } else if v == "3699" {
+        3699
+    } else if v == "3700" {
+        3700
+    } else if v == "3701" {
+        3701
+    } else if v == "3702" {
+        3702
+    } else if v == "3703" {
+        3703
+    } else if v == "3704" {
+        3704
+    } else if v == "3705" {
+        3705
+    } else if v == "3706" {
+        3706
+    } else if v == "3707" {
+        3707
+    } else if v == "3708" {
+        3708
+    } else if v == "3709" {
+        3709
+    } else if v == "3710" {
+        3710
+    } else if v == "3711" {
+        3711
+    } else if v == "3712" {
+        3712
+    } else if v == "3713" {
+        3713
+    } else if v == "3714" {
+        3714
+    } else if v == "3715" {
+        3715
+    } else if v == "3716" {
+        3716
+    } else if v == "3717" {
+        3717
+    } else if v == "3718" {
+        3718
+    } else if v == "3719" {
+        3719
+    } else if v == "3720" {
+        3720
+    } else if v == "3721" {
+        3721
+    } else if v == "3722" {
+        3722
+    } else if v == "3723" {
+        3723
+    } else if v == "3724" {
+        3724
+    } else if v == "3725" {
+        3725
+    } else if v == "3726" {
+        3726
+    } else if v == "3727" {
+        3727
+    } else if v == "3728" {
+        3728
+    } else if v == "3729" {
+        3729
+    } else if v == "3730" {
+        3730
+    } else if v == "3731" {
+        3731
+    } else if v == "3732" {
+        3732
+    } else if v == "3733" {
+        3733
+    } else if v == "3734" {
+        3734
+    } else if v == "3735" {
+        3735
+    } else if v == "3736" {
+        3736
+    } else if v == "3737" {
+        3737
+    } else if v == "3738" {
+        3738
+    } else if v == "3739" {
+        3739
+    } else if v == "3740" {
+        3740
+    } else if v == "3741" {
+        3741
+    } else if v == "3742" {
+        3742
+    } else if v == "3743" {
+        3743
+    } else if v == "3744" {
+        3744
+    } else if v == "3745" {
+        3745
+    } else if v == "3746" {
+        3746
+    } else if v == "3747" {
+        3747
+    } else if v == "3748" {
+        3748
+    } else if v == "3749" {
+        3749
+    } else if v == "3750" {
+        3750
+    } else if v == "3751" {
+        3751
+    } else if v == "3752" {
+        3752
+    } else if v == "3753" {
+        3753
+    } else if v == "3754" {
+        3754
+    } else if v == "3755" {
+        3755
+    } else if v == "3756" {
+        3756
+    } else if v == "3757" {
+        3757
+    } else if v == "3758" {
+        3758
+    } else if v == "3759" {
+        3759
+    } else if v == "3760" {
+        3760
+    } else if v == "3761" {
+        3761
+    } else if v == "3762" {
+        3762
+    } else if v == "3763" {
+        3763
+    } else if v == "3764" {
+        3764
+    } else if v == "3765" {
+        3765
+    } else if v == "3766" {
+        3766
+    } else if v == "3767" {
+        3767
+    } else if v == "3768" {
+        3768
+    } else if v == "3769" {
+        3769
+    } else if v == "3770" {
+        3770
+    } else if v == "3771" {
+        3771
+    } else if v == "3772" {
+        3772
+    } else if v == "3773" {
+        3773
+    } else if v == "3774" {
+        3774
+    } else if v == "3775" {
+        3775
+    } else if v == "3776" {
+        3776
+    } else if v == "3777" {
+        3777
+    } else if v == "3778" {
+        3778
+    } else if v == "3779" {
+        3779
+    } else if v == "3780" {
+        3780
+    } else if v == "3781" {
+        3781
+    } else if v == "3782" {
+        3782
+    } else if v == "3783" {
+        3783
+    } else if v == "3784" {
+        3784
+    } else if v == "3785" {
+        3785
+    } else if v == "3786" {
+        3786
+    } else if v == "3787" {
+        3787
+    } else if v == "3788" {
+        3788
+    } else if v == "3789" {
+        3789
+    } else if v == "3790" {
+        3790
+    } else if v == "3791" {
+        3791
+    } else if v == "3792" {
+        3792
+    } else if v == "3793" {
+        3793
+    } else if v == "3794" {
+        3794
+    } else if v == "3795" {
+        3795
+    } else if v == "3796" {
+        3796
+    } else if v == "3797" {
+        3797
+    } else if v == "3798" {
+        3798
+    } else if v == "3799" {
+        3799
+    } else if v == "3800" {
+        3800
+    } else if v == "3801" {
+        3801
+    } else if v == "3802" {
+        3802
+    } else if v == "3803" {
+        3803
+    } else if v == "3804" {
+        3804
+    } else if v == "3805" {
+        3805
+    } else if v == "3806" {
+        3806
+    } else if v == "3807" {
+        3807
+    } else if v == "3808" {
+        3808
+    } else if v == "3809" {
+        3809
+    } else if v == "3810" {
+        3810
+    } else if v == "3811" {
+        3811
+    } else if v == "3812" {
+        3812
+    } else if v == "3813" {
+        3813
+    } else if v == "3814" {
+        3814
+    } else if v == "3815" {
+        3815
+    } else if v == "3816" {
+        3816
+    } else if v == "3817" {
+        3817
+    } else if v == "3818" {
+        3818
+    } else if v == "3819" {
+        3819
+    } else if v == "3820" {
+        3820
+    } else if v == "3821" {
+        3821
+    } else if v == "3822" {
+        3822
+    } else if v == "3823" {
+        3823
+    } else if v == "3824" {
+        3824
+    } else if v == "3825" {
+        3825
+    } else if v == "3826" {
+        3826
+    } else if v == "3827" {
+        3827
+    } else if v == "3828" {
+        3828
+    } else if v == "3829" {
+        3829
+    } else if v == "3830" {
+        3830
+    } else if v == "3831" {
+        3831
+    } else if v == "3832" {
+        3832
+    } else if v == "3833" {
+        3833
+    } else if v == "3834" {
+        3834
+    } else if v == "3835" {
+        3835
+    } else if v == "3836" {
+        3836
+    } else if v == "3837" {
+        3837
+    } else if v == "3838" {
+        3838
+    } else if v == "3839" {
+        3839
+    } else if v == "3840" {
+        3840
+    } else if v == "3841" {
+        3841
+    } else if v == "3842" {
+        3842
+    } else if v == "3843" {
+        3843
+    } else if v == "3844" {
+        3844
+    } else if v == "3845" {
+        3845
+    } else if v == "3846" {
+        3846
+    } else if v == "3847" {
+        3847
+    } else if v == "3848" {
+        3848
+    } else if v == "3849" {
+        3849
+    } else if v == "3850" {
+        3850
+    } else if v == "3851" {
+        3851
+    } else if v == "3852" {
+        3852
+    } else if v == "3853" {
+        3853
+    } else if v == "3854" {
+        3854
+    } else if v == "3855" {
+        3855
+    } else if v == "3856" {
+        3856
+    } else if v == "3857" {
+        3857
+    } else if v == "3858" {
+        3858
+    } else if v == "3859" {
+        3859
+    } else if v == "3860" {
+        3860
+    } else if v == "3861" {
+        3861
+    } else if v == "3862" {
+        3862
+    } else if v == "3863" {
+        3863
+    } else if v == "3864" {
+        3864
+    } else if v == "3865" {
+        3865
+    } else if v == "3866" {
+        3866
+    } else if v == "3867" {
+        3867
+    } else if v == "3868" {
+        3868
+    } else if v == "3869" {
+        3869
+    } else if v == "3870" {
+        3870
+    } else if v == "3871" {
+        3871
+    } else if v == "3872" {
+        3872
+    } else if v == "3873" {
+        3873
+    } else if v == "3874" {
+        3874
+    } else if v == "3875" {
+        3875
+    } else if v == "3876" {
+        3876
+    } else if v == "3877" {
+        3877
+    } else if v == "3878" {
+        3878
+    } else if v == "3879" {
+        3879
+    } else if v == "3880" {
+        3880
+    } else if v == "3881" {
+        3881
+    } else if v == "3882" {
+        3882
+    } else if v == "3883" {
+        3883
+    } else if v == "3884" {
+        3884
+    } else if v == "3885" {
+        3885
+    } else if v == "3886" {
+        3886
+    } else if v == "3887" {
+        3887
+    } else if v == "3888" {
+        3888
+    } else if v == "3889" {
+        3889
+    } else if v == "3890" {
+        3890
+    } else if v == "3891" {
+        3891
+    } else if v == "3892" {
+        3892
+    } else if v == "3893" {
+        3893
+    } else if v == "3894" {
+        3894
+    } else if v == "3895" {
+        3895
+    } else if v == "3896" {
+        3896
+    } else if v == "3897" {
+        3897
+    } else if v == "3898" {
+        3898
+    } else if v == "3899" {
+        3899
+    } else if v == "3900" {
+        3900
+    } else if v == "3901" {
+        3901
+    } else if v == "3902" {
+        3902
+    } else if v == "3903" {
+        3903
+    } else if v == "3904" {
+        3904
+    } else if v == "3905" {
+        3905
+    } else if v == "3906" {
+        3906
+    } else if v == "3907" {
+        3907
+    } else if v == "3908" {
+        3908
+    } else if v == "3909" {
+        3909
+    } else if v == "3910" {
+        3910
+    } else if v == "3911" {
+        3911
+    } else if v == "3912" {
+        3912
+    } else if v == "3913" {
+        3913
+    } else if v == "3914" {
+        3914
+    } else if v == "3915" {
+        3915
+    } else if v == "3916" {
+        3916
+    } else if v == "3917" {
+        3917
+    } else if v == "3918" {
+        3918
+    } else if v == "3919" {
+        3919
+    } else if v == "3920" {
+        3920
+    } else if v == "3921" {
+        3921
+    } else if v == "3922" {
+        3922
+    } else if v == "3923" {
+        3923
+    } else if v == "3924" {
+        3924
+    } else if v == "3925" {
+        3925
+    } else if v == "3926" {
+        3926
+    } else if v == "3927" {
+        3927
+    } else if v == "3928" {
+        3928
+    } else if v == "3929" {
+        3929
+    } else if v == "3930" {
+        3930
+    } else if v == "3931" {
+        3931
+    } else if v == "3932" {
+        3932
+    } else if v == "3933" {
+        3933
+    } else if v == "3934" {
+        3934
+    } else if v == "3935" {
+        3935
+    } else if v == "3936" {
+        3936
+    } else if v == "3937" {
+        3937
+    } else if v == "3938" {
+        3938
+    } else if v == "3939" {
+        3939
+    } else if v == "3940" {
+        3940
+    } else if v == "3941" {
+        3941
+    } else if v == "3942" {
+        3942
+    } else if v == "3943" {
+        3943
+    } else if v == "3944" {
+        3944
+    } else if v == "3945" {
+        3945
+    } else if v == "3946" {
+        3946
+    } else if v == "3947" {
+        3947
+    } else if v == "3948" {
+        3948
+    } else if v == "3949" {
+        3949
+    } else if v == "3950" {
+        3950
+    } else if v == "3951" {
+        3951
+    } else if v == "3952" {
+        3952
+    } else if v == "3953" {
+        3953
+    } else if v == "3954" {
+        3954
+    } else if v == "3955" {
+        3955
+    } else if v == "3956" {
+        3956
+    } else if v == "3957" {
+        3957
+    } else if v == "3958" {
+        3958
+    } else if v == "3959" {
+        3959
+    } else if v == "3960" {
+        3960
+    } else if v == "3961" {
+        3961
+    } else if v == "3962" {
+        3962
+    } else if v == "3963" {
+        3963
+    } else if v == "3964" {
+        3964
+    } else if v == "3965" {
+        3965
+    } else if v == "3966" {
+        3966
+    } else if v == "3967" {
+        3967
+    } else if v == "3968" {
+        3968
+    } else if v == "3969" {
+        3969
+    } else if v == "3970" {
+        3970
+    } else if v == "3971" {
+        3971
+    } else if v == "3972" {
+        3972
+    } else if v == "3973" {
+        3973
+    } else if v == "3974" {
+        3974
+    } else if v == "3975" {
+        3975
+    } else if v == "3976" {
+        3976
+    } else if v == "3977" {
+        3977
+    } else if v == "3978" {
+        3978
+    } else if v == "3979" {
+        3979
+    } else if v == "3980" {
+        3980
+    } else if v == "3981" {
+        3981
+    } else if v == "3982" {
+        3982
+    } else if v == "3983" {
+        3983
+    } else if v == "3984" {
+        3984
+    } else if v == "3985" {
+        3985
+    } else if v == "3986" {
+        3986
+    } else if v == "3987" {
+        3987
+    } else if v == "3988" {
+        3988
+    } else if v == "3989" {
+        3989
+    } else if v == "3990" {
+        3990
+    } else if v == "3991" {
+        3991
+    } else if v == "3992" {
+        3992
+    } else if v == "3993" {
+        3993
+    } else if v == "3994" {
+        3994
+    } else if v == "3995" {
+        3995
+    } else if v == "3996" {
+        3996
+    } else if v == "3997" {
+        3997
+    } else if v == "3998" {
+        3998
+    } else if v == "3999" {
+        3999
+    } else if v == "4000" {
+        4000
+    } else if v == "4001" {
+        4001
+    } else if v == "4002" {
+        4002
+    } else if v == "4003" {
+        4003
+    } else if v == "4004" {
+        4004
+    } else if v == "4005" {
+        4005
+    } else if v == "4006" {
+        4006
+    } else if v == "4007" {
+        4007
+    } else if v == "4008" {
+        4008
+    } else if v == "4009" {
+        4009
+    } else if v == "4010" {
+        4010
+    } else if v == "4011" {
+        4011
+    } else if v == "4012" {
+        4012
+    } else if v == "4013" {
+        4013
+    } else if v == "4014" {
+        4014
+    } else if v == "4015" {
+        4015
+    } else if v == "4016" {
+        4016
+    } else if v == "4017" {
+        4017
+    } else if v == "4018" {
+        4018
+    } else if v == "4019" {
+        4019
+    } else if v == "4020" {
+        4020
+    } else if v == "4021" {
+        4021
+    } else if v == "4022" {
+        4022
+    } else if v == "4023" {
+        4023
+    } else if v == "4024" {
+        4024
+    } else if v == "4025" {
+        4025
+    } else if v == "4026" {
+        4026
+    } else if v == "4027" {
+        4027
+    } else if v == "4028" {
+        4028
+    } else if v == "4029" {
+        4029
+    } else if v == "4030" {
+        4030
+    } else if v == "4031" {
+        4031
+    } else if v == "4032" {
+        4032
+    } else if v == "4033" {
+        4033
+    } else if v == "4034" {
+        4034
+    } else if v == "4035" {
+        4035
+    } else if v == "4036" {
+        4036
+    } else if v == "4037" {
+        4037
+    } else if v == "4038" {
+        4038
+    } else if v == "4039" {
+        4039
+    } else if v == "4040" {
+        4040
+    } else if v == "4041" {
+        4041
+    } else if v == "4042" {
+        4042
+    } else if v == "4043" {
+        4043
+    } else if v == "4044" {
+        4044
+    } else if v == "4045" {
+        4045
+    } else if v == "4046" {
+        4046
+    } else if v == "4047" {
+        4047
+    } else if v == "4048" {
+        4048
+    } else if v == "4049" {
+        4049
+    } else if v == "4050" {
+        4050
+    } else if v == "4051" {
+        4051
+    } else if v == "4052" {
+        4052
+    } else if v == "4053" {
+        4053
+    } else if v == "4054" {
+        4054
+    } else if v == "4055" {
+        4055
+    } else if v == "4056" {
+        4056
+    } else if v == "4057" {
+        4057
+    } else if v == "4058" {
+        4058
+    } else if v == "4059" {
+        4059
+    } else if v == "4060" {
+        4060
+    } else if v == "4061" {
+        4061
+    } else if v == "4062" {
+        4062
+    } else if v == "4063" {
+        4063
+    } else if v == "4064" {
+        4064
+    } else if v == "4065" {
+        4065
+    } else if v == "4066" {
+        4066
+    } else if v == "4067" {
+        4067
+    } else if v == "4068" {
+        4068
+    } else if v == "4069" {
+        4069
+    } else if v == "4070" {
+        4070
+    } else if v == "4071" {
+        4071
+    } else if v == "4072" {
+        4072
+    } else if v == "4073" {
+        4073
+    } else if v == "4074" {
+        4074
+    } else if v == "4075" {
+        4075
+    } else if v == "4076" {
+        4076
+    } else if v == "4077" {
+        4077
+    } else if v == "4078" {
+        4078
+    } else if v == "4079" {
+        4079
+    } else if v == "4080" {
+        4080
+    } else if v == "4081" {
+        4081
+    } else if v == "4082" {
+        4082
+    } else if v == "4083" {
+        4083
+    } else if v == "4084" {
+        4084
+    } else if v == "4085" {
+        4085
+    } else if v == "4086" {
+        4086
+    } else if v == "4087" {
+        4087
+    } else if v == "4088" {
+        4088
+    } else if v == "4089" {
+        4089
+    } else if v == "4090" {
+        4090
+    } else if v == "4091" {
+        4091
+    } else if v == "4092" {
+        4092
+    } else if v == "4093" {
+        4093
+    } else if v == "4094" {
+        4094
+    } else if v == "4095" {
+        4095
+    } else if v == "4096" {
+        4096
+    } else if v == "4097" {
+        4097
+    } else if v == "4098" {
+        4098
+    } else if v == "4099" {
+        4099
+    } else if v == "4100" {
+        4100
+    } else if v == "4101" {
+        4101
+    } else if v == "4102" {
+        4102
+    } else if v == "4103" {
+        4103
+    } else if v == "4104" {
+        4104
+    } else if v == "4105" {
+        4105
+    } else if v == "4106" {
+        4106
+    } else if v == "4107" {
+        4107
+    } else if v == "4108" {
+        4108
+    } else if v == "4109" {
+        4109
+    } else if v == "4110" {
+        4110
+    } else if v == "4111" {
+        4111
+    } else if v == "4112" {
+        4112
+    } else if v == "4113" {
+        4113
+    } else if v == "4114" {
+        4114
+    } else if v == "4115" {
+        4115
+    } else if v == "4116" {
+        4116
+    } else if v == "4117" {
+        4117
+    } else if v == "4118" {
+        4118
+    } else if v == "4119" {
+        4119
+    } else if v == "4120" {
+        4120
+    } else if v == "4121" {
+        4121
+    } else if v == "4122" {
+        4122
+    } else if v == "4123" {
+        4123
+    } else if v == "4124" {
+        4124
+    } else if v == "4125" {
+        4125
+    } else if v == "4126" {
+        4126
+    } else if v == "4127" {
+        4127
+    } else if v == "4128" {
+        4128
+    } else if v == "4129" {
+        4129
+    } else if v == "4130" {
+        4130
+    } else if v == "4131" {
+        4131
+    } else if v == "4132" {
+        4132
+    } else if v == "4133" {
+        4133
+    } else if v == "4134" {
+        4134
+    } else if v == "4135" {
+        4135
+    } else if v == "4136" {
+        4136
+    } else if v == "4137" {
+        4137
+    } else if v == "4138" {
+        4138
+    } else if v == "4139" {
+        4139
+    } else if v == "4140" {
+        4140
+    } else if v == "4141" {
+        4141
+    } else if v == "4142" {
+        4142
+    } else if v == "4143" {
+        4143
+    } else if v == "4144" {
+        4144
+    } else if v == "4145" {
+        4145
+    } else if v == "4146" {
+        4146
+    } else if v == "4147" {
+        4147
+    } else if v == "4148" {
+        4148
+    } else if v == "4149" {
+        4149
+    } else if v == "4150" {
+        4150
+    } else if v == "4151" {
+        4151
+    } else if v == "4152" {
+        4152
+    } else if v == "4153" {
+        4153
+    } else if v == "4154" {
+        4154
+    } else if v == "4155" {
+        4155
+    } else if v == "4156" {
+        4156
+    } else if v == "4157" {
+        4157
+    } else if v == "4158" {
+        4158
+    } else if v == "4159" {
+        4159
+    } else if v == "4160" {
+        4160
+    } else if v == "4161" {
+        4161
+    } else if v == "4162" {
+        4162
+    } else if v == "4163" {
+        4163
+    } else if v == "4164" {
+        4164
+    } else if v == "4165" {
+        4165
+    } else if v == "4166" {
+        4166
+    } else if v == "4167" {
+        4167
+    } else if v == "4168" {
+        4168
+    } else if v == "4169" {
+        4169
+    } else if v == "4170" {
+        4170
+    } else if v == "4171" {
+        4171
+    } else if v == "4172" {
+        4172
+    } else if v == "4173" {
+        4173
+    } else if v == "4174" {
+        4174
+    } else if v == "4175" {
+        4175
+    } else if v == "4176" {
+        4176
+    } else if v == "4177" {
+        4177
+    } else if v == "4178" {
+        4178
+    } else if v == "4179" {
+        4179
+    } else if v == "4180" {
+        4180
+    } else if v == "4181" {
+        4181
+    } else if v == "4182" {
+        4182
+    } else if v == "4183" {
+        4183
+    } else if v == "4184" {
+        4184
+    } else if v == "4185" {
+        4185
+    } else if v == "4186" {
+        4186
+    } else if v == "4187" {
+        4187
+    } else if v == "4188" {
+        4188
+    } else if v == "4189" {
+        4189
+    } else if v == "4190" {
+        4190
+    } else if v == "4191" {
+        4191
+    } else if v == "4192" {
+        4192
+    } else if v == "4193" {
+        4193
+    } else if v == "4194" {
+        4194
+    } else if v == "4195" {
+        4195
+    } else if v == "4196" {
+        4196
+    } else if v == "4197" {
+        4197
+    } else if v == "4198" {
+        4198
+    } else if v == "4199" {
+        4199
+    } else if v == "4200" {
+        4200
+    } else if v == "4201" {
+        4201
+    } else if v == "4202" {
+        4202
+    } else if v == "4203" {
+        4203
+    } else if v == "4204" {
+        4204
+    } else if v == "4205" {
+        4205
+    } else if v == "4206" {
+        4206
+    } else if v == "4207" {
+        4207
+    } else if v == "4208" {
+        4208
+    } else if v == "4209" {
+        4209
+    } else if v == "4210" {
+        4210
+    } else if v == "4211" {
+        4211
+    } else if v == "4212" {
+        4212
+    } else if v == "4213" {
+        4213
+    } else if v == "4214" {
+        4214
+    } else if v == "4215" {
+        4215
+    } else if v == "4216" {
+        4216
+    } else if v == "4217" {
+        4217
+    } else if v == "4218" {
+        4218
+    } else if v == "4219" {
+        4219
+    } else if v == "4220" {
+        4220
+    } else if v == "4221" {
+        4221
+    } else if v == "4222" {
+        4222
+    } else if v == "4223" {
+        4223
+    } else if v == "4224" {
+        4224
+    } else if v == "4225" {
+        4225
+    } else if v == "4226" {
+        4226
+    } else if v == "4227" {
+        4227
+    } else if v == "4228" {
+        4228
+    } else if v == "4229" {
+        4229
+    } else if v == "4230" {
+        4230
+    } else if v == "4231" {
+        4231
+    } else if v == "4232" {
+        4232
+    } else if v == "4233" {
+        4233
+    } else if v == "4234" {
+        4234
+    } else if v == "4235" {
+        4235
+    } else if v == "4236" {
+        4236
+    } else if v == "4237" {
+        4237
+    } else if v == "4238" {
+        4238
+    } else if v == "4239" {
+        4239
+    } else if v == "4240" {
+        4240
+    } else if v == "4241" {
+        4241
+    } else if v == "4242" {
+        4242
+    } else if v == "4243" {
+        4243
+    } else if v == "4244" {
+        4244
+    } else if v == "4245" {
+        4245
+    } else if v == "4246" {
+        4246
+    } else if v == "4247" {
+        4247
+    } else if v == "4248" {
+        4248
+    } else if v == "4249" {
+        4249
+    } else if v == "4250" {
+        4250
+    } else if v == "4251" {
+        4251
+    } else if v == "4252" {
+        4252
+    } else if v == "4253" {
+        4253
+    } else if v == "4254" {
+        4254
+    } else if v == "4255" {
+        4255
+    } else if v == "4256" {
+        4256
+    } else if v == "4257" {
+        4257
+    } else if v == "4258" {
+        4258
+    } else if v == "4259" {
+        4259
+    } else if v == "4260" {
+        4260
+    } else if v == "4261" {
+        4261
+    } else if v == "4262" {
+        4262
+    } else if v == "4263" {
+        4263
+    } else if v == "4264" {
+        4264
+    } else if v == "4265" {
+        4265
+    } else if v == "4266" {
+        4266
+    } else if v == "4267" {
+        4267
+    } else if v == "4268" {
+        4268
+    } else if v == "4269" {
+        4269
+    } else if v == "4270" {
+        4270
+    } else if v == "4271" {
+        4271
+    } else if v == "4272" {
+        4272
+    } else if v == "4273" {
+        4273
+    } else if v == "4274" {
+        4274
+    } else if v == "4275" {
+        4275
+    } else if v == "4276" {
+        4276
+    } else if v == "4277" {
+        4277
+    } else if v == "4278" {
+        4278
+    } else if v == "4279" {
+        4279
+    } else if v == "4280" {
+        4280
+    } else if v == "4281" {
+        4281
+    } else if v == "4282" {
+        4282
+    } else if v == "4283" {
+        4283
+    } else if v == "4284" {
+        4284
+    } else if v == "4285" {
+        4285
+    } else if v == "4286" {
+        4286
+    } else if v == "4287" {
+        4287
+    } else if v == "4288" {
+        4288
+    } else if v == "4289" {
+        4289
+    } else if v == "4290" {
+        4290
+    } else if v == "4291" {
+        4291
+    } else if v == "4292" {
+        4292
+    } else if v == "4293" {
+        4293
+    } else if v == "4294" {
+        4294
+    } else if v == "4295" {
+        4295
+    } else if v == "4296" {
+        4296
+    } else if v == "4297" {
+        4297
+    } else if v == "4298" {
+        4298
+    } else if v == "4299" {
+        4299
+    } else if v == "4300" {
+        4300
+    } else if v == "4301" {
+        4301
+    } else if v == "4302" {
+        4302
+    } else if v == "4303" {
+        4303
+    } else if v == "4304" {
+        4304
+    } else if v == "4305" {
+        4305
+    } else if v == "4306" {
+        4306
+    } else if v == "4307" {
+        4307
+    } else if v == "4308" {
+        4308
+    } else if v == "4309" {
+        4309
+    } else if v == "4310" {
+        4310
+    } else if v == "4311" {
+        4311
+    } else if v == "4312" {
+        4312
+    } else if v == "4313" {
+        4313
+    } else if v == "4314" {
+        4314
+    } else if v == "4315" {
+        4315
+    } else if v == "4316" {
+        4316
+    } else if v == "4317" {
+        4317
+    } else if v == "4318" {
+        4318
+    } else if v == "4319" {
+        4319
+    } else if v == "4320" {
+        4320
+    } else if v == "4321" {
+        4321
+    } else if v == "4322" {
+        4322
+    } else if v == "4323" {
+        4323
+    } else if v == "4324" {
+        4324
+    } else if v == "4325" {
+        4325
+    } else if v == "4326" {
+        4326
+    } else if v == "4327" {
+        4327
+    } else if v == "4328" {
+        4328
+    } else if v == "4329" {
+        4329
+    } else if v == "4330" {
+        4330
+    } else if v == "4331" {
+        4331
+    } else if v == "4332" {
+        4332
+    } else if v == "4333" {
+        4333
+    } else if v == "4334" {
+        4334
+    } else if v == "4335" {
+        4335
+    } else if v == "4336" {
+        4336
+    } else if v == "4337" {
+        4337
+    } else if v == "4338" {
+        4338
+    } else if v == "4339" {
+        4339
+    } else if v == "4340" {
+        4340
+    } else if v == "4341" {
+        4341
+    } else if v == "4342" {
+        4342
+    } else if v == "4343" {
+        4343
+    } else if v == "4344" {
+        4344
+    } else if v == "4345" {
+        4345
+    } else if v == "4346" {
+        4346
+    } else if v == "4347" {
+        4347
+    } else if v == "4348" {
+        4348
+    } else if v == "4349" {
+        4349
+    } else if v == "4350" {
+        4350
+    } else if v == "4351" {
+        4351
+    } else if v == "4352" {
+        4352
+    } else if v == "4353" {
+        4353
+    } else if v == "4354" {
+        4354
+    } else if v == "4355" {
+        4355
+    } else if v == "4356" {
+        4356
+    } else if v == "4357" {
+        4357
+    } else if v == "4358" {
+        4358
+    } else if v == "4359" {
+        4359
+    } else if v == "4360" {
+        4360
+    } else if v == "4361" {
+        4361
+    } else if v == "4362" {
+        4362
+    } else if v == "4363" {
+        4363
+    } else if v == "4364" {
+        4364
+    } else if v == "4365" {
+        4365
+    } else if v == "4366" {
+        4366
+    } else if v == "4367" {
+        4367
+    } else if v == "4368" {
+        4368
+    } else if v == "4369" {
+        4369
+    } else if v == "4370" {
+        4370
+    } else if v == "4371" {
+        4371
+    } else if v == "4372" {
+        4372
+    } else if v == "4373" {
+        4373
+    } else if v == "4374" {
+        4374
+    } else if v == "4375" {
+        4375
+    } else if v == "4376" {
+        4376
+    } else if v == "4377" {
+        4377
+    } else if v == "4378" {
+        4378
+    } else if v == "4379" {
+        4379
+    } else if v == "4380" {
+        4380
+    } else if v == "4381" {
+        4381
+    } else if v == "4382" {
+        4382
+    } else if v == "4383" {
+        4383
+    } else if v == "4384" {
+        4384
+    } else if v == "4385" {
+        4385
+    } else if v == "4386" {
+        4386
+    } else if v == "4387" {
+        4387
+    } else if v == "4388" {
+        4388
+    } else if v == "4389" {
+        4389
+    } else if v == "4390" {
+        4390
+    } else if v == "4391" {
+        4391
+    } else if v == "4392" {
+        4392
+    } else if v == "4393" {
+        4393
+    } else if v == "4394" {
+        4394
+    } else if v == "4395" {
+        4395
+    } else if v == "4396" {
+        4396
+    } else if v == "4397" {
+        4397
+    } else if v == "4398" {
+        4398
+    } else if v == "4399" {
+        4399
+    } else if v == "4400" {
+        4400
+    } else if v == "4401" {
+        4401
+    } else if v == "4402" {
+        4402
+    } else if v == "4403" {
+        4403
+    } else if v == "4404" {
+        4404
+    } else if v == "4405" {
+        4405
+    } else if v == "4406" {
+        4406
+    } else if v == "4407" {
+        4407
+    } else if v == "4408" {
+        4408
+    } else if v == "4409" {
+        4409
+    } else if v == "4410" {
+        4410
+    } else if v == "4411" {
+        4411
+    } else if v == "4412" {
+        4412
+    } else if v == "4413" {
+        4413
+    } else if v == "4414" {
+        4414
+    } else if v == "4415" {
+        4415
+    } else if v == "4416" {
+        4416
+    } else if v == "4417" {
+        4417
+    } else if v == "4418" {
+        4418
+    } else if v == "4419" {
+        4419
+    } else if v == "4420" {
+        4420
+    } else if v == "4421" {
+        4421
+    } else if v == "4422" {
+        4422
+    } else if v == "4423" {
+        4423
+    } else if v == "4424" {
+        4424
+    } else if v == "4425" {
+        4425
+    } else if v == "4426" {
+        4426
+    } else if v == "4427" {
+        4427
+    } else if v == "4428" {
+        4428
+    } else if v == "4429" {
+        4429
+    } else if v == "4430" {
+        4430
+    } else if v == "4431" {
+        4431
+    } else if v == "4432" {
+        4432
+    } else if v == "4433" {
+        4433
+    } else if v == "4434" {
+        4434
+    } else if v == "4435" {
+        4435
+    } else if v == "4436" {
+        4436
+    } else if v == "4437" {
+        4437
+    } else if v == "4438" {
+        4438
+    } else if v == "4439" {
+        4439
+    } else if v == "4440" {
+        4440
+    } else if v == "4441" {
+        4441
+    } else if v == "4442" {
+        4442
+    } else if v == "4443" {
+        4443
+    } else if v == "4444" {
+        4444
+    } else if v == "4445" {
+        4445
+    } else if v == "4446" {
+        4446
+    } else if v == "4447" {
+        4447
+    } else if v == "4448" {
+        4448
+    } else if v == "4449" {
+        4449
+    } else if v == "4450" {
+        4450
+    } else if v == "4451" {
+        4451
+    } else if v == "4452" {
+        4452
+    } else if v == "4453" {
+        4453
+    } else if v == "4454" {
+        4454
+    } else if v == "4455" {
+        4455
+    } else if v == "4456" {
+        4456
+    } else if v == "4457" {
+        4457
+    } else if v == "4458" {
+        4458
+    } else if v == "4459" {
+        4459
+    } else if v == "4460" {
+        4460
+    } else if v == "4461" {
+        4461
+    } else if v == "4462" {
+        4462
+    } else if v == "4463" {
+        4463
+    } else if v == "4464" {
+        4464
+    } else if v == "4465" {
+        4465
+    } else if v == "4466" {
+        4466
+    } else if v == "4467" {
+        4467
+    } else if v == "4468" {
+        4468
+    } else if v == "4469" {
+        4469
+    } else if v == "4470" {
+        4470
+    } else if v == "4471" {
+        4471
+    } else if v == "4472" {
+        4472
+    } else if v == "4473" {
+        4473
+    } else if v == "4474" {
+        4474
+    } else if v == "4475" {
+        4475
+    } else if v == "4476" {
+        4476
+    } else if v == "4477" {
+        4477
+    } else if v == "4478" {
+        4478
+    } else if v == "4479" {
+        4479
+    } else if v == "4480" {
+        4480
+    } else if v == "4481" {
+        4481
+    } else if v == "4482" {
+        4482
+    } else if v == "4483" {
+        4483
+    } else if v == "4484" {
+        4484
+    } else if v == "4485" {
+        4485
+    } else if v == "4486" {
+        4486
+    } else if v == "4487" {
+        4487
+    } else if v == "4488" {
+        4488
+    } else if v == "4489" {
+        4489
+    } else if v == "4490" {
+        4490
+    } else if v == "4491" {
+        4491
+    } else if v == "4492" {
+        4492
+    } else if v == "4493" {
+        4493
+    } else if v == "4494" {
+        4494
+    } else if v == "4495" {
+        4495
+    } else if v == "4496" {
+        4496
+    } else if v == "4497" {
+        4497
+    } else if v == "4498" {
+        4498
+    } else if v == "4499" {
+        4499
+    } else if v == "4500" {
+        4500
+    } else if v == "4501" {
+        4501
+    } else if v == "4502" {
+        4502
+    } else if v == "4503" {
+        4503
+    } else if v == "4504" {
+        4504
+    } else if v == "4505" {
+        4505
+    } else if v == "4506" {
+        4506
+    } else if v == "4507" {
+        4507
+    } else if v == "4508" {
+        4508
+    } else if v == "4509" {
+        4509
+    } else if v == "4510" {
+        4510
+    } else if v == "4511" {
+        4511
+    } else if v == "4512" {
+        4512
+    } else if v == "4513" {
+        4513
+    } else if v == "4514" {
+        4514
+    } else if v == "4515" {
+        4515
+    } else if v == "4516" {
+        4516
+    } else if v == "4517" {
+        4517
+    } else if v == "4518" {
+        4518
+    } else if v == "4519" {
+        4519
+    } else if v == "4520" {
+        4520
+    } else if v == "4521" {
+        4521
+    } else if v == "4522" {
+        4522
+    } else if v == "4523" {
+        4523
+    } else if v == "4524" {
+        4524
+    } else if v == "4525" {
+        4525
+    } else if v == "4526" {
+        4526
+    } else if v == "4527" {
+        4527
+    } else if v == "4528" {
+        4528
+    } else if v == "4529" {
+        4529
+    } else if v == "4530" {
+        4530
+    } else if v == "4531" {
+        4531
+    } else if v == "4532" {
+        4532
+    } else if v == "4533" {
+        4533
+    } else if v == "4534" {
+        4534
+    } else if v == "4535" {
+        4535
+    } else if v == "4536" {
+        4536
+    } else if v == "4537" {
+        4537
+    } else if v == "4538" {
+        4538
+    } else if v == "4539" {
+        4539
+    } else if v == "4540" {
+        4540
+    } else if v == "4541" {
+        4541
+    } else if v == "4542" {
+        4542
+    } else if v == "4543" {
+        4543
+    } else if v == "4544" {
+        4544
+    } else if v == "4545" {
+        4545
+    } else if v == "4546" {
+        4546
+    } else if v == "4547" {
+        4547
+    } else if v == "4548" {
+        4548
+    } else if v == "4549" {
+        4549
+    } else if v == "4550" {
+        4550
+    } else if v == "4551" {
+        4551
+    } else if v == "4552" {
+        4552
+    } else if v == "4553" {
+        4553
+    } else if v == "4554" {
+        4554
+    } else if v == "4555" {
+        4555
+    } else if v == "4556" {
+        4556
+    } else if v == "4557" {
+        4557
+    } else if v == "4558" {
+        4558
+    } else if v == "4559" {
+        4559
+    } else if v == "4560" {
+        4560
+    } else if v == "4561" {
+        4561
+    } else if v == "4562" {
+        4562
+    } else if v == "4563" {
+        4563
+    } else if v == "4564" {
+        4564
+    } else if v == "4565" {
+        4565
+    } else if v == "4566" {
+        4566
+    } else if v == "4567" {
+        4567
+    } else if v == "4568" {
+        4568
+    } else if v == "4569" {
+        4569
+    } else if v == "4570" {
+        4570
+    } else if v == "4571" {
+        4571
+    } else if v == "4572" {
+        4572
+    } else if v == "4573" {
+        4573
+    } else if v == "4574" {
+        4574
+    } else if v == "4575" {
+        4575
+    } else if v == "4576" {
+        4576
+    } else if v == "4577" {
+        4577
+    } else if v == "4578" {
+        4578
+    } else if v == "4579" {
+        4579
+    } else if v == "4580" {
+        4580
+    } else if v == "4581" {
+        4581
+    } else if v == "4582" {
+        4582
+    } else if v == "4583" {
+        4583
+    } else if v == "4584" {
+        4584
+    } else if v == "4585" {
+        4585
+    } else if v == "4586" {
+        4586
+    } else if v == "4587" {
+        4587
+    } else if v == "4588" {
+        4588
+    } else if v == "4589" {
+        4589
+    } else if v == "4590" {
+        4590
+    } else if v == "4591" {
+        4591
+    } else if v == "4592" {
+        4592
+    } else if v == "4593" {
+        4593
+    } else if v == "4594" {
+        4594
+    } else if v == "4595" {
+        4595
+    } else if v == "4596" {
+        4596
+    } else if v == "4597" {
+        4597
+    } else if v == "4598" {
+        4598
+    } else if v == "4599" {
+        4599
+    } else if v == "4600" {
+        4600
+    } else if v == "4601" {
+        4601
+    } else if v == "4602" {
+        4602
+    } else if v == "4603" {
+        4603
+    } else if v == "4604" {
+        4604
+    } else if v == "4605" {
+        4605
+    } else if v == "4606" {
+        4606
+    } else if v == "4607" {
+        4607
+    } else if v == "4608" {
+        4608
+    } else if v == "4609" {
+        4609
+    } else if v == "4610" {
+        4610
+    } else if v == "4611" {
+        4611
+    } else if v == "4612" {
+        4612
+    } else if v == "4613" {
+        4613
+    } else if v == "4614" {
+        4614
+    } else if v == "4615" {
+        4615
+    } else if v == "4616" {
+        4616
+    } else if v == "4617" {
+        4617
+    } else if v == "4618" {
+        4618
+    } else if v == "4619" {
+        4619
+    } else if v == "4620" {
+        4620
+    } else if v == "4621" {
+        4621
+    } else if v == "4622" {
+        4622
+    } else if v == "4623" {
+        4623
+    } else if v == "4624" {
+        4624
+    } else if v == "4625" {
+        4625
+    } else if v == "4626" {
+        4626
+    } else if v == "4627" {
+        4627
+    } else if v == "4628" {
+        4628
+    } else if v == "4629" {
+        4629
+    } else if v == "4630" {
+        4630
+    } else if v == "4631" {
+        4631
+    } else if v == "4632" {
+        4632
+    } else if v == "4633" {
+        4633
+    } else if v == "4634" {
+        4634
+    } else if v == "4635" {
+        4635
+    } else if v == "4636" {
+        4636
+    } else if v == "4637" {
+        4637
+    } else if v == "4638" {
+        4638
+    } else if v == "4639" {
+        4639
+    } else if v == "4640" {
+        4640
+    } else if v == "4641" {
+        4641
+    } else if v == "4642" {
+        4642
+    } else if v == "4643" {
+        4643
+    } else if v == "4644" {
+        4644
+    } else if v == "4645" {
+        4645
+    } else if v == "4646" {
+        4646
+    } else if v == "4647" {
+        4647
+    } else if v == "4648" {
+        4648
+    } else if v == "4649" {
+        4649
+    } else if v == "4650" {
+        4650
+    } else if v == "4651" {
+        4651
+    } else if v == "4652" {
+        4652
+    } else if v == "4653" {
+        4653
+    } else if v == "4654" {
+        4654
+    } else if v == "4655" {
+        4655
+    } else if v == "4656" {
+        4656
+    } else if v == "4657" {
+        4657
+    } else if v == "4658" {
+        4658
+    } else if v == "4659" {
+        4659
+    } else if v == "4660" {
+        4660
+    } else if v == "4661" {
+        4661
+    } else if v == "4662" {
+        4662
+    } else if v == "4663" {
+        4663
+    } else if v == "4664" {
+        4664
+    } else if v == "4665" {
+        4665
+    } else if v == "4666" {
+        4666
+    } else if v == "4667" {
+        4667
+    } else if v == "4668" {
+        4668
+    } else if v == "4669" {
+        4669
+    } else if v == "4670" {
+        4670
+    } else if v == "4671" {
+        4671
+    } else if v == "4672" {
+        4672
+    } else if v == "4673" {
+        4673
+    } else if v == "4674" {
+        4674
+    } else if v == "4675" {
+        4675
+    } else if v == "4676" {
+        4676
+    } else if v == "4677" {
+        4677
+    } else if v == "4678" {
+        4678
+    } else if v == "4679" {
+        4679
+    } else if v == "4680" {
+        4680
+    } else if v == "4681" {
+        4681
+    } else if v == "4682" {
+        4682
+    } else if v == "4683" {
+        4683
+    } else if v == "4684" {
+        4684
+    } else if v == "4685" {
+        4685
+    } else if v == "4686" {
+        4686
+    } else if v == "4687" {
+        4687
+    } else if v == "4688" {
+        4688
+    } else if v == "4689" {
+        4689
+    } else if v == "4690" {
+        4690
+    } else if v == "4691" {
+        4691
+    } else if v == "4692" {
+        4692
+    } else if v == "4693" {
+        4693
+    } else if v == "4694" {
+        4694
+    } else if v == "4695" {
+        4695
+    } else if v == "4696" {
+        4696
+    } else if v == "4697" {
+        4697
+    } else if v == "4698" {
+        4698
+    } else if v == "4699" {
+        4699
+    } else if v == "4700" {
+        4700
+    } else if v == "4701" {
+        4701
+    } else if v == "4702" {
+        4702
+    } else if v == "4703" {
+        4703
+    } else if v == "4704" {
+        4704
+    } else if v == "4705" {
+        4705
+    } else if v == "4706" {
+        4706
+    } else if v == "4707" {
+        4707
+    } else if v == "4708" {
+        4708
+    } else if v == "4709" {
+        4709
+    } else if v == "4710" {
+        4710
+    } else if v == "4711" {
+        4711
+    } else if v == "4712" {
+        4712
+    } else if v == "4713" {
+        4713
+    } else if v == "4714" {
+        4714
+    } else if v == "4715" {
+        4715
+    } else if v == "4716" {
+        4716
+    } else if v == "4717" {
+        4717
+    } else if v == "4718" {
+        4718
+    } else if v == "4719" {
+        4719
+    } else if v == "4720" {
+        4720
+    } else if v == "4721" {
+        4721
+    } else if v == "4722" {
+        4722
+    } else if v == "4723" {
+        4723
+    } else if v == "4724" {
+        4724
+    } else if v == "4725" {
+        4725
+    } else if v == "4726" {
+        4726
+    } else if v == "4727" {
+        4727
+    } else if v == "4728" {
+        4728
+    } else if v == "4729" {
+        4729
+    } else if v == "4730" {
+        4730
+    } else if v == "4731" {
+        4731
+    } else if v == "4732" {
+        4732
+    } else if v == "4733" {
+        4733
+    } else if v == "4734" {
+        4734
+    } else if v == "4735" {
+        4735
+    } else if v == "4736" {
+        4736
+    } else if v == "4737" {
+        4737
+    } else if v == "4738" {
+        4738
+    } else if v == "4739" {
+        4739
+    } else if v == "4740" {
+        4740
+    } else if v == "4741" {
+        4741
+    } else if v == "4742" {
+        4742
+    } else if v == "4743" {
+        4743
+    } else if v == "4744" {
+        4744
+    } else if v == "4745" {
+        4745
+    } else if v == "4746" {
+        4746
+    } else if v == "4747" {
+        4747
+    } else if v == "4748" {
+        4748
+    } else if v == "4749" {
+        4749
+    } else if v == "4750" {
+        4750
+    } else if v == "4751" {
+        4751
+    } else if v == "4752" {
+        4752
+    } else if v == "4753" {
+        4753
+    } else if v == "4754" {
+        4754
+    } else if v == "4755" {
+        4755
+    } else if v == "4756" {
+        4756
+    } else if v == "4757" {
+        4757
+    } else if v == "4758" {
+        4758
+    } else if v == "4759" {
+        4759
+    } else if v == "4760" {
+        4760
+    } else if v == "4761" {
+        4761
+    } else if v == "4762" {
+        4762
+    } else if v == "4763" {
+        4763
+    } else if v == "4764" {
+        4764
+    } else if v == "4765" {
+        4765
+    } else if v == "4766" {
+        4766
+    } else if v == "4767" {
+        4767
+    } else if v == "4768" {
+        4768
+    } else if v == "4769" {
+        4769
+    } else if v == "4770" {
+        4770
+    } else if v == "4771" {
+        4771
+    } else if v == "4772" {
+        4772
+    } else if v == "4773" {
+        4773
+    } else if v == "4774" {
+        4774
+    } else if v == "4775" {
+        4775
+    } else if v == "4776" {
+        4776
+    } else if v == "4777" {
+        4777
+    } else if v == "4778" {
+        4778
+    } else if v == "4779" {
+        4779
+    } else if v == "4780" {
+        4780
+    } else if v == "4781" {
+        4781
+    } else if v == "4782" {
+        4782
+    } else if v == "4783" {
+        4783
+    } else if v == "4784" {
+        4784
+    } else if v == "4785" {
+        4785
+    } else if v == "4786" {
+        4786
+    } else if v == "4787" {
+        4787
+    } else if v == "4788" {
+        4788
+    } else if v == "4789" {
+        4789
+    } else if v == "4790" {
+        4790
+    } else if v == "4791" {
+        4791
+    } else if v == "4792" {
+        4792
+    } else if v == "4793" {
+        4793
+    } else if v == "4794" {
+        4794
+    } else if v == "4795" {
+        4795
+    } else if v == "4796" {
+        4796
+    } else if v == "4797" {
+        4797
+    } else if v == "4798" {
+        4798
+    } else if v == "4799" {
+        4799
+    } else if v == "4800" {
+        4800
+    } else if v == "4801" {
+        4801
+    } else if v == "4802" {
+        4802
+    } else if v == "4803" {
+        4803
+    } else if v == "4804" {
+        4804
+    } else if v == "4805" {
+        4805
+    } else if v == "4806" {
+        4806
+    } else if v == "4807" {
+        4807
+    } else if v == "4808" {
+        4808
+    } else if v == "4809" {
+        4809
+    } else if v == "4810" {
+        4810
+    } else if v == "4811" {
+        4811
+    } else if v == "4812" {
+        4812
+    } else if v == "4813" {
+        4813
+    } else if v == "4814" {
+        4814
+    } else if v == "4815" {
+        4815
+    } else if v == "4816" {
+        4816
+    } else if v == "4817" {
+        4817
+    } else if v == "4818" {
+        4818
+    } else if v == "4819" {
+        4819
+    } else if v == "4820" {
+        4820
+    } else if v == "4821" {
+        4821
+    } else if v == "4822" {
+        4822
+    } else if v == "4823" {
+        4823
+    } else if v == "4824" {
+        4824
+    } else if v == "4825" {
+        4825
+    } else if v == "4826" {
+        4826
+    } else if v == "4827" {
+        4827
+    } else if v == "4828" {
+        4828
+    } else if v == "4829" {
+        4829
+    } else if v == "4830" {
+        4830
+    } else if v == "4831" {
+        4831
+    } else if v == "4832" {
+        4832
+    } else if v == "4833" {
+        4833
+    } else if v == "4834" {
+        4834
+    } else if v == "4835" {
+        4835
+    } else if v == "4836" {
+        4836
+    } else if v == "4837" {
+        4837
+    } else if v == "4838" {
+        4838
+    } else if v == "4839" {
+        4839
+    } else if v == "4840" {
+        4840
+    } else if v == "4841" {
+        4841
+    } else if v == "4842" {
+        4842
+    } else if v == "4843" {
+        4843
+    } else if v == "4844" {
+        4844
+    } else if v == "4845" {
+        4845
+    } else if v == "4846" {
+        4846
+    } else if v == "4847" {
+        4847
+    } else if v == "4848" {
+        4848
+    } else if v == "4849" {
+        4849
+    } else if v == "4850" {
+        4850
+    } else if v == "4851" {
+        4851
+    } else if v == "4852" {
+        4852
+    } else if v == "4853" {
+        4853
+    } else if v == "4854" {
+        4854
+    } else if v == "4855" {
+        4855
+    } else if v == "4856" {
+        4856
+    } else if v == "4857" {
+        4857
+    } else if v == "4858" {
+        4858
+    } else if v == "4859" {
+        4859
+    } else if v == "4860" {
+        4860
+    } else if v == "4861" {
+        4861
+    } else if v == "4862" {
+        4862
+    } else if v == "4863" {
+        4863
+    } else if v == "4864" {
+        4864
+    } else if v == "4865" {
+        4865
+    } else if v == "4866" {
+        4866
+    } else if v == "4867" {
+        4867
+    } else if v == "4868" {
+        4868
+    } else if v == "4869" {
+        4869
+    } else if v == "4870" {
+        4870
+    } else if v == "4871" {
+        4871
+    } else if v == "4872" {
+        4872
+    } else if v == "4873" {
+        4873
+    } else if v == "4874" {
+        4874
+    } else if v == "4875" {
+        4875
+    } else if v == "4876" {
+        4876
+    } else if v == "4877" {
+        4877
+    } else if v == "4878" {
+        4878
+    } else if v == "4879" {
+        4879
+    } else if v == "4880" {
+        4880
+    } else if v == "4881" {
+        4881
+    } else if v == "4882" {
+        4882
+    } else if v == "4883" {
+        4883
+    } else if v == "4884" {
+        4884
+    } else if v == "4885" {
+        4885
+    } else if v == "4886" {
+        4886
+    } else if v == "4887" {
+        4887
+    } else if v == "4888" {
+        4888
+    } else if v == "4889" {
+        4889
+    } else if v == "4890" {
+        4890
+    } else if v == "4891" {
+        4891
+    } else if v == "4892" {
+        4892
+    } else if v == "4893" {
+        4893
+    } else if v == "4894" {
+        4894
+    } else if v == "4895" {
+        4895
+    } else if v == "4896" {
+        4896
+    } else if v == "4897" {
+        4897
+    } else if v == "4898" {
+        4898
+    } else if v == "4899" {
+        4899
+    } else if v == "4900" {
+        4900
+    } else if v == "4901" {
+        4901
+    } else if v == "4902" {
+        4902
+    } else if v == "4903" {
+        4903
+    } else if v == "4904" {
+        4904
+    } else if v == "4905" {
+        4905
+    } else if v == "4906" {
+        4906
+    } else if v == "4907" {
+        4907
+    } else if v == "4908" {
+        4908
+    } else if v == "4909" {
+        4909
+    } else if v == "4910" {
+        4910
+    } else if v == "4911" {
+        4911
+    } else if v == "4912" {
+        4912
+    } else if v == "4913" {
+        4913
+    } else if v == "4914" {
+        4914
+    } else if v == "4915" {
+        4915
+    } else if v == "4916" {
+        4916
+    } else if v == "4917" {
+        4917
+    } else if v == "4918" {
+        4918
+    } else if v == "4919" {
+        4919
+    } else if v == "4920" {
+        4920
+    } else if v == "4921" {
+        4921
+    } else if v == "4922" {
+        4922
+    } else if v == "4923" {
+        4923
+    } else if v == "4924" {
+        4924
+    } else if v == "4925" {
+        4925
+    } else if v == "4926" {
+        4926
+    } else if v == "4927" {
+        4927
+    } else if v == "4928" {
+        4928
+    } else if v == "4929" {
+        4929
+    } else if v == "4930" {
+        4930
+    } else if v == "4931" {
+        4931
+    } else if v == "4932" {
+        4932
+    } else if v == "4933" {
+        4933
+    } else if v == "4934" {
+        4934
+    } else if v == "4935" {
+        4935
+    } else if v == "4936" {
+        4936
+    } else if v == "4937" {
+        4937
+    } else if v == "4938" {
+        4938
+    } else if v == "4939" {
+        4939
+    } else if v == "4940" {
+        4940
+    } else if v == "4941" {
+        4941
+    } else if v == "4942" {
+        4942
+    } else if v == "4943" {
+        4943
+    } else if v == "4944" {
+        4944
+    } else if v == "4945" {
+        4945
+    } else if v == "4946" {
+        4946
+    } else if v == "4947" {
+        4947
+    } else if v == "4948" {
+        4948
+    } else if v == "4949" {
+        4949
+    } else if v == "4950" {
+        4950
+    } else if v == "4951" {
+        4951
+    } else if v == "4952" {
+        4952
+    } else if v == "4953" {
+        4953
+    } else if v == "4954" {
+        4954
+    } else if v == "4955" {
+        4955
+    } else if v == "4956" {
+        4956
+    } else if v == "4957" {
+        4957
+    } else if v == "4958" {
+        4958
+    } else if v == "4959" {
+        4959
+    } else if v == "4960" {
+        4960
+    } else if v == "4961" {
+        4961
+    } else if v == "4962" {
+        4962
+    } else if v == "4963" {
+        4963
+    } else if v == "4964" {
+        4964
+    } else if v == "4965" {
+        4965
+    } else if v == "4966" {
+        4966
+    } else if v == "4967" {
+        4967
+    } else if v == "4968" {
+        4968
+    } else if v == "4969" {
+        4969
+    } else if v == "4970" {
+        4970
+    } else if v == "4971" {
+        4971
+    } else if v == "4972" {
+        4972
+    } else if v == "4973" {
+        4973
+    } else if v == "4974" {
+        4974
+    } else if v == "4975" {
+        4975
+    } else if v == "4976" {
+        4976
+    } else if v == "4977" {
+        4977
+    } else if v == "4978" {
+        4978
+    } else if v == "4979" {
+        4979
+    } else if v == "4980" {
+        4980
+    } else if v == "4981" {
+        4981
+    } else if v == "4982" {
+        4982
+    } else if v == "4983" {
+        4983
+    } else if v == "4984" {
+        4984
+    } else if v == "4985" {
+        4985
+    } else if v == "4986" {
+        4986
+    } else if v == "4987" {
+        4987
+    } else if v == "4988" {
+        4988
+    } else if v == "4989" {
+        4989
+    } else if v == "4990" {
+        4990
+    } else if v == "4991" {
+        4991
+    } else if v == "4992" {
+        4992
+    } else if v == "4993" {
+        4993
+    } else if v == "4994" {
+        4994
+    } else if v == "4995" {
+        4995
+    } else if v == "4996" {
+        4996
+    } else if v == "4997" {
+        4997
+    } else if v == "4998" {
+        4998
+    } else if v == "4999" {
+        4999
+    } else if v == "5000" {
+        5000
+    } else if v == "5001" {
+        5001
+    } else if v == "5002" {
+        5002
+    } else if v == "5003" {
+        5003
+    } else if v == "5004" {
+        5004
+    } else if v == "5005" {
+        5005
+    } else if v == "5006" {
+        5006
+    } else if v == "5007" {
+        5007
+    } else if v == "5008" {
+        5008
+    } else if v == "5009" {
+        5009
+    } else if v == "5010" {
+        5010
+    } else if v == "5011" {
+        5011
+    } else if v == "5012" {
+        5012
+    } else if v == "5013" {
+        5013
+    } else if v == "5014" {
+        5014
+    } else if v == "5015" {
+        5015
+    } else if v == "5016" {
+        5016
+    } else if v == "5017" {
+        5017
+    } else if v == "5018" {
+        5018
+    } else if v == "5019" {
+        5019
+    } else if v == "5020" {
+        5020
+    } else if v == "5021" {
+        5021
+    } else if v == "5022" {
+        5022
+    } else if v == "5023" {
+        5023
+    } else if v == "5024" {
+        5024
+    } else if v == "5025" {
+        5025
+    } else if v == "5026" {
+        5026
+    } else if v == "5027" {
+        5027
+    } else if v == "5028" {
+        5028
+    } else if v == "5029" {
+        5029
+    } else if v == "5030" {
+        5030
+    } else if v == "5031" {
+        5031
+    } else if v == "5032" {
+        5032
+    } else if v == "5033" {
+        5033
+    } else if v == "5034" {
+        5034
+    } else if v == "5035" {
+        5035
+    } else if v == "5036" {
+        5036
+    } else if v == "5037" {
+        5037
+    } else if v == "5038" {
+        5038
+    } else if v == "5039" {
+        5039
+    } else if v == "5040" {
+        5040
+    } else if v == "5041" {
+        5041
+    } else if v == "5042" {
+        5042
+    } else if v == "5043" {
+        5043
+    } else if v == "5044" {
+        5044
+    } else if v == "5045" {
+        5045
+    } else if v == "5046" {
+        5046
+    } else if v == "5047" {
+        5047
+    } else if v == "5048" {
+        5048
+    } else if v == "5049" {
+        5049
+    } else if v == "5050" {
+        5050
+    } else if v == "5051" {
+        5051
+    } else if v == "5052" {
+        5052
+    } else if v == "5053" {
+        5053
+    } else if v == "5054" {
+        5054
+    } else if v == "5055" {
+        5055
+    } else if v == "5056" {
+        5056
+    } else if v == "5057" {
+        5057
+    } else if v == "5058" {
+        5058
+    } else if v == "5059" {
+        5059
+    } else if v == "5060" {
+        5060
+    } else if v == "5061" {
+        5061
+    } else if v == "5062" {
+        5062
+    } else if v == "5063" {
+        5063
+    } else if v == "5064" {
+        5064
+    } else if v == "5065" {
+        5065
+    } else if v == "5066" {
+        5066
+    } else if v == "5067" {
+        5067
+    } else if v == "5068" {
+        5068
+    } else if v == "5069" {
+        5069
+    } else if v == "5070" {
+        5070
+    } else if v == "5071" {
+        5071
+    } else if v == "5072" {
+        5072
+    } else if v == "5073" {
+        5073
+    } else if v == "5074" {
+        5074
+    } else if v == "5075" {
+        5075
+    } else if v == "5076" {
+        5076
+    } else if v == "5077" {
+        5077
+    } else if v == "5078" {
+        5078
+    } else if v == "5079" {
+        5079
+    } else if v == "5080" {
+        5080
+    } else if v == "5081" {
+        5081
+    } else if v == "5082" {
+        5082
+    } else if v == "5083" {
+        5083
+    } else if v == "5084" {
+        5084
+    } else if v == "5085" {
+        5085
+    } else if v == "5086" {
+        5086
+    } else if v == "5087" {
+        5087
+    } else if v == "5088" {
+        5088
+    } else if v == "5089" {
+        5089
+    } else if v == "5090" {
+        5090
+    } else if v == "5091" {
+        5091
+    } else if v == "5092" {
+        5092
+    } else if v == "5093" {
+        5093
+    } else if v == "5094" {
+        5094
+    } else if v == "5095" {
+        5095
+    } else if v == "5096" {
+        5096
+    } else if v == "5097" {
+        5097
+    } else if v == "5098" {
+        5098
+    } else if v == "5099" {
+        5099
+    } else if v == "5100" {
+        5100
+    } else if v == "5101" {
+        5101
+    } else if v == "5102" {
+        5102
+    } else if v == "5103" {
+        5103
+    } else if v == "5104" {
+        5104
+    } else if v == "5105" {
+        5105
+    } else if v == "5106" {
+        5106
+    } else if v == "5107" {
+        5107
+    } else if v == "5108" {
+        5108
+    } else if v == "5109" {
+        5109
+    } else if v == "5110" {
+        5110
+    } else if v == "5111" {
+        5111
+    } else if v == "5112" {
+        5112
+    } else if v == "5113" {
+        5113
+    } else if v == "5114" {
+        5114
+    } else if v == "5115" {
+        5115
+    } else if v == "5116" {
+        5116
+    } else if v == "5117" {
+        5117
+    } else if v == "5118" {
+        5118
+    } else if v == "5119" {
+        5119
+    } else if v == "5120" {
+        5120
+    } else if v == "5121" {
+        5121
+    } else if v == "5122" {
+        5122
+    } else if v == "5123" {
+        5123
+    } else if v == "5124" {
+        5124
+    } else if v == "5125" {
+        5125
+    } else if v == "5126" {
+        5126
+    } else if v == "5127" {
+        5127
+    } else if v == "5128" {
+        5128
+    } else if v == "5129" {
+        5129
+    } else if v == "5130" {
+        5130
+    } else if v == "5131" {
+        5131
+    } else if v == "5132" {
+        5132
+    } else if v == "5133" {
+        5133
+    } else if v == "5134" {
+        5134
+    } else if v == "5135" {
+        5135
+    } else if v == "5136" {
+        5136
+    } else if v == "5137" {
+        5137
+    } else if v == "5138" {
+        5138
+    } else if v == "5139" {
+        5139
+    } else if v == "5140" {
+        5140
+    } else if v == "5141" {
+        5141
+    } else if v == "5142" {
+        5142
+    } else if v == "5143" {
+        5143
+    } else if v == "5144" {
+        5144
+    } else if v == "5145" {
+        5145
+    } else if v == "5146" {
+        5146
+    } else if v == "5147" {
+        5147
+    } else if v == "5148" {
+        5148
+    } else if v == "5149" {
+        5149
+    } else if v == "5150" {
+        5150
+    } else if v == "5151" {
+        5151
+    } else if v == "5152" {
+        5152
+    } else if v == "5153" {
+        5153
+    } else if v == "5154" {
+        5154
+    } else if v == "5155" {
+        5155
+    } else if v == "5156" {
+        5156
+    } else if v == "5157" {
+        5157
+    } else if v == "5158" {
+        5158
+    } else if v == "5159" {
+        5159
+    } else if v == "5160" {
+        5160
+    } else if v == "5161" {
+        5161
+    } else if v == "5162" {
+        5162
+    } else if v == "5163" {
+        5163
+    } else if v == "5164" {
+        5164
+    } else if v == "5165" {
+        5165
+    } else if v == "5166" {
+        5166
+    } else if v == "5167" {
+        5167
+    } else if v == "5168" {
+        5168
+    } else if v == "5169" {
+        5169
+    } else if v == "5170" {
+        5170
+    } else if v == "5171" {
+        5171
+    } else if v == "5172" {
+        5172
+    } else if v == "5173" {
+        5173
+    } else if v == "5174" {
+        5174
+    } else if v == "5175" {
+        5175
+    } else if v == "5176" {
+        5176
+    } else if v == "5177" {
+        5177
+    } else if v == "5178" {
+        5178
+    } else if v == "5179" {
+        5179
+    } else if v == "5180" {
+        5180
+    } else if v == "5181" {
+        5181
+    } else if v == "5182" {
+        5182
+    } else if v == "5183" {
+        5183
+    } else if v == "5184" {
+        5184
+    } else if v == "5185" {
+        5185
+    } else if v == "5186" {
+        5186
+    } else if v == "5187" {
+        5187
+    } else if v == "5188" {
+        5188
+    } else if v == "5189" {
+        5189
+    } else if v == "5190" {
+        5190
+    } else if v == "5191" {
+        5191
+    } else if v == "5192" {
+        5192
+    } else if v == "5193" {
+        5193
+    } else if v == "5194" {
+        5194
+    } else if v == "5195" {
+        5195
+    } else if v == "5196" {
+        5196
+    } else if v == "5197" {
+        5197
+    } else if v == "5198" {
+        5198
+    } else if v == "5199" {
+        5199
+    } else if v == "5200" {
+        5200
+    } else if v == "5201" {
+        5201
+    } else if v == "5202" {
+        5202
+    } else if v == "5203" {
+        5203
+    } else if v == "5204" {
+        5204
+    } else if v == "5205" {
+        5205
+    } else {
+        5206
+    }
+}
diff --git a/src/test/ui/issues/issue-74614.rs b/src/test/ui/issues/issue-74614.rs
new file mode 100644 (file)
index 0000000..f5e8deb
--- /dev/null
@@ -0,0 +1,17 @@
+// build-pass
+
+fn test<T>() {
+    std::mem::size_of::<T>();
+}
+
+pub fn foo<T>(_: T) -> &'static fn() {
+    &(test::<T> as fn())
+}
+
+fn outer<T>() {
+    foo(|| ());
+}
+
+fn main() {
+    outer::<u8>();
+}
index c1aa3d70f77cc0381772ce6a6851ad9a02a58b52..561376c8f059d1eb18e9fcee9ada5c40d0f0e47f 100644 (file)
@@ -13,10 +13,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     big.iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     [0u8; 33].iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     Box::new(small).iter();
@@ -26,10 +26,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(big).iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new([0u8; 33]).iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     Box::new(Box::new(small)).iter();
@@ -39,10 +39,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(Box::new(big)).iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(Box::new([0u8; 33])).iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     // Expressions that should not
index afdf6cb7f442020b2d2037c4f34d9e7970954c93..cc310191f0caf3d5d6c5c15bb27ea10e576dac53 100644 (file)
@@ -13,10 +13,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     big.into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     [0u8; 33].into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     Box::new(small).into_iter();
@@ -26,10 +26,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(big).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new([0u8; 33]).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     Box::new(Box::new(small)).into_iter();
@@ -39,10 +39,10 @@ fn main() {
     //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(Box::new(big)).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
     Box::new(Box::new([0u8; 33])).into_iter();
-    //~^ WARNING this method call currently resolves to `<&[T] as IntoIterator>::into_iter`
+    //~^ WARNING this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this was previously accepted by the compiler but is being phased out
 
     // Expressions that should not
index bbec9147f574b7ace25750ac9195d151fdbc713c..b31f444b36e9964fb65ee29c7929b726d1e9271b 100644 (file)
@@ -17,7 +17,7 @@ LL |     [1, 2].into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:15:9
    |
 LL |     big.into_iter();
@@ -26,7 +26,7 @@ LL |     big.into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:18:15
    |
 LL |     [0u8; 33].into_iter();
@@ -53,7 +53,7 @@ LL |     Box::new([1, 2]).into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:28:19
    |
 LL |     Box::new(big).into_iter();
@@ -62,7 +62,7 @@ LL |     Box::new(big).into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:31:25
    |
 LL |     Box::new([0u8; 33]).into_iter();
@@ -89,7 +89,7 @@ LL |     Box::new(Box::new([1, 2])).into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:41:29
    |
 LL |     Box::new(Box::new(big)).into_iter();
@@ -98,7 +98,7 @@ LL |     Box::new(Box::new(big)).into_iter();
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
 
-warning: this method call currently resolves to `<&[T] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
+warning: this method call currently resolves to `<&[T; N] as IntoIterator>::into_iter` (due to autoref coercions), but that might change in the future when `IntoIterator` impls for arrays are added.
   --> $DIR/into-iter-on-arrays-lint.rs:44:35
    |
 LL |     Box::new(Box::new([0u8; 33])).into_iter();
index bdf95350c70451c6a82eb66a03c8332f790b95e8..f485766bcd34e32d049ff3dd36ee7273bec8fa7d 100644 (file)
@@ -7,6 +7,7 @@
 
 use std::marker::PhantomData;
 
+trait Bar { }
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
 #[repr(C)]
@@ -53,7 +54,7 @@ pub struct StructWithProjectionAndLifetime<'a>(
     pub fn char_type(p: char); //~ ERROR uses type `char`
     pub fn i128_type(p: i128); //~ ERROR uses type `i128`
     pub fn u128_type(p: u128); //~ ERROR uses type `u128`
-    pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone`
+    pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar`
     pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
     pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
     pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize`
index 13b9adca3f9f5af7c4cd86f6d369daac55ae66b8..a54226a7fc4a2c7e9ebd557becc123166541d797 100644 (file)
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Foo`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:46:28
+  --> $DIR/lint-ctypes.rs:47:28
    |
 LL |     pub fn ptr_type1(size: *const Foo);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -12,13 +12,13 @@ LL | #![deny(improper_ctypes)]
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:24:1
+  --> $DIR/lint-ctypes.rs:25:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `Foo`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:47:28
+  --> $DIR/lint-ctypes.rs:48:28
    |
 LL |     pub fn ptr_type2(size: *const Foo);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -26,13 +26,13 @@ LL |     pub fn ptr_type2(size: *const Foo);
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:24:1
+  --> $DIR/lint-ctypes.rs:25:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:48:26
+  --> $DIR/lint-ctypes.rs:49:26
    |
 LL |     pub fn slice_type(p: &[u32]);
    |                          ^^^^^^ not FFI-safe
@@ -41,7 +41,7 @@ LL |     pub fn slice_type(p: &[u32]);
    = note: slices have no C equivalent
 
 error: `extern` block uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:49:24
+  --> $DIR/lint-ctypes.rs:50:24
    |
 LL |     pub fn str_type(p: &str);
    |                        ^^^^ not FFI-safe
@@ -50,7 +50,7 @@ LL |     pub fn str_type(p: &str);
    = note: string slices have no C equivalent
 
 error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:50:24
+  --> $DIR/lint-ctypes.rs:51:24
    |
 LL |     pub fn box_type(p: Box<u32>);
    |                        ^^^^^^^^ not FFI-safe
@@ -59,7 +59,7 @@ LL |     pub fn box_type(p: Box<u32>);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `std::option::Option<std::boxed::Box<u32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:51:28
+  --> $DIR/lint-ctypes.rs:52:28
    |
 LL |     pub fn opt_box_type(p: Option<Box<u32>>);
    |                            ^^^^^^^^^^^^^^^^ not FFI-safe
@@ -68,7 +68,7 @@ LL |     pub fn opt_box_type(p: Option<Box<u32>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:53:25
+  --> $DIR/lint-ctypes.rs:54:25
    |
 LL |     pub fn char_type(p: char);
    |                         ^^^^ not FFI-safe
@@ -77,7 +77,7 @@ LL |     pub fn char_type(p: char);
    = note: the `char` type has no C equivalent
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:54:25
+  --> $DIR/lint-ctypes.rs:55:25
    |
 LL |     pub fn i128_type(p: i128);
    |                         ^^^^ not FFI-safe
@@ -85,23 +85,23 @@ LL |     pub fn i128_type(p: i128);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:55:25
+  --> $DIR/lint-ctypes.rs:56:25
    |
 LL |     pub fn u128_type(p: u128);
    |                         ^^^^ not FFI-safe
    |
    = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:56:26
+error: `extern` block uses type `dyn Bar`, which is not FFI-safe
+  --> $DIR/lint-ctypes.rs:57:26
    |
-LL |     pub fn trait_type(p: &dyn Clone);
-   |                          ^^^^^^^^^^ not FFI-safe
+LL |     pub fn trait_type(p: &dyn Bar);
+   |                          ^^^^^^^^ not FFI-safe
    |
    = note: trait objects have no C equivalent
 
 error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:57:26
+  --> $DIR/lint-ctypes.rs:58:26
    |
 LL |     pub fn tuple_type(p: (i32, i32));
    |                          ^^^^^^^^^^ not FFI-safe
@@ -110,7 +110,7 @@ LL |     pub fn tuple_type(p: (i32, i32));
    = note: tuples have unspecified layout
 
 error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:58:27
+  --> $DIR/lint-ctypes.rs:59:27
    |
 LL |     pub fn tuple_type2(p: I32Pair);
    |                           ^^^^^^^ not FFI-safe
@@ -119,7 +119,7 @@ LL |     pub fn tuple_type2(p: I32Pair);
    = note: tuples have unspecified layout
 
 error: `extern` block uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:59:25
+  --> $DIR/lint-ctypes.rs:60:25
    |
 LL |     pub fn zero_size(p: ZeroSize);
    |                         ^^^^^^^^ not FFI-safe
@@ -127,26 +127,26 @@ LL |     pub fn zero_size(p: ZeroSize);
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:20:1
+  --> $DIR/lint-ctypes.rs:21:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:60:33
+  --> $DIR/lint-ctypes.rs:61:33
    |
 LL |     pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:43:1
+  --> $DIR/lint-ctypes.rs:44:1
    |
 LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `std::marker::PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:63:12
+  --> $DIR/lint-ctypes.rs:64:12
    |
 LL |         -> ::std::marker::PhantomData<bool>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -154,7 +154,7 @@ LL |         -> ::std::marker::PhantomData<bool>;
    = note: composed only of `PhantomData`
 
 error: `extern` block uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:64:23
+  --> $DIR/lint-ctypes.rs:65:23
    |
 LL |     pub fn fn_type(p: RustFn);
    |                       ^^^^^^ not FFI-safe
@@ -163,7 +163,7 @@ LL |     pub fn fn_type(p: RustFn);
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` block uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:65:24
+  --> $DIR/lint-ctypes.rs:66:24
    |
 LL |     pub fn fn_type2(p: fn());
    |                        ^^^^ not FFI-safe
@@ -172,7 +172,7 @@ LL |     pub fn fn_type2(p: fn());
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:66:28
+  --> $DIR/lint-ctypes.rs:67:28
    |
 LL |     pub fn fn_contained(p: RustBadRet);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -181,7 +181,7 @@ LL |     pub fn fn_contained(p: RustBadRet);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:67:32
+  --> $DIR/lint-ctypes.rs:68:32
    |
 LL |     pub fn transparent_i128(p: TransparentI128);
    |                                ^^^^^^^^^^^^^^^ not FFI-safe
@@ -189,7 +189,7 @@ LL |     pub fn transparent_i128(p: TransparentI128);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:68:31
+  --> $DIR/lint-ctypes.rs:69:31
    |
 LL |     pub fn transparent_str(p: TransparentStr);
    |                               ^^^^^^^^^^^^^^ not FFI-safe
@@ -198,7 +198,7 @@ LL |     pub fn transparent_str(p: TransparentStr);
    = note: string slices have no C equivalent
 
 error: `extern` block uses type `std::boxed::Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:69:30
+  --> $DIR/lint-ctypes.rs:70:30
    |
 LL |     pub fn transparent_fn(p: TransparentBadFn);
    |                              ^^^^^^^^^^^^^^^^ not FFI-safe
@@ -207,7 +207,7 @@ LL |     pub fn transparent_fn(p: TransparentBadFn);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `[u8; 8]`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:70:27
+  --> $DIR/lint-ctypes.rs:71:27
    |
 LL |     pub fn raw_array(arr: [u8; 8]);
    |                           ^^^^^^^ not FFI-safe
@@ -216,7 +216,7 @@ LL |     pub fn raw_array(arr: [u8; 8]);
    = note: passing raw arrays by value is not FFI-safe
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:72:34
+  --> $DIR/lint-ctypes.rs:73:34
    |
 LL |     pub static static_u128_type: u128;
    |                                  ^^^^ not FFI-safe
@@ -224,7 +224,7 @@ LL |     pub static static_u128_type: u128;
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:73:40
+  --> $DIR/lint-ctypes.rs:74:40
    |
 LL |     pub static static_u128_array_type: [u128; 16];
    |                                        ^^^^^^^^^^ not FFI-safe
index 8421dc1d0c1303921e0981db1c908c9c8e4aa4e9..1931934a2112a7ded99b5e6ff3dfc08a4f15732d 100644 (file)
@@ -1,28 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/constant-in-expr-inherent-1.rs:8:5
    |
-LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8...
-  --> $DIR/constant-in-expr-inherent-1.rs:7:8
-   |
 LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
-   |        ^^
-note: ...so that the types are compatible
-  --> $DIR/constant-in-expr-inherent-1.rs:8:5
-   |
-LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
-   = note: expected `Foo<'_>`
-              found `Foo<'a>`
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/constant-in-expr-inherent-1.rs:8:5
-   |
+   |               ------- this data with lifetime `'a`...
 LL |     <Foo<'a>>::C
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
index 708ab1cf38297d2d3778de18bf1039063c09453c..4a2665d8e1694f2d68d04396c83127fe58b875b9 100644 (file)
@@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR cannot infer an appropriate lifetime
+    ss.r //~ ERROR E0759
 }
 
 fn store(ss: &mut SomeStruct, b: Box<dyn SomeTrait>) {
index 1b1e0d9610724b6e83c1a48c19e2a0ff427fb158..70b99ef7869ca8cfab83e016c7463e4eb2ef17d9 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `ss` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
diff --git a/src/test/ui/polymorphization/const_parameters/closures.rs b/src/test/ui/polymorphization/const_parameters/closures.rs
new file mode 100644 (file)
index 0000000..f20605e
--- /dev/null
@@ -0,0 +1,67 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(const_generics, rustc_attrs)]
+//~^ WARN the feature `const_generics` is incomplete
+
+// This test checks that the polymorphization analysis correctly detects unused const
+// parameters in closures.
+
+// Function doesn't have any generic parameters to be unused.
+#[rustc_polymorphize_error]
+pub fn no_parameters() {
+    let _ = || {};
+}
+
+// Function has an unused generic parameter in parent and closure.
+#[rustc_polymorphize_error]
+pub fn unused<const T: usize>() -> usize {
+    //~^ ERROR item has unused generic parameters
+    let add_one = |x: usize| x + 1;
+    //~^ ERROR item has unused generic parameters
+    add_one(3)
+}
+
+// Function has an unused generic parameter in closure, but not in parent.
+#[rustc_polymorphize_error]
+pub fn used_parent<const T: usize>() -> usize {
+    let x: usize = T;
+    let add_one = |x: usize| x + 1;
+    //~^ ERROR item has unused generic parameters
+    x + add_one(3)
+}
+
+// Function uses generic parameter in value of a binding in closure.
+#[rustc_polymorphize_error]
+pub fn used_binding<const T: usize>() -> usize {
+    let x = || {
+        let y: usize = T;
+        y
+    };
+
+    x()
+}
+
+// Closure uses a value as an upvar, which used the generic parameter.
+#[rustc_polymorphize_error]
+pub fn unused_upvar<const T: usize>() -> usize {
+    let x: usize = T;
+    let y = || x;
+    //~^ ERROR item has unused generic parameters
+    y()
+}
+
+// Closure uses generic parameter in substitutions to another function.
+#[rustc_polymorphize_error]
+pub fn used_substs<const T: usize>() -> usize {
+    let x = || unused::<T>();
+    x()
+}
+
+fn main() {
+    no_parameters();
+    let _ = unused::<1>();
+    let _ = used_parent::<1>();
+    let _ = used_binding::<1>();
+    let _ = unused_upvar::<1>();
+    let _ = used_substs::<1>();
+}
diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr
new file mode 100644 (file)
index 0000000..266b6e6
--- /dev/null
@@ -0,0 +1,44 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/closures.rs:3:12
+   |
+LL | #![feature(const_generics, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:19:19
+   |
+LL | pub fn unused<const T: usize>() -> usize {
+   |                     - generic parameter `T` is unused
+LL |
+LL |     let add_one = |x: usize| x + 1;
+   |                   ^^^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:17:8
+   |
+LL | pub fn unused<const T: usize>() -> usize {
+   |        ^^^^^^       - generic parameter `T` is unused
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:28:19
+   |
+LL | pub fn used_parent<const T: usize>() -> usize {
+   |                          - generic parameter `T` is unused
+LL |     let x: usize = T;
+LL |     let add_one = |x: usize| x + 1;
+   |                   ^^^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:48:13
+   |
+LL | pub fn unused_upvar<const T: usize>() -> usize {
+   |                           - generic parameter `T` is unused
+LL |     let x: usize = T;
+LL |     let y = || x;
+   |             ^^^^
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/polymorphization/const_parameters/functions.rs b/src/test/ui/polymorphization/const_parameters/functions.rs
new file mode 100644 (file)
index 0000000..04c279d
--- /dev/null
@@ -0,0 +1,37 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(const_generics, rustc_attrs)]
+//~^ WARN the feature `const_generics` is incomplete
+
+// This test checks that the polymorphization analysis correctly detects unused const
+// parameters in functions.
+
+// Function doesn't have any generic parameters to be unused.
+#[rustc_polymorphize_error]
+pub fn no_parameters() {}
+
+// Function has an unused generic parameter.
+#[rustc_polymorphize_error]
+pub fn unused<const T: usize>() {
+    //~^ ERROR item has unused generic parameters
+}
+
+// Function uses generic parameter in value of a binding.
+#[rustc_polymorphize_error]
+pub fn used_binding<const T: usize>() -> usize {
+    let x: usize = T;
+    x
+}
+
+// Function uses generic parameter in substitutions to another function.
+#[rustc_polymorphize_error]
+pub fn used_substs<const T: usize>() {
+    unused::<T>()
+}
+
+fn main() {
+    no_parameters();
+    unused::<1>();
+    used_binding::<1>();
+    used_substs::<1>();
+}
diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr
new file mode 100644 (file)
index 0000000..e379e32
--- /dev/null
@@ -0,0 +1,17 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/functions.rs:3:12
+   |
+LL | #![feature(const_generics, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: item has unused generic parameters
+  --> $DIR/functions.rs:15:8
+   |
+LL | pub fn unused<const T: usize>() {
+   |        ^^^^^^       - generic parameter `T` is unused
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/polymorphization/drop_shims/simple.rs b/src/test/ui/polymorphization/drop_shims/simple.rs
new file mode 100644 (file)
index 0000000..2695dc6
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+// compile-flags:-Zpolymorphize=on
+
+pub struct OnDrop<F: Fn()>(pub F);
+
+impl<F: Fn()> Drop for OnDrop<F> {
+    fn drop(&mut self) { }
+}
+
+fn foo<R, S: FnOnce()>(
+    _: R,
+    _: S,
+) {
+    let bar = || {
+        let _ = OnDrop(|| ());
+    };
+    let _ = bar();
+}
+
+fn main() {
+    foo(3u32, || {});
+}
diff --git a/src/test/ui/polymorphization/drop_shims/transitive.rs b/src/test/ui/polymorphization/drop_shims/transitive.rs
new file mode 100644 (file)
index 0000000..c228911
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+// compile-flags:-Zpolymorphize=on
+
+pub struct OnDrop<F: Fn()>(pub F);
+
+impl<F: Fn()> Drop for OnDrop<F> {
+    fn drop(&mut self) { }
+}
+
+fn bar<F: FnOnce()>(f: F) {
+    let _ = OnDrop(|| ());
+    f()
+}
+
+fn foo<R, S: FnOnce()>(
+    _: R,
+    _: S,
+) {
+    let bar = || {
+        bar(|| {})
+    };
+    let _ = bar();
+}
+
+fn main() {
+    foo(3u32, || {});
+}
diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs
new file mode 100644 (file)
index 0000000..9eb34fb
--- /dev/null
@@ -0,0 +1,94 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(const_generics, generators, generator_trait, rustc_attrs)]
+//~^ WARN the feature `const_generics` is incomplete
+
+use std::marker::Unpin;
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+enum YieldOrReturn<Y, R> {
+    Yield(Y),
+    Return(R),
+}
+
+fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>>
+where
+    T: Generator<(), Yield = Y, Return = R> + Unpin,
+{
+    let mut results = Vec::new();
+    loop {
+        match Pin::new(&mut t).resume(()) {
+            GeneratorState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)),
+            GeneratorState::Complete(returned) => {
+                results.push(YieldOrReturn::Return(returned));
+                return results;
+            }
+        }
+    }
+}
+
+// This test checks that the polymorphization analysis functions on generators.
+
+#[rustc_polymorphize_error]
+pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+    //~^ ERROR item has unused generic parameters
+    || {
+        //~^ ERROR item has unused generic parameters
+        yield 1;
+        2
+    }
+}
+
+#[rustc_polymorphize_error]
+pub fn used_type_in_yield<Y: Default>() -> impl Generator<(), Yield = Y, Return = u32> + Unpin {
+    || {
+        yield Y::default();
+        2
+    }
+}
+
+#[rustc_polymorphize_error]
+pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Return = R> + Unpin {
+    || {
+        yield 3;
+        R::default()
+    }
+}
+
+#[rustc_polymorphize_error]
+pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+    //~^ ERROR item has unused generic parameters
+    || {
+        //~^ ERROR item has unused generic parameters
+        yield 1;
+        2
+    }
+}
+
+#[rustc_polymorphize_error]
+pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
+{
+    || {
+        yield Y;
+        2
+    }
+}
+
+#[rustc_polymorphize_error]
+pub fn used_const_in_return<const R: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
+{
+    || {
+        yield 4;
+        R
+    }
+}
+
+fn main() {
+    finish(unused_type::<u32>());
+    finish(used_type_in_yield::<u32>());
+    finish(used_type_in_return::<u32>());
+    finish(unused_const::<1u32>());
+    finish(used_const_in_yield::<1u32>());
+    finish(used_const_in_return::<1u32>());
+}
diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr
new file mode 100644 (file)
index 0000000..c59055b
--- /dev/null
@@ -0,0 +1,49 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/generators.rs:3:12
+   |
+LL | #![feature(const_generics, generators, generator_trait, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+error: item has unused generic parameters
+  --> $DIR/generators.rs:36:5
+   |
+LL |   pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+   |                      - generic parameter `T` is unused
+LL |
+LL | /     || {
+LL | |
+LL | |         yield 1;
+LL | |         2
+LL | |     }
+   | |_____^
+
+error: item has unused generic parameters
+  --> $DIR/generators.rs:34:8
+   |
+LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+   |        ^^^^^^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+  --> $DIR/generators.rs:62:5
+   |
+LL |   pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+   |                             - generic parameter `T` is unused
+LL |
+LL | /     || {
+LL | |
+LL | |         yield 1;
+LL | |         2
+LL | |     }
+   | |_____^
+
+error: item has unused generic parameters
+  --> $DIR/generators.rs:60:8
+   |
+LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+   |        ^^^^^^^^^^^^       - generic parameter `T` is unused
+
+error: aborting due to 4 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/polymorphization/lifetimes.rs b/src/test/ui/polymorphization/lifetimes.rs
new file mode 100644 (file)
index 0000000..f26df45
--- /dev/null
@@ -0,0 +1,25 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(rustc_attrs)]
+
+// This test checks that the polymorphization analysis doesn't break when the
+// function/closure doesn't just have generic parameters.
+
+// Function has an unused generic parameter.
+#[rustc_polymorphize_error]
+pub fn unused<'a, T>(_: &'a u32) {
+    //~^ ERROR item has unused generic parameters
+}
+
+#[rustc_polymorphize_error]
+pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
+    let _: T = Default::default();
+    let add_one = |x: u32| x + 1;
+    //~^ ERROR item has unused generic parameters
+    add_one(3)
+}
+
+fn main() {
+    unused::<u32>(&3);
+    used::<u32>(&3);
+}
diff --git a/src/test/ui/polymorphization/lifetimes.stderr b/src/test/ui/polymorphization/lifetimes.stderr
new file mode 100644 (file)
index 0000000..2020256
--- /dev/null
@@ -0,0 +1,17 @@
+error: item has unused generic parameters
+  --> $DIR/lifetimes.rs:10:8
+   |
+LL | pub fn unused<'a, T>(_: &'a u32) {
+   |        ^^^^^^     - generic parameter `T` is unused
+
+error: item has unused generic parameters
+  --> $DIR/lifetimes.rs:17:19
+   |
+LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
+   |                 - generic parameter `T` is unused
+LL |     let _: T = Default::default();
+LL |     let add_one = |x: u32| x + 1;
+   |                   ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/polymorphization/normalized_sig_types.rs b/src/test/ui/polymorphization/normalized_sig_types.rs
new file mode 100644 (file)
index 0000000..d732b10
--- /dev/null
@@ -0,0 +1,26 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on
+
+pub trait ParallelIterator: Sized {
+    fn drive<C: Consumer<()>>(_: C) {
+        C::into_folder();
+    }
+}
+
+pub trait Consumer<T>: Sized {
+    type Result;
+    fn into_folder() -> Self::Result;
+}
+
+impl ParallelIterator for () {}
+
+impl<F: Fn(), T> Consumer<T> for F {
+    type Result = ();
+    fn into_folder() -> Self::Result {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    <()>::drive(|| ());
+}
diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs
new file mode 100644 (file)
index 0000000..82a9493
--- /dev/null
@@ -0,0 +1,24 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(rustc_attrs)]
+
+// This test checks that `T` is considered used in `foo`, because it is used in a predicate for
+// `I`, which is used.
+
+#[rustc_polymorphize_error]
+fn bar<I>() {
+    //~^ ERROR item has unused generic parameters
+}
+
+#[rustc_polymorphize_error]
+fn foo<I, T>(_: I)
+where
+    I: Iterator<Item = T>,
+{
+    bar::<I>()
+}
+
+fn main() {
+    let x = &[2u32];
+    foo(x.iter());
+}
diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr
new file mode 100644 (file)
index 0000000..c23730f
--- /dev/null
@@ -0,0 +1,8 @@
+error: item has unused generic parameters
+  --> $DIR/predicates.rs:9:4
+   |
+LL | fn bar<I>() {
+   |    ^^^ - generic parameter `I` is unused
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/polymorphization/promoted-function.rs b/src/test/ui/polymorphization/promoted-function.rs
new file mode 100644 (file)
index 0000000..0d3af7a
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+fn fop<T>() {}
+
+fn bar<T>() -> &'static fn() {
+    &(fop::<T> as fn())
+}
+pub const FN: &'static fn() = &(fop::<i32> as fn());
+
+fn main() {
+    bar::<u32>();
+    bar::<i32>();
+    (FN)();
+}
diff --git a/src/test/ui/polymorphization/too-many-generic-params.rs b/src/test/ui/polymorphization/too-many-generic-params.rs
new file mode 100644 (file)
index 0000000..ec62446
--- /dev/null
@@ -0,0 +1,85 @@
+// build-pass
+#![feature(rustc_attrs)]
+
+// This test checks that the analysis doesn't panic when there are >64 generic parameters, but
+// instead considers those parameters used.
+
+#[rustc_polymorphize_error]
+fn bar<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA,
+       AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW,
+       AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL, BM>()
+{
+    let _: Option<A> = None;
+    let _: Option<B> = None;
+    let _: Option<C> = None;
+    let _: Option<D> = None;
+    let _: Option<E> = None;
+    let _: Option<F> = None;
+    let _: Option<G> = None;
+    let _: Option<H> = None;
+    let _: Option<I> = None;
+    let _: Option<J> = None;
+    let _: Option<K> = None;
+    let _: Option<L> = None;
+    let _: Option<M> = None;
+    let _: Option<N> = None;
+    let _: Option<O> = None;
+    let _: Option<P> = None;
+    let _: Option<Q> = None;
+    let _: Option<R> = None;
+    let _: Option<S> = None;
+    let _: Option<T> = None;
+    let _: Option<U> = None;
+    let _: Option<V> = None;
+    let _: Option<W> = None;
+    let _: Option<X> = None;
+    let _: Option<Y> = None;
+    let _: Option<Z> = None;
+    let _: Option<AA> = None;
+    let _: Option<AB> = None;
+    let _: Option<AC> = None;
+    let _: Option<AD> = None;
+    let _: Option<AE> = None;
+    let _: Option<AF> = None;
+    let _: Option<AG> = None;
+    let _: Option<AH> = None;
+    let _: Option<AI> = None;
+    let _: Option<AJ> = None;
+    let _: Option<AK> = None;
+    let _: Option<AL> = None;
+    let _: Option<AM> = None;
+    let _: Option<AN> = None;
+    let _: Option<AO> = None;
+    let _: Option<AP> = None;
+    let _: Option<AQ> = None;
+    let _: Option<AR> = None;
+    let _: Option<AS> = None;
+    let _: Option<AT> = None;
+    let _: Option<AU> = None;
+    let _: Option<AV> = None;
+    let _: Option<AW> = None;
+    let _: Option<AX> = None;
+    let _: Option<AY> = None;
+    let _: Option<AZ> = None;
+    let _: Option<BA> = None;
+    let _: Option<BB> = None;
+    let _: Option<BC> = None;
+    let _: Option<BD> = None;
+    let _: Option<BE> = None;
+    let _: Option<BF> = None;
+    let _: Option<BG> = None;
+    let _: Option<BH> = None;
+    let _: Option<BI> = None;
+    let _: Option<BJ> = None;
+    let _: Option<BK> = None;
+    let _: Option<BL> = None;
+    let _: Option<BM> = None;
+}
+
+fn main() {
+    bar::<u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+          u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+          u32>();
+}
diff --git a/src/test/ui/polymorphization/type_parameters/closures.rs b/src/test/ui/polymorphization/type_parameters/closures.rs
new file mode 100644 (file)
index 0000000..07ab135
--- /dev/null
@@ -0,0 +1,161 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(stmt_expr_attributes, rustc_attrs)]
+
+// This test checks that the polymorphization analysis correctly detects unused type
+// parameters in closures.
+
+// Function doesn't have any generic parameters to be unused.
+#[rustc_polymorphize_error]
+pub fn no_parameters() {
+    let _ = || {};
+}
+
+// Function has an unused generic parameter in parent and closure.
+#[rustc_polymorphize_error]
+pub fn unused<T>() -> u32 {
+    //~^ ERROR item has unused generic parameters
+
+    let add_one = |x: u32| x + 1;
+    //~^ ERROR item has unused generic parameters
+    add_one(3)
+}
+
+// Function has an unused generic parameter in closure, but not in parent.
+#[rustc_polymorphize_error]
+pub fn used_parent<T: Default>() -> u32 {
+    let _: T = Default::default();
+    let add_one = |x: u32| x + 1;
+    //~^ ERROR item has unused generic parameters
+    add_one(3)
+}
+
+// Function uses generic parameter in value of a binding in closure.
+#[rustc_polymorphize_error]
+pub fn used_binding_value<T: Default>() -> T {
+    let x = || {
+        let y: T = Default::default();
+        y
+    };
+
+    x()
+}
+
+// Function uses generic parameter in generic of a binding in closure.
+#[rustc_polymorphize_error]
+pub fn used_binding_generic<T>() -> Option<T> {
+    let x = || {
+        let y: Option<T> = None;
+        y
+    };
+
+    x()
+}
+
+// Function and closure uses generic parameter in argument.
+#[rustc_polymorphize_error]
+pub fn used_argument<T>(t: T) -> u32 {
+    let x = |_: T| 3;
+    x(t)
+}
+
+// Closure uses generic parameter in argument.
+#[rustc_polymorphize_error]
+pub fn used_argument_closure<T: Default>() -> u32 {
+    let t: T = Default::default();
+
+    let x = |_: T| 3;
+    x(t)
+}
+
+// Closure uses generic parameter as upvar.
+#[rustc_polymorphize_error]
+pub fn used_upvar<T: Default>() -> T {
+    let x: T = Default::default();
+
+    let y = || x;
+    y()
+}
+
+// Closure uses generic parameter in substitutions to another function.
+#[rustc_polymorphize_error]
+pub fn used_substs<T>() -> u32 {
+    let x = || unused::<T>();
+    x()
+}
+
+struct Foo<F>(F);
+
+impl<F: Default> Foo<F> {
+    // Function has an unused generic parameter from impl and fn.
+    #[rustc_polymorphize_error]
+    pub fn unused_all<G: Default>() -> u32 {
+        //~^ ERROR item has unused generic parameters
+        let add_one = |x: u32| x + 1;
+        //~^ ERROR item has unused generic parameters
+        add_one(3)
+    }
+
+    // Function uses generic parameter from impl and fn in closure.
+    #[rustc_polymorphize_error]
+    pub fn used_both<G: Default>() -> u32 {
+        let add_one = |x: u32| {
+            let _: F = Default::default();
+            let _: G = Default::default();
+            x + 1
+        };
+
+        add_one(3)
+    }
+
+    // Function uses generic parameter from fn in closure.
+    #[rustc_polymorphize_error]
+    pub fn used_fn<G: Default>() -> u32 {
+        //~^ ERROR item has unused generic parameters
+        let add_one = |x: u32| {
+            //~^ ERROR item has unused generic parameters
+            let _: G = Default::default();
+            x + 1
+        };
+
+        add_one(3)
+    }
+
+    // Function uses generic parameter from impl in closure.
+    #[rustc_polymorphize_error]
+    pub fn used_impl<G: Default>() -> u32 {
+        //~^ ERROR item has unused generic parameters
+        let add_one = |x: u32| {
+            //~^ ERROR item has unused generic parameters
+            let _: F = Default::default();
+            x + 1
+        };
+
+        add_one(3)
+    }
+
+    // Closure uses generic parameter in substitutions to another function.
+    #[rustc_polymorphize_error]
+    pub fn used_substs() -> u32 {
+        let x = || unused::<F>();
+        x()
+    }
+}
+
+fn main() {
+    no_parameters();
+    let _ = unused::<u32>();
+    let _ = used_parent::<u32>();
+    let _ = used_binding_value::<u32>();
+    let _ = used_binding_generic::<u32>();
+    let _ = used_argument(3u32);
+    let _ = used_argument_closure::<u32>();
+    let _ = used_upvar::<u32>();
+    let _ = used_substs::<u32>();
+
+    let _ = Foo::<u32>::unused_all::<u32>();
+    let _ = Foo::<u32>::used_both::<u32>();
+    let _ = Foo::<u32>::used_impl::<u32>();
+    let _ = Foo::<u32>::used_fn::<u32>();
+    let _ = Foo::<u32>::used_substs();
+}
diff --git a/src/test/ui/polymorphization/type_parameters/closures.stderr b/src/test/ui/polymorphization/type_parameters/closures.stderr
new file mode 100644 (file)
index 0000000..417feeb
--- /dev/null
@@ -0,0 +1,90 @@
+error: item has unused generic parameters
+  --> $DIR/closures.rs:19:19
+   |
+LL | pub fn unused<T>() -> u32 {
+   |               - generic parameter `T` is unused
+...
+LL |     let add_one = |x: u32| x + 1;
+   |                   ^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:16:8
+   |
+LL | pub fn unused<T>() -> u32 {
+   |        ^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:28:19
+   |
+LL | pub fn used_parent<T: Default>() -> u32 {
+   |                    - generic parameter `T` is unused
+LL |     let _: T = Default::default();
+LL |     let add_one = |x: u32| x + 1;
+   |                   ^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:94:23
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn unused_all<G: Default>() -> u32 {
+   |                       - generic parameter `G` is unused
+LL |
+LL |         let add_one = |x: u32| x + 1;
+   |                       ^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:92:12
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn unused_all<G: Default>() -> u32 {
+   |            ^^^^^^^^^^ - generic parameter `G` is unused
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:128:23
+   |
+LL |       pub fn used_impl<G: Default>() -> u32 {
+   |                        - generic parameter `G` is unused
+LL |
+LL |           let add_one = |x: u32| {
+   |  _______________________^
+LL | |
+LL | |             let _: F = Default::default();
+LL | |             x + 1
+LL | |         };
+   | |_________^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:126:12
+   |
+LL |     pub fn used_impl<G: Default>() -> u32 {
+   |            ^^^^^^^^^ - generic parameter `G` is unused
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:115:23
+   |
+LL |   impl<F: Default> Foo<F> {
+   |        - generic parameter `F` is unused
+...
+LL |           let add_one = |x: u32| {
+   |  _______________________^
+LL | |
+LL | |             let _: G = Default::default();
+LL | |             x + 1
+LL | |         };
+   | |_________^
+
+error: item has unused generic parameters
+  --> $DIR/closures.rs:113:12
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn used_fn<G: Default>() -> u32 {
+   |            ^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/polymorphization/type_parameters/functions.rs b/src/test/ui/polymorphization/type_parameters/functions.rs
new file mode 100644 (file)
index 0000000..aad957e
--- /dev/null
@@ -0,0 +1,96 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(rustc_attrs)]
+
+// This test checks that the polymorphization analysis correctly detects unused type
+// parameters in functions.
+
+// Function doesn't have any generic parameters to be unused.
+#[rustc_polymorphize_error]
+pub fn no_parameters() {}
+
+// Function has an unused generic parameter.
+#[rustc_polymorphize_error]
+pub fn unused<T>() {
+    //~^ ERROR item has unused generic parameters
+}
+
+// Function uses generic parameter in value of a binding.
+#[rustc_polymorphize_error]
+pub fn used_binding_value<T: Default>() {
+    let _: T = Default::default();
+}
+
+// Function uses generic parameter in generic of a binding.
+#[rustc_polymorphize_error]
+pub fn used_binding_generic<T>() {
+    let _: Option<T> = None;
+}
+
+// Function uses generic parameter in argument.
+#[rustc_polymorphize_error]
+pub fn used_argument<T>(_: T) {}
+
+// Function uses generic parameter in substitutions to another function.
+#[rustc_polymorphize_error]
+pub fn used_substs<T>() {
+    unused::<T>()
+}
+
+struct Foo<F>(F);
+
+impl<F: Default> Foo<F> {
+    // Function has an unused generic parameter from impl.
+    #[rustc_polymorphize_error]
+    pub fn unused_impl() {
+        //~^ ERROR item has unused generic parameters
+    }
+
+    // Function has an unused generic parameter from impl and fn.
+    #[rustc_polymorphize_error]
+    pub fn unused_both<G: Default>() {
+        //~^ ERROR item has unused generic parameters
+    }
+
+    // Function uses generic parameter from impl.
+    #[rustc_polymorphize_error]
+    pub fn used_impl() {
+        let _: F = Default::default();
+    }
+
+    // Function uses generic parameter from impl.
+    #[rustc_polymorphize_error]
+    pub fn used_fn<G: Default>() {
+        //~^ ERROR item has unused generic parameters
+        let _: G = Default::default();
+    }
+
+    // Function uses generic parameter from impl.
+    #[rustc_polymorphize_error]
+    pub fn used_both<G: Default>() {
+        let _: F = Default::default();
+        let _: G = Default::default();
+    }
+
+    // Function uses generic parameter in substitutions to another function.
+    #[rustc_polymorphize_error]
+    pub fn used_substs() {
+        unused::<F>()
+    }
+}
+
+fn main() {
+    no_parameters();
+    unused::<u32>();
+    used_binding_value::<u32>();
+    used_binding_generic::<u32>();
+    used_argument(3u32);
+    used_substs::<u32>();
+
+    Foo::<u32>::unused_impl();
+    Foo::<u32>::unused_both::<u32>();
+    Foo::<u32>::used_impl();
+    Foo::<u32>::used_fn::<u32>();
+    Foo::<u32>::used_both::<u32>();
+    Foo::<u32>::used_substs();
+}
diff --git a/src/test/ui/polymorphization/type_parameters/functions.stderr b/src/test/ui/polymorphization/type_parameters/functions.stderr
new file mode 100644 (file)
index 0000000..d629ff7
--- /dev/null
@@ -0,0 +1,35 @@
+error: item has unused generic parameters
+  --> $DIR/functions.rs:14:8
+   |
+LL | pub fn unused<T>() {
+   |        ^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+  --> $DIR/functions.rs:45:12
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn unused_impl() {
+   |            ^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/functions.rs:51:12
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn unused_both<G: Default>() {
+   |            ^^^^^^^^^^^ - generic parameter `G` is unused
+
+error: item has unused generic parameters
+  --> $DIR/functions.rs:63:12
+   |
+LL | impl<F: Default> Foo<F> {
+   |      - generic parameter `F` is unused
+...
+LL |     pub fn used_fn<G: Default>() {
+   |            ^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/polymorphization/unsized_cast.rs b/src/test/ui/polymorphization/unsized_cast.rs
new file mode 100644 (file)
index 0000000..b8facc1
--- /dev/null
@@ -0,0 +1,29 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(fn_traits, rustc_attrs, unboxed_closures)]
+
+// This test checks that the polymorphization analysis considers a closure
+// as using all generic parameters if it does an unsizing cast.
+
+#[rustc_polymorphize_error]
+fn foo<T: Default>() {
+    let _: T = Default::default();
+    (|| Box::new(|| {}) as Box<dyn Fn()>)();
+    //~^ ERROR item has unused generic parameters
+    //~^^ ERROR item has unused generic parameters
+}
+
+#[rustc_polymorphize_error]
+fn foo2<T: Default>() {
+    let _: T = Default::default();
+    (|| {
+        let call: extern "rust-call" fn(_, _) = Fn::call;
+        call(&|| {}, ());
+        //~^ ERROR item has unused generic parameters
+    })();
+}
+
+fn main() {
+    foo::<u32>();
+    foo2::<u32>();
+}
diff --git a/src/test/ui/polymorphization/unsized_cast.stderr b/src/test/ui/polymorphization/unsized_cast.stderr
new file mode 100644 (file)
index 0000000..d4727ac
--- /dev/null
@@ -0,0 +1,29 @@
+error: item has unused generic parameters
+  --> $DIR/unsized_cast.rs:11:18
+   |
+LL | fn foo<T: Default>() {
+   |        - generic parameter `T` is unused
+LL |     let _: T = Default::default();
+LL |     (|| Box::new(|| {}) as Box<dyn Fn()>)();
+   |                  ^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/unsized_cast.rs:11:5
+   |
+LL | fn foo<T: Default>() {
+   |        - generic parameter `T` is unused
+LL |     let _: T = Default::default();
+LL |     (|| Box::new(|| {}) as Box<dyn Fn()>)();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+  --> $DIR/unsized_cast.rs:21:15
+   |
+LL | fn foo2<T: Default>() {
+   |         - generic parameter `T` is unused
+...
+LL |         call(&|| {}, ());
+   |               ^^^^^
+
+error: aborting due to 3 previous errors
+
index 1894cd218ee347f94546d2b7fa32a878f5937ad1..301edc0d086b11fee1b251fd47b5ab7ebba36190 100644 (file)
@@ -8,12 +8,12 @@ print-type-size     variant `Some`: 12 bytes
 print-type-size         field `.0`: 12 bytes
 print-type-size     variant `None`: 0 bytes
 print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
-print-type-size     discriminant: 1 bytes
 print-type-size     variant `Record`: 7 bytes
-print-type-size         field `.pre`: 1 bytes
-print-type-size         field `.post`: 2 bytes
 print-type-size         field `.val`: 4 bytes
+print-type-size         field `.post`: 2 bytes
+print-type-size         field `.pre`: 1 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size     end padding: 1 bytes
 print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 4 bytes
 print-type-size     variant `Some`: 4 bytes
index 2c21221fbb0f5b436b554a8500766656fc47e6eb..3c851b6de2a1ac8f624780246c37871dcce3da86 100644 (file)
@@ -6,7 +6,13 @@ macro_rules! make_it {
         #[proc_macro]
         pub fn $name(input: TokenStream) -> TokenStream {
             println!("Def site: {:?}", Span::def_site());
-            input
+            println!("Input: {:?}", input);
+            let new: TokenStream = input.into_iter().map(|mut t| {
+                t.set_span(Span::def_site());
+                t
+            }).collect();
+            println!("Respanned: {:?}", new);
+            new
         }
     };
 }
index 5265c6533b4799fec444b01543b432b71f53375c..0a9b9887d95535fd9ba4627ed12e1ce5ee1b86a1 100644 (file)
@@ -10,3 +10,6 @@
 use proc_macro::{TokenStream, Span};
 
 make_macro::make_it!(print_def_site);
+
+#[proc_macro]
+pub fn dummy(input: TokenStream) -> TokenStream { input }
index fb13bb064c7089117d9fc9d1a69b2d1b49884ad3..9ce90e42069fbd7820fd938fcb2733bbf79090ab 100644 (file)
@@ -5,6 +5,7 @@
 // Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
 // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
 // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+// normalize-stdout-test "#\d+" -> "#CTXT"
 
 #[macro_use]
 extern crate test_macros;
index 5d93144b445530ddf79b355c2ca14a278179ebd2..c36c75603876ddeadb17244f2436ba04fac2ada1 100644 (file)
@@ -2,79 +2,79 @@ PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
index 223c4047cb2b1e2548b9dd2fb86fcf23ad00c3a7..2a9ff4c20cdec9530b4481aab0d1c9726a1fab01 100644 (file)
@@ -6,6 +6,7 @@
 // Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
 // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
 // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+// normalize-stdout-test "#\d+" -> "#CTXT"
 
 #[macro_use]
 extern crate test_macros;
index e4212377626ca7fdccc575b5388a59ac039dee1c..456940b89da2b04026afd0526e21748e00110bda 100644 (file)
@@ -2,109 +2,109 @@ PRINT-ATTR INPUT (DISPLAY): struct A(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "identity",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: '!',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "$crate",
-                        span: #3 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Joint,
-                        span: #3 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Alone,
-                        span: #3 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Ident {
                         ident: "S",
-                        span: #3 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                 ],
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct B(identity ! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "B",
-        span: #10 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "identity",
-                span: #10 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: '!',
                 spacing: Alone,
-                span: #10 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "$crate",
-                        span: #10 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Joint,
-                        span: #10 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Punct {
                         ch: ':',
                         spacing: Alone,
-                        span: #10 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                     Ident {
                         ident: "S",
-                        span: #10 bytes(LO..HI),
+                        span: #CTXT bytes(LO..HI),
                     },
                 ],
-                span: #10 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #10 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
index 5f2549376d1ba25ea0e88fd193cc7db07ef0fdb8..1a5223d3d4190c24ae1be664cd39b8ffba625e13 100644 (file)
@@ -6,6 +6,7 @@
 // Anonymize unstable non-dummy spans while still showing dummy spans `0..0`.
 // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
 // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
+// normalize-stdout-test "#\d+" -> "#CTXT"
 
 #[macro_use]
 extern crate test_macros;
index 8a7406b1a3d134350ed110566dc505911311d0dc..deef102afb2d9faad8fc8623eb5e713f0645c1ff 100644 (file)
@@ -2,239 +2,239 @@ PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #3 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #3 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #13 bytes(LO..HI),
+                span: #CTXT bytes(LO..HI),
             },
         ],
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #13 bytes(LO..HI),
+        span: #CTXT bytes(LO..HI),
     },
 ]
index b57ce99b13841a41379ec11fa2527234cb948754..41c829d9d889945bdef0227c3065ed767823b89a 100644 (file)
@@ -1,6 +1,7 @@
 // Check what token streams proc macros see when interpolated tokens are passed to them as input.
 
 // check-pass
+// normalize-stdout-test "#\d+" -> "#CTXT"
 // aux-build:test-macros.rs
 
 #[macro_use]
index ee988d48b461d30d1e76bd50d72e1bd35f0f7877..d98f52249a7812d837f077a7f25032d012fac089 100644 (file)
@@ -5,61 +5,61 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "A",
-                span: #0 bytes(402..403),
+                span: #CTXT bytes(445..446),
             },
         ],
-        span: #3 bytes(269..271),
+        span: #CTXT bytes(312..314),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "const",
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Ident {
         ident: "A",
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Punct {
         ch: ':',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Ident {
         ident: "u8",
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Punct {
         ch: '=',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Literal {
         kind: Integer,
         symbol: "0",
         suffix: None,
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct A { }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Ident {
         ident: "A",
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [],
-        span: #0 bytes(0..0),
+        span: #CTXT bytes(0..0),
     },
 ]
index 449377aed993e87dd302213e55722fe422950ea3..4b1787453cb55c6609d675ab4651fc21dff8adba 100644 (file)
@@ -1,13 +1,26 @@
 // aux-build:make-macro.rs
 // aux-build:meta-macro.rs
 // edition:2018
-// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
+// compile-flags: -Z span-debug -Z macro-backtrace
 // check-pass
+// normalize-stdout-test "#\d+" -> "#CTXT"
 // normalize-stdout-test "\d+#" -> "0#"
-// ^ We don't care about symbol ids, so set them all to 0
+//
+// We don't care about symbol ids, so we set them all to 0
 // in the stdout
 extern crate meta_macro;
 
+macro_rules! produce_it {
+    () => {
+        // `print_def_site!` will respan the `$crate` identifier
+        // with `Span::def_site()`. This should cause it to resolve
+        // relative to `meta_macro`, *not* `make_macro` (despite
+        // the fact that that `print_def_site` is produced by
+        // a `macro_rules!` macro in `make_macro`).
+        meta_macro::print_def_site!($crate::dummy!());
+    }
+}
+
 fn main() {
-    meta_macro::print_def_site!();
+    produce_it!();
 }
index daca40eda90065586706980f76dcc2590fc618b2..e162bdd7fc090594f60006c972d7d37e80b517fc 100644 (file)
@@ -1,32 +1,3 @@
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#3)
-#![feature /* 0#0 */(prelude_import)]
-#[prelude_import /* 0#1 */]
-use std /* 0#1 */::prelude /* 0#1 */::v1 /* 0#1 */::*;
-#[macro_use /* 0#1 */]
-extern crate std /* 0#1 */;
-// aux-build:make-macro.rs
-// aux-build:meta-macro.rs
-// edition:2018
-// compile-flags: -Z span-debug -Z unpretty=expanded,hygiene
-// check-pass
-// normalize-stdout-test "\d+#" -> "0#"
-// ^ We don't care about symbol ids, so set them all to 0
-// in the stdout
-extern crate meta_macro /* 0#0 */;
-
-fn main /* 0#0 */() { }
-
-/*
-Expansions:
-0: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Root
-1: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: AstPass(StdImports)
-2: parent: ExpnId(0), call_site_ctxt: #0, def_site_ctxt: #0, kind: Macro(Bang, "meta_macro::print_def_site")
-
-SyntaxContexts:
-#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
-#1: parent: #0, outer_mark: (ExpnId(1), Opaque)
-#2: parent: #0, outer_mark: (ExpnId(1), Transparent)
-#3: parent: #0, outer_mark: (ExpnId(2), Opaque)
-#4: parent: #0, outer_mark: (ExpnId(2), Transparent)
-#5: parent: #0, outer_mark: (ExpnId(2), SemiTransparent)
-*/
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT)
+Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:20:37: 20:43 (#CTXT) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:20:43: 20:45 (#CTXT) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:20:43: 20:45 (#CTXT) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:20:45: 20:50 (#CTXT) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:20:50: 20:51 (#CTXT) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:20:51: 20:53 (#CTXT) }]
+Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT) }]
index dbfde9e113f37747eb4bc434b0913d1a039a73ff..579e232c0d92beb64b22619cc16fbc1ed97cef04 100644 (file)
@@ -2,6 +2,7 @@
 // aux-build:meta-macro.rs
 // edition:2018
 // compile-flags: -Z span-debug
+// normalize-stdout-test "#\d+" -> "#CTXT"
 // run-pass
 
 extern crate meta_macro;
index fa79f72137f64e2c8ca9ebaecfc7057b15da8c9c..a9847a25d9273df411e8f47b084d2834529ef07e 100644 (file)
@@ -1 +1,3 @@
-Def site: $DIR/auxiliary/make-macro.rs:7:9: 10:10 (#3)
+Def site: $DIR/auxiliary/make-macro.rs:7:9: 16:10 (#CTXT)
+Input: TokenStream []
+Respanned: TokenStream []
index 2f8ef20232782d663d91dc669e93d0e13580855e..62c3dd84ce1a4b4172ef8df8a4e28178471344c1 100644 (file)
@@ -2,6 +2,7 @@
 // aux-build:nested-macro-rules.rs
 // aux-build:test-macros.rs
 // compile-flags: -Z span-debug
+// normalize-stdout-test "#\d+" -> "#CTXT"
 // edition:2018
 
 extern crate nested_macro_rules;
index e4cfe020324b8b9090f1856e8c3ebad95b2766af..337b9863def1b0c5b00e7fa7877aeb0bd699f58b 100644 (file)
@@ -5,10 +5,10 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "FirstStruct",
-                span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#3),
+                span: $DIR/auxiliary/nested-macro-rules.rs:15:14: 15:25 (#CTXT),
             },
         ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#3),
+        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#CTXT),
     },
 ]
 PRINT-BANG INPUT (DISPLAY): SecondStruct
@@ -18,9 +18,9 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Ident {
                 ident: "SecondStruct",
-                span: $DIR/nested-macro-rules.rs:18:38: 18:50 (#9),
+                span: $DIR/nested-macro-rules.rs:19:38: 19:50 (#CTXT),
             },
         ],
-        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#8),
+        span: $DIR/auxiliary/nested-macro-rules.rs:9:27: 9:32 (#CTXT),
     },
 ]
index cfcd4c0d2a658071b66780086b6a00c50a449d98..1dc8796de90f9df7ac62bda677f20df004923cfe 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // aux-build:test-macros.rs
 // compile-flags: -Z span-debug
+// normalize-stdout-test "#\d+" -> "#CTXT"
 // edition:2018
 //
 // Tests the pretty-printing behavior of inserting `NoDelim` groups
index 75a189a9fcdeab28073086e5282a7de052ef1cae..79cdf2b53b52e8481cf28af9e5891bf61d0f89ab 100644 (file)
@@ -4,7 +4,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         kind: Str,
         symbol: "hi",
         suffix: None,
-        span: $DIR/nodelim-groups.rs:13:42: 13:46 (#3),
+        span: $DIR/nodelim-groups.rs:14:42: 14:46 (#CTXT),
     },
     Group {
         delimiter: None,
@@ -13,12 +13,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:17:16: 17:17 (#0),
+                span: $DIR/nodelim-groups.rs:18:16: 18:17 (#CTXT),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:17:18: 17:19 (#0),
+                span: $DIR/nodelim-groups.rs:18:18: 18:19 (#CTXT),
             },
             Group {
                 delimiter: Parenthesis,
@@ -27,24 +27,24 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                         kind: Integer,
                         symbol: "25",
                         suffix: None,
-                        span: $DIR/nodelim-groups.rs:17:21: 17:23 (#0),
+                        span: $DIR/nodelim-groups.rs:18:21: 18:23 (#CTXT),
                     },
                 ],
-                span: $DIR/nodelim-groups.rs:17:20: 17:24 (#0),
+                span: $DIR/nodelim-groups.rs:18:20: 18:24 (#CTXT),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:17:25: 17:26 (#0),
+                span: $DIR/nodelim-groups.rs:18:25: 18:26 (#CTXT),
             },
             Literal {
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:17:27: 17:28 (#0),
+                span: $DIR/nodelim-groups.rs:18:27: 18:28 (#CTXT),
             },
         ],
-        span: $DIR/nodelim-groups.rs:13:47: 13:51 (#3),
+        span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
     },
     Group {
         delimiter: Parenthesis,
@@ -53,21 +53,21 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:53: 13:54 (#3),
+                span: $DIR/nodelim-groups.rs:14:53: 14:54 (#CTXT),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:13:55: 13:56 (#3),
+                span: $DIR/nodelim-groups.rs:14:55: 14:56 (#CTXT),
             },
             Literal {
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:57: 13:58 (#3),
+                span: $DIR/nodelim-groups.rs:14:57: 14:58 (#CTXT),
             },
         ],
-        span: $DIR/nodelim-groups.rs:13:52: 13:59 (#3),
+        span: $DIR/nodelim-groups.rs:14:52: 14:59 (#CTXT),
     },
 ]
 PRINT-BANG INPUT (DISPLAY): "hi" "hello".len() + "world".len() (1 + 1)
@@ -77,7 +77,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         kind: Str,
         symbol: "hi",
         suffix: None,
-        span: $DIR/nodelim-groups.rs:13:42: 13:46 (#8),
+        span: $DIR/nodelim-groups.rs:14:42: 14:46 (#CTXT),
     },
     Group {
         delimiter: None,
@@ -86,49 +86,49 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                 kind: Str,
                 symbol: "hello",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Punct {
                 ch: '.',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Ident {
                 ident: "len",
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [],
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Literal {
                 kind: Str,
                 symbol: "world",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Punct {
                 ch: '.',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Ident {
                 ident: "len",
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [],
-                span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+                span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
             },
         ],
-        span: $DIR/nodelim-groups.rs:13:47: 13:51 (#8),
+        span: $DIR/nodelim-groups.rs:14:47: 14:51 (#CTXT),
     },
     Group {
         delimiter: Parenthesis,
@@ -137,20 +137,20 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:53: 13:54 (#8),
+                span: $DIR/nodelim-groups.rs:14:53: 14:54 (#CTXT),
             },
             Punct {
                 ch: '+',
                 spacing: Alone,
-                span: $DIR/nodelim-groups.rs:13:55: 13:56 (#8),
+                span: $DIR/nodelim-groups.rs:14:55: 14:56 (#CTXT),
             },
             Literal {
                 kind: Integer,
                 symbol: "1",
                 suffix: None,
-                span: $DIR/nodelim-groups.rs:13:57: 13:58 (#8),
+                span: $DIR/nodelim-groups.rs:14:57: 14:58 (#CTXT),
             },
         ],
-        span: $DIR/nodelim-groups.rs:13:52: 13:59 (#8),
+        span: $DIR/nodelim-groups.rs:14:52: 14:59 (#CTXT),
     },
 ]
index 5d199149c39b860d029bc80728988afe33c76b25..9d3f485e314385148fd081174954b3faaf1cedb7 100644 (file)
@@ -5,18 +5,18 @@ trait Foo {}
 impl<'a> Foo for &'a [u8] {}
 
 fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-    let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR cannot infer an appropriate lifetime
+    let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR E0759
     x
 }
 
 fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(v) //~ ERROR E0759
 }
 
 fn c(v: &[u8]) -> Box<dyn Foo> {
     // same as previous case due to RFC 599
 
-    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(v) //~ ERROR E0759
 }
 
 fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
index 7f5a3a47976c7d38f812fa9fb9a1232657dd2a1c..63fea1f41626d10e22dda55f34b9a949d772d92d 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:8:46
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
@@ -15,7 +15,7 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
    |         ^^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:13:14
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
@@ -32,7 +32,7 @@ help: alternatively, add an explicit `'static` bound to this reference
 LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
    |         ^^^^^^^^^^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/region-object-lifetime-in-coercion.rs:19:14
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
index 647212407fc8a5217178f5324d3a321039378f9c..4eb1b275f163ec77af5f50bb86c28b486e72644f 100644 (file)
@@ -4,7 +4,7 @@ struct Dog {
 
 impl Dog {
     pub fn chase_cat(&mut self) {
-        let p: &'static mut usize = &mut self.cats_chased; //~ ERROR cannot infer
+        let p: &'static mut usize = &mut self.cats_chased; //~ ERROR E0759
         *p += 1;
     }
 
index a0b8b6b51e5a1b36572ad8567ad4cbfd94ce81b7..738691fd695eb4fe2aa8e05f40fbbe675e108a1b 100644 (file)
@@ -1,29 +1,11 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-addr-of-self.rs:7:37
    |
+LL |     pub fn chase_cat(&mut self) {
+   |                      --------- this data with an anonymous lifetime `'_`...
 LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 6:5...
-  --> $DIR/regions-addr-of-self.rs:6:5
-   |
-LL | /     pub fn chase_cat(&mut self) {
-LL | |         let p: &'static mut usize = &mut self.cats_chased;
-LL | |         *p += 1;
-LL | |     }
-   | |_____^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/regions-addr-of-self.rs:7:37
-   |
-LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/regions-addr-of-self.rs:7:37
-   |
-LL |         let p: &'static mut usize = &mut self.cats_chased;
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
index 2364ba2728600e7f7a4478c3b4621318ee78689c..7144ab5a24c51443ec36b8dffda63669e12317a0 100644 (file)
@@ -7,7 +7,7 @@ trait X { }
 impl<'a, T> X for B<'a, T> {}
 
 fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
-    box B(&*v) as Box<dyn X> //~ ERROR cannot infer
+    box B(&*v) as Box<dyn X> //~ ERROR E0759
 }
 
 fn main() { }
index 114e4052aae09b63159cc61e3899af7c0e982403..aab7ce993aa3c3861a55018bbfb1b46912c75056 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-close-object-into-object-2.rs:10:11
    |
 LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
index d5310770436866d544eae03d33347d6a3027b907..4c087f264f92b964010c16521d98fd6a97f92889 100644 (file)
@@ -7,7 +7,7 @@ trait X { }
 impl<'a, T> X for B<'a, T> {}
 
 fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
-    box B(&*v) as Box<dyn X> //~ ERROR cannot infer
+    box B(&*v) as Box<dyn X> //~ ERROR E0759
 }
 
 fn main() {}
index 850d81940791fd168afbe9224765cf642bbaaf61..90f807a41c5629f07d04aeb0d00a47b1491fa879 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-close-object-into-object-4.rs:10:11
    |
 LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
index 8617c0e9da8f76f51a6319847965b265e8aff148..55d964ac5340569b287a993d650fe88ba70b2f94 100644 (file)
@@ -6,7 +6,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
 
 fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
     // This is illegal, because the region bound on `proc` is 'static.
-    Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(move || { *x }) //~ ERROR E0759
 }
 
 fn main() { }
index 67eee3bb6e28127bbd8db3417d40386340b6a38f..e76073f4f6b13f5b6be54d1179799ef19cd2c63c 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/regions-proc-bound-capture.rs:9:14
    |
 LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
diff --git a/src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs b/src/test/ui/regions/type-param-outlives-reempty-issue-74429-2.rs
new file mode 100644 (file)
index 0000000..a65c17e
--- /dev/null
@@ -0,0 +1,66 @@
+// Regression test for #74429, where we didn't think that a type parameter
+// outlived `ReEmpty`.
+
+// check-pass
+
+use std::marker::PhantomData;
+use std::ptr::NonNull;
+
+pub unsafe trait RawData {
+    type Elem;
+}
+
+unsafe impl<A> RawData for OwnedRepr<A> {
+    type Elem = A;
+}
+
+unsafe impl<'a, A> RawData for ViewRepr<&'a A> {
+    type Elem = A;
+}
+
+pub struct OwnedRepr<A> {
+    ptr: PhantomData<A>,
+}
+
+// these Copy impls are not necessary for the repro, but allow the code to compile without error
+// on 1.44.1
+#[derive(Copy, Clone)]
+pub struct ViewRepr<A> {
+    life: PhantomData<A>,
+}
+
+#[derive(Copy, Clone)]
+pub struct ArrayBase<S>
+where
+    S: RawData,
+{
+    ptr: NonNull<S::Elem>,
+}
+
+pub type Array<A> = ArrayBase<OwnedRepr<A>>;
+
+pub type ArrayView<'a, A> = ArrayBase<ViewRepr<&'a A>>;
+
+impl<A, S> ArrayBase<S>
+where
+    S: RawData<Elem = A>,
+{
+    pub fn index_axis(&self) -> ArrayView<'_, A> {
+        unimplemented!()
+    }
+
+    pub fn axis_iter<'a>(&'a self) -> std::iter::Empty<&'a A> {
+        unimplemented!()
+    }
+}
+
+pub fn x<T: Copy>(a: Array<T>) {
+    // drop just avoids a must_use warning
+    drop((0..1).filter(|_| true));
+    let y = a.index_axis();
+    a.axis_iter().for_each(|_| {
+        drop(y);
+    });
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs b/src/test/ui/regions/type-param-outlives-reempty-issue-74429.rs
new file mode 100644 (file)
index 0000000..d463f31
--- /dev/null
@@ -0,0 +1,35 @@
+// Regression test for #74429, where we didn't think that a type parameter
+// outlived `ReEmpty`.
+
+// check-pass
+
+use std::marker::PhantomData;
+
+fn apply<T, F: FnOnce(T)>(_: T, _: F) {}
+
+#[derive(Clone, Copy)]
+struct Invariant<T> {
+    t: T,
+    p: PhantomData<fn(T) -> T>,
+}
+
+fn verify_reempty<T>(x: T) {
+    // r is inferred to have type `Invariant<&ReEmpty(U0) T>`
+    let r = Invariant { t: &x, p: PhantomData };
+    // Creates a new universe, all variables from now on are in `U1`, say.
+    let _: fn(&()) = |_| {};
+    // Closure parameter is of type `&ReEmpty(U1) T`, so the closure has an implied
+    // bound of `T: ReEmpty(U1)`
+    apply(&x, |_| {
+        // Requires `typeof(r)` is well-formed, i.e. `T: ReEmpty(U0)`. If we
+        // only have the implied bound from the closure parameter to use this
+        // requires `ReEmpty(U1): ReEmpty(U0)`, which isn't true so we reported
+        // an error.
+        //
+        // This doesn't happen any more because we ensure that `T: ReEmpty(U0)`
+        // is an implicit bound for all type parameters.
+        drop(r);
+    });
+}
+
+fn main() {}
index 448077b439e80bb3416fe4fdf62361755fb9fffc..f9b4eed0497c4d83af83f6a2b6743ee8cd22a481 100644 (file)
@@ -8,7 +8,7 @@ LL |     call(foo);
    |          ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
    |
    = help: the trait `std::ops::Fn<()>` is not implemented for `fn() {foo}`
-   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error[E0277]: expected a `std::ops::FnMut<()>` closure, found `fn() {foo}`
@@ -21,7 +21,7 @@ LL |     call_mut(foo);
    |              ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
    |
    = help: the trait `std::ops::FnMut<()>` is not implemented for `fn() {foo}`
-   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `fn() {foo}`
@@ -34,7 +34,7 @@ LL |     call_once(foo);
    |               ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
    |
    = help: the trait `std::ops::FnOnce<()>` is not implemented for `fn() {foo}`
-   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error[E0277]: expected a `std::ops::Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
@@ -47,7 +47,7 @@ LL |     call(foo_unsafe);
    |          ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
    |
    = help: the trait `std::ops::Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
-   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error[E0277]: expected a `std::ops::FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
@@ -60,7 +60,7 @@ LL |     call_mut(foo_unsafe);
    |              ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
    |
    = help: the trait `std::ops::FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
-   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error[E0277]: expected a `std::ops::FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
@@ -73,7 +73,7 @@ LL |     call_once(foo_unsafe);
    |               ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
    |
    = help: the trait `std::ops::FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
-   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }
+   = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 
 error: aborting due to 6 previous errors
index 64d6ccf34091681d386c7c3f746c7e529e2d15fb..9439df266d59bbe6c7da7b1d0a822e3462f55917 100644 (file)
@@ -2,7 +2,7 @@
 // being run when compiling with new LLVM pass manager and ThinLTO.
 // Note: The issue occurred only on non-zero opt-level.
 //
-// min-llvm-version 9.0
+// min-llvm-version: 9.0
 // needs-sanitizer-support
 // needs-sanitizer-address
 //
index 0afe631f1e3fc03921e8539f2eee46ca69cc546f..43998ca8c5784478dfca0e18aea561c2aab3ef40 100644 (file)
@@ -6,7 +6,7 @@
 
 impl Foo {
     async fn f(self: Pin<&Self>) -> impl Clone { self }
-    //~^ ERROR cannot infer an appropriate lifetime
+    //~^ ERROR E0759
 }
 
 fn main() {
index f2fbb0ba7d7556738dd6951afe48ea920e2553d7..9cd0fd328ffa007a37fda588dbed69e79ce2aca9 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
index 5054568b18970ca0331dfde31bed23c1de9c65ac..04935fc52ab9e31253bb8dce181cacfafdd589ac 100644 (file)
@@ -3,7 +3,7 @@
 struct Foo;
 
 impl Foo {
-    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR cannot infer an appropriate lifetime
+    fn f(self: Pin<&Self>) -> impl Clone { self } //~ ERROR E0759
 }
 
 fn main() {
index 2e10ab3d3f9b84a8c1802524008ab8020e311bd2..cb9d5b56dbc5cbd585691e8647bf4a224f660776 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
diff --git a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs b/src/test/ui/specialization/min_specialization/impl-on-nonexisting.rs
new file mode 100644 (file)
index 0000000..77a6432
--- /dev/null
@@ -0,0 +1,7 @@
+#![feature(min_specialization)]
+
+trait Trait {}
+impl Trait for NonExistent {}
+//~^ ERROR cannot find type `NonExistent` in this scope
+
+fn main() {}
diff --git a/src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr b/src/test/ui/specialization/min_specialization/impl-on-nonexisting.stderr
new file mode 100644 (file)
index 0000000..b032ccb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `NonExistent` in this scope
+  --> $DIR/impl-on-nonexisting.rs:4:16
+   |
+LL | impl Trait for NonExistent {}
+   |                ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
index 5db924642e59df3d1f021b83f2f240d0529eef56..80d7ae6dc637d78723cdc17ab762f4d7945bc324 100644 (file)
@@ -62,7 +62,7 @@ fn multiple3() { }
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_const_unstable(feature = "c", issue = "none")]
 #[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels
-pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
+pub const fn multiple4() { } //~ ERROR multiple deprecated attributes
 //~^ ERROR Invalid stability or deprecation version found
 
 #[rustc_deprecated(since = "a", reason = "text")]
index 3c5da3f14403503d00caf5533ede8b3624fd8f80..134c657c62015b51be3739ec0fa7ba2d048d14a1 100644 (file)
@@ -82,7 +82,7 @@ error[E0544]: multiple stability levels
 LL | #[stable(feature = "a", since = "b")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0540]: multiple rustc_deprecated attributes
+error[E0550]: multiple deprecated attributes
   --> $DIR/stability-attribute-sanity.rs:65:1
    |
 LL | pub const fn multiple4() { }
@@ -108,5 +108,5 @@ LL | fn deprecated_without_unstable_or_stable() { }
 
 error: aborting due to 18 previous errors
 
-Some errors have detailed explanations: E0539, E0541.
+Some errors have detailed explanations: E0539, E0541, E0550.
 For more information about an error, try `rustc --explain E0539`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.nll.stderr
new file mode 100644 (file)
index 0000000..acf0c0e
--- /dev/null
@@ -0,0 +1,37 @@
+error[E0597]: `val` does not live long enough
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+   |               -- lifetime `'a` defined here                  ------------------- opaque type requires that `val` is borrowed for `'a`
+LL |         val.use_self()
+   |         ^^^ borrowed value does not live long enough
+LL |     }
+   |     - `val` dropped here while still borrowed
+   |
+help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+   |                                                                                  ^^^^
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs
new file mode 100644 (file)
index 0000000..b2dc16a
--- /dev/null
@@ -0,0 +1,113 @@
+// FIXME: the following cases need to suggest more things to make users reach a working end state.
+
+mod bav {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+        val.use_self() //~ ERROR E0597
+    }
+}
+
+mod bap {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0515
+    }
+}
+
+// This case in particular requires the user to write all of the bounds we have in `mod bax`.
+mod bay {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod bax {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait<'a> {
+        fn use_self(&'a self) -> &'a () { panic!() }
+    }
+    trait Bar {}
+
+    impl<'a> MyTrait<'a> for Box<dyn ObjectTrait<Assoc = i32> + 'a> {
+        fn use_self(&'a self) -> &'a () { panic!() }
+    }
+    impl Bar for i32 {}
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+        val.use_self()
+    }
+}
+
+mod baw {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {
+        type Assoc: Bar;
+    }
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Bar {}
+
+    impl<'a> MyTrait for Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = Box<dyn Bar>>>) -> impl OtherTrait<'a> + 'a{
+        val.use_self() //~ ERROR E0515
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr
new file mode 100644 (file)
index 0000000..00971b4
--- /dev/null
@@ -0,0 +1,57 @@
+error[E0597]: `val` does not live long enough
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:21:9
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> {
+   |               -- lifetime `'a` defined here                  ------------------- opaque type requires that `val` is borrowed for `'a`
+LL |         val.use_self()
+   |         ^^^ borrowed value does not live long enough
+LL |     }
+   |     - `val` dropped here while still borrowed
+   |
+help: you can add a bound to the opaque type to make it last less than `'static` and match `'a`
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32>>) -> impl OtherTrait<'a> + 'a {
+   |                                                                                  ^^^^
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:43:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0515]: cannot return value referencing function parameter `val`
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9
+   |
+LL |         val.use_self()
+   |         ---^^^^^^^^^^^
+   |         |
+   |         returns a value referencing data owned by the current function
+   |         `val` is borrowed here
+
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:13
+   |
+LL |     fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
+   |                        -------------------------------------- this data with lifetime `'a`...
+LL |         val.use_self()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> {
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
+   |                                                       ^^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.fixed
new file mode 100644 (file)
index 0000000..3c10f85
--- /dev/null
@@ -0,0 +1,112 @@
+// run-rustfix
+#![allow(dead_code)]
+
+mod foo {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait<T> {}
+    trait MyTrait<T> {
+        fn use_self<K>(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
+        fn use_self<K>(&self) -> &() { panic!() }
+    }
+    impl<T> Irrelevant for dyn ObjectTrait<T> {}
+
+    fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+        val.use_self::<T>() //~ ERROR E0759
+    }
+}
+
+mod bar {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod baz {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for Box<dyn ObjectTrait + '_> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for Box<dyn ObjectTrait> {}
+
+    fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod bat {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+
+    impl dyn ObjectTrait + '_ {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod ban {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait + '_ {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0759
+    }
+}
+
+mod bal {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait + '_ {}
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        MyTrait::use_self(val) //~ ERROR E0759
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr
new file mode 100644 (file)
index 0000000..697467d
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9
+   |
+LL |     fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+   |                      --- `val` is a reference that is only valid in the function body
+LL |         val.use_self::<T>()
+   |         ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         val.use_self()
+   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         val.use_self()
+   |         ^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error[E0521]: borrowed data escapes outside of function
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                   --- `val` is a reference that is only valid in the function body
+LL |         MyTrait::use_self(val)
+   |         ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs
new file mode 100644 (file)
index 0000000..88ab03d
--- /dev/null
@@ -0,0 +1,112 @@
+// run-rustfix
+#![allow(dead_code)]
+
+mod foo {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait<T> {}
+    trait MyTrait<T> {
+        fn use_self<K>(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+        fn use_self<K>(&self) -> &() { panic!() }
+    }
+    impl<T> Irrelevant for dyn ObjectTrait<T> {}
+
+    fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+        val.use_self::<T>() //~ ERROR E0759
+    }
+}
+
+mod bar {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod baz {
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &();
+    }
+    trait Irrelevant {}
+
+    impl MyTrait for Box<dyn ObjectTrait> {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    impl Irrelevant for Box<dyn ObjectTrait> {}
+
+    fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod bat {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+
+    impl dyn ObjectTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        val.use_self() //~ ERROR E0772
+    }
+}
+
+mod ban {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+        val.use_self() //~ ERROR E0759
+    }
+}
+
+mod bal {
+    trait OtherTrait<'a> {}
+    impl<'a> OtherTrait<'a> for &'a () {}
+
+    trait ObjectTrait {}
+    trait MyTrait {
+        fn use_self(&self) -> &() { panic!() }
+    }
+    trait Irrelevant {
+        fn use_self(&self) -> &() { panic!() }
+    }
+
+    impl MyTrait for dyn ObjectTrait {}
+    impl Irrelevant for dyn ObjectTrait {}
+
+    fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+        MyTrait::use_self(val) //~ ERROR E0759
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
new file mode 100644 (file)
index 0000000..2fb6c25
--- /dev/null
@@ -0,0 +1,134 @@
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:13
+   |
+LL |     fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
+   |                           ---------------------- this data with lifetime `'a`...
+LL |         val.use_self::<T>()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32
+   |
+LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> {
+   |                                ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self<K>(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
+   |                                               ^^^^
+
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:13
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                        ------------------- this data with lifetime `'a`...
+LL |         val.use_self()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
+   |
+LL |     impl dyn ObjectTrait {
+   |              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl dyn ObjectTrait + '_ {
+   |                          ^^^^
+
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:13
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
+   |                        ------------------- this data with lifetime `'a`...
+LL |         val.use_self()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26
+   |
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL |     impl MyTrait for dyn ObjectTrait {}
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {}
+   |                                      ^^^^
+help: to declare that the `impl Trait` captures data from argument `val`, you can add an explicit `'a` lifetime bound
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                                                                    ^^^^
+
+error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:27
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
+   |                        ------------------- this data with lifetime `'a`...
+LL |         MyTrait::use_self(val)
+   |                           ^^^ ...is captured here...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
+   |
+LL |         MyTrait::use_self(val)
+   |         ^^^^^^^^^^^^^^^^^
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:104:26
+   |
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+...
+LL |     impl MyTrait for dyn ObjectTrait {}
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {}
+   |                                      ^^^^
+
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:37:13
+   |
+LL |     fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
+   |                        ------------------- this data with lifetime `'a`...
+LL |         val.use_self()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
+   |
+LL |     impl MyTrait for dyn ObjectTrait {
+   |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for dyn ObjectTrait + '_ {
+   |                                      ^^^^
+
+error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an implicit `'static` lifetime requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:54:13
+   |
+LL |     fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
+   |                        ----------------------------- this data with lifetime `'a`...
+LL |         val.use_self()
+   |             ^^^^^^^^ ...is captured and required to live as long as `'static` here
+   |
+note: the used `impl` has a `'static` requirement
+  --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait> {
+   |                              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
+LL |         fn use_self(&self) -> &() { panic!() }
+   |            -------- calling this method introduces the `impl`'s 'static` requirement
+help: consider relaxing the implicit `'static` requirement
+   |
+LL |     impl MyTrait for Box<dyn ObjectTrait + '_> {
+   |                                          ^^^^
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0759`.
index d3853445dfdfebb01518eb66ac063a0872c38fcb..94dd826a15cae71be3d0881f4bbeba350e2c2c38 100644 (file)
@@ -16,7 +16,7 @@ fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
 where
     G: Get<T>
 {
-    move || { //~ ERROR cannot infer an appropriate lifetime
+    move || { //~ ERROR `dest`
         *dest = g.get();
     }
 }
index 9ab060328537b56b08f0f3dcf6b023edfcd3fea5..d7051515f11029c04401888c11f9407e529b5a60 100644 (file)
@@ -6,7 +6,7 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `dest` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/missing-lifetimes-in-signature.rs:19:5
    |
 LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
index f78edb1c83a4c97e549713f99975b073b9b30144..d8446e58dbb63eb9e7b593d69e6ae660492a232e 100644 (file)
@@ -27,7 +27,7 @@ impl Bar {
     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -38,7 +38,7 @@ impl Baz {
     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -49,7 +49,7 @@ impl Bat {
     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
@@ -60,7 +60,7 @@ impl Ban {
     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
         Iter {
             current: None,
-            remaining: self.0.iter(), //~ ERROR cannot infer an appropriate lifetime
+            remaining: self.0.iter(), //~ ERROR E0759
         }
     }
 }
index 1257e9b172cf71ac9e4458f81fe212e6eb0d2744..9f30787f07cc6d9d9114805811f52a0b0323191a 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:30:31
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
@@ -23,7 +23,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> {
    |                                                        ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:41:31
    |
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
@@ -44,7 +44,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter(&self) -> impl Iterator<Item = Box<dyn Foo + '_>> + '_ {
    |                                                        ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:52:31
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
@@ -65,7 +65,7 @@ help: to declare that the trait object captures data from argument `self`, you c
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo + 'a>> + 'a {
    |                                                               ^^^^
 
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `self` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/trait-object-nested-in-impl-trait.rs:63:31
    |
 LL |     fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.rs
new file mode 100644 (file)
index 0000000..333dce3
--- /dev/null
@@ -0,0 +1,10 @@
+fn main() {
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+    let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+    //~^ ERROR generic parameters without surrounding angle brackets
+}
diff --git a/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr b/src/test/ui/suggestions/recover-missing-turbofish-surrounding-angle-braket.stderr
new file mode 100644 (file)
index 0000000..981f957
--- /dev/null
@@ -0,0 +1,46 @@
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:2:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:4:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:6:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: generic parameters without surrounding angle brackets
+  --> $DIR/recover-missing-turbofish-surrounding-angle-braket.rs:8:48
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::Vec<_>>();
+   |                                                ^^^^^^
+   |
+help: surround the type parameters with angle brackets
+   |
+LL |     let _ = vec![1, 2, 3].into_iter().collect::<Vec<_>>();
+   |                                                ^      ^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/traits/issue-72410.rs b/src/test/ui/traits/issue-72410.rs
new file mode 100644 (file)
index 0000000..c95f1df
--- /dev/null
@@ -0,0 +1,18 @@
+// Regression test for #72410, this should be used with debug assertion enabled.
+
+// should be fine
+pub trait Foo {
+    fn map()
+    where
+        Self: Sized,
+        for<'a> &'a mut [u8]: ;
+}
+
+// should fail
+pub trait Bar {
+    fn map()
+    where for<'a> &'a mut [dyn Bar]: ;
+    //~^ ERROR: the trait `Bar` cannot be made into an object
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-72410.stderr b/src/test/ui/traits/issue-72410.stderr
new file mode 100644 (file)
index 0000000..1db2320
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Bar` cannot be made into an object
+  --> $DIR/issue-72410.rs:14:19
+   |
+LL | pub trait Bar {
+   |           --- this trait cannot be made into an object...
+LL |     fn map()
+   |        --- ...because associated function `map` has no `self` parameter
+LL |     where for<'a> &'a mut [dyn Bar]: ;
+   |                   ^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
+   |
+help: consider turning `map` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
+   |
+LL |     where for<'a> &'a mut [dyn Bar]:, Self: Sized ;
+   |                                     ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
index 73a11a5e743f6a7f85810bfbcc0d86d54cf7fd3d..6a3f3c98f127a96d1b5e0a3c93e7d1e1f95b0018 100644 (file)
@@ -5,7 +5,6 @@
 #![feature(never_type)]
 
 use std::mem::size_of;
-use std::num::NonZeroU8;
 
 struct t {a: u8, b: i8}
 struct u {a: u8, b: i8, c: u8}
@@ -103,23 +102,6 @@ enum Option2<A, B> {
     None
 }
 
-// Two layouts are considered for `CanBeNicheFilledButShouldnt`:
-//   Niche-filling:
-//     { u32 (4 bytes), NonZeroU8 + tag in niche (1 byte), padding (3 bytes) }
-//   Tagged:
-//     { tag (1 byte), NonZeroU8 (1 byte), padding (2 bytes), u32 (4 bytes) }
-// Both are the same size (due to padding),
-// but the tagged layout is better as the tag creates a niche with 254 invalid values,
-// allowing types like `Option<Option<CanBeNicheFilledButShouldnt>>` to fit into 8 bytes.
-pub enum CanBeNicheFilledButShouldnt {
-    A(NonZeroU8, u32),
-    B
-}
-pub enum AlwaysTaggedBecauseItHasNoNiche {
-    A(u8, u32),
-    B
-}
-
 pub fn main() {
     assert_eq!(size_of::<u8>(), 1 as usize);
     assert_eq!(size_of::<u32>(), 4 as usize);
@@ -163,11 +145,4 @@ pub fn main() {
     assert_eq!(size_of::<Option<Option<(&(), bool)>>>(), size_of::<(bool, &())>());
     assert_eq!(size_of::<Option<Option2<bool, &()>>>(), size_of::<(bool, &())>());
     assert_eq!(size_of::<Option<Option2<&(), bool>>>(), size_of::<(bool, &())>());
-
-    assert_eq!(size_of::<CanBeNicheFilledButShouldnt>(), 8);
-    assert_eq!(size_of::<Option<CanBeNicheFilledButShouldnt>>(), 8);
-    assert_eq!(size_of::<Option<Option<CanBeNicheFilledButShouldnt>>>(), 8);
-    assert_eq!(size_of::<AlwaysTaggedBecauseItHasNoNiche>(), 8);
-    assert_eq!(size_of::<Option<AlwaysTaggedBecauseItHasNoNiche>>(), 8);
-    assert_eq!(size_of::<Option<Option<AlwaysTaggedBecauseItHasNoNiche>>>(), 8);
 }
index 133c5231031fd65a8d86b67159828b3b539d8362..2c8b1e76b1b82984d7a677a07d53c27b6c849f23 100644 (file)
@@ -194,6 +194,8 @@ trait Qux {
     const D: _ = 42;
     //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
     // type E: _; // FIXME: make the parser propagate the existence of `B`
+    type F: std::ops::Fn(_);
+    //~^ ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 impl Qux for Struct {
     type A = _;
index a1945f2b9cf4e88b314f5d395d555a76f3a1ced4..782ff4948cda46e9032450e063bc65acbfbd44e8 100644 (file)
@@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T);
    |                   ^ expected identifier, found reserved identifier
 
 error: associated constant in `impl` without body
-  --> $DIR/typeck_type_placeholder_item.rs:203:5
+  --> $DIR/typeck_type_placeholder_item.rs:205:5
    |
 LL |     const C: _;
    |     ^^^^^^^^^^-
@@ -545,6 +545,12 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace `_` with the correct type: `i32`
 
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+  --> $DIR/typeck_type_placeholder_item.rs:197:26
+   |
+LL |     type F: std::ops::Fn(_);
+   |                          ^ not allowed in type signatures
+
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:40:24
    |
@@ -582,25 +588,25 @@ LL |         fn clone(&self) -> _ { FnTest9 }
    |                            help: replace with the correct return type: `main::FnTest9`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:199:14
+  --> $DIR/typeck_type_placeholder_item.rs:201:14
    |
 LL |     type A = _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:201:14
+  --> $DIR/typeck_type_placeholder_item.rs:203:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:203:14
+  --> $DIR/typeck_type_placeholder_item.rs:205:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
-  --> $DIR/typeck_type_placeholder_item.rs:206:14
+  --> $DIR/typeck_type_placeholder_item.rs:208:14
    |
 LL |     const D: _ = 42;
    |              ^
@@ -608,7 +614,7 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace `_` with the correct type: `i32`
 
-error: aborting due to 66 previous errors
+error: aborting due to 67 previous errors
 
 Some errors have detailed explanations: E0121, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.
index d5aa18eb0f4e75f0e4c5969418ac03703d7f8fa4..e951adf030f5c2e9e958b2b45b31839832ec43e1 100644 (file)
@@ -5,7 +5,7 @@
 
 fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
-    Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
+    Box::new(items.iter()) //~ ERROR E0759
 }
 
 fn b<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
index dda5de431d30944e4e0f9a1f4f6c5c221773c609..dd804864dab4f59e0eb96f063b2223e50aa21978 100644 (file)
@@ -1,4 +1,4 @@
-error[E0759]: cannot infer an appropriate lifetime
+error[E0759]: `items` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
   --> $DIR/dyn-trait-underscore.rs:8:20
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
index 4514208a90dc9a5cfe0955dc0c94fc73193c1485..071547c945edc1e36e1896ce885f05f995989e6f 100644 (file)
@@ -1,11 +1,11 @@
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized-trait-impl-self-type.rs:10:17
+  --> $DIR/unsized-trait-impl-self-type.rs:10:27
    |
 LL | struct S5<Y>(Y);
    |           - required by this bound in `S5`
 LL | 
 LL | impl<X: ?Sized> T3<X> for S5<X> {
-   |      -          ^^^^^ doesn't have a size known at compile-time
+   |      -                    ^^^^^ doesn't have a size known at compile-time
    |      |
    |      this type parameter needs to be `std::marker::Sized`
    |
diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.rs b/src/test/ui/wf/wf-foreign-fn-decl-ret.rs
new file mode 100644 (file)
index 0000000..b9d956c
--- /dev/null
@@ -0,0 +1,18 @@
+pub trait Unsatisfied {}
+
+#[repr(transparent)]
+pub struct Bar<T: Unsatisfied>(T);
+
+pub trait Foo {
+    type Assoc;
+}
+
+extern "C" {
+    pub fn lint_me() -> <() as Foo>::Assoc;
+    //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277]
+
+    pub fn lint_me_aswell() -> Bar<u32>;
+    //~^ ERROR: the trait bound `u32: Unsatisfied` is not satisfied [E0277]
+}
+
+fn main() {}
diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
new file mode 100644 (file)
index 0000000..9081b79
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `(): Foo` is not satisfied
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
+   |
+LL |     pub fn lint_me() -> <() as Foo>::Assoc;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+
+error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
+  --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
+   |
+LL | pub struct Bar<T: Unsatisfied>(T);
+   |                   ----------- required by this bound in `Bar`
+...
+LL |     pub fn lint_me_aswell() -> Bar<u32>;
+   |                                ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/wf/wf-impl-self-type.rs b/src/test/ui/wf/wf-impl-self-type.rs
new file mode 100644 (file)
index 0000000..2dd9b4e
--- /dev/null
@@ -0,0 +1,7 @@
+// Tests that we point at the proper location for an error
+// involving the self-type of an impl
+
+trait Foo {}
+impl Foo for Option<[u8]> {} //~ ERROR the size for
+
+fn main() {}
diff --git a/src/test/ui/wf/wf-impl-self-type.stderr b/src/test/ui/wf/wf-impl-self-type.stderr
new file mode 100644 (file)
index 0000000..a3a5311
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-impl-self-type.rs:5:14
+   |
+LL | impl Foo for Option<[u8]> {}
+   |              ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   | 
+  ::: $SRC_DIR/libcore/option.rs:LL:COL
+   |
+LL | pub enum Option<T> {
+   |                 - required by this bound in `std::option::Option`
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `[u8]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 43cf77395cad5b79887b20b7cf19d418bbd703a9..aa6872140ab0fa10f641ab0b981d5330d419e927 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 43cf77395cad5b79887b20b7cf19d418bbd703a9
+Subproject commit aa6872140ab0fa10f641ab0b981d5330d419e927
index 3f425e5b7258d52580b162ba1b6aecac643d8191..e85e8874ba60039e3ba12819d198603bb95211b4 100644 (file)
@@ -19,7 +19,7 @@ fi
 
 if [[ $BETA = "true" ]]; then
   echo "Update documentation for the beta release"
-  cp -r out/master out/beta
+  cp -r out/master/* out/beta
 fi
 
 # Generate version index that is shown as root index page
@@ -33,12 +33,13 @@ cd out
 git config user.name "GHA CI"
 git config user.email "gha@ci.invalid"
 
-if git diff --exit-code --quiet; then
-  echo "No changes to the output on this push; exiting."
-  exit 0
-fi
-
 if [[ -n $TAG_NAME ]]; then
+  # track files, so that the following check works
+  git add --intent-to-add "$TAG_NAME"
+  if git diff --exit-code --quiet -- $TAG_NAME/; then
+    echo "No changes to the output on this push; exiting."
+    exit 0
+  fi
   # Add the new dir
   git add "$TAG_NAME"
   # Update the symlink
@@ -47,9 +48,17 @@ if [[ -n $TAG_NAME ]]; then
   git add versions.json
   git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}"
 elif [[ $BETA = "true" ]]; then
+  if git diff --exit-code --quiet -- beta/; then
+    echo "No changes to the output on this push; exiting."
+    exit 0
+  fi
   git add beta
   git commit -m "Automatic deploy to GitHub Pages (beta): ${SHA}"
 else
+  if git diff --exit-code --quiet; then
+    echo "No changes to the output on this push; exiting."
+    exit 0
+  fi
   git add .
   git commit -m "Automatic deploy to GitHub Pages: ${SHA}"
 fi
index 5d08b44ba404f9294f0b45973e017e571c208058..776b04295f949c0e46b46fd8a2186fd91604cbd1 100644 (file)
@@ -1,4 +1,4 @@
-# Change Log
+# Changelog
 
 All notable changes to this project will be documented in this file.
 See [Changelog Update](doc/changelog_update.md) if you want to update this
@@ -6,11 +6,73 @@ document.
 
 ## Unreleased / In Rust Nightly
 
-[7ea7cd1...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master)
+[c2c07fa...master](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master)
+
+## Rust 1.46
+
+Current beta, release 2020-08-27
+
+[7ea7cd1...c2c07fa](https://github.com/rust-lang/rust-clippy/compare/7ea7cd1...master)
+
+### New lints
+
+* [`unnested_or_patterns`] [#5378](https://github.com/rust-lang/rust-clippy/pull/5378)
+* [`iter_next_slice`] [#5597](https://github.com/rust-lang/rust-clippy/pull/5597)
+* [`unnecessary_sort_by`] [#5623](https://github.com/rust-lang/rust-clippy/pull/5623)
+* [`vec_resize_to_zero`] [#5637](https://github.com/rust-lang/rust-clippy/pull/5637)
+
+### Moves and Deprecations
+
+* Move [`cast_ptr_alignment`] to pedantic [#5667](https://github.com/rust-lang/rust-clippy/pull/5667)
+
+### Enhancements
+
+* Improve [`mem_replace_with_uninit`] lint [#5695](https://github.com/rust-lang/rust-clippy/pull/5695)
+
+### False Positive Fixes
+
+* [`len_zero`]: Avoid linting ranges when the `range_is_empty` feature is not enabled
+  [#5656](https://github.com/rust-lang/rust-clippy/pull/5656)
+* [`let_and_return`]: Don't lint if a temporary borrow is involved
+  [#5680](https://github.com/rust-lang/rust-clippy/pull/5680)
+* [`reversed_empty_ranges`]: Avoid linting `N..N` in for loop arguments in
+  [#5692](https://github.com/rust-lang/rust-clippy/pull/5692)
+* [`if_same_then_else`]: Don't assume multiplication is always commutative
+  [#5702](https://github.com/rust-lang/rust-clippy/pull/5702)
+* [`blacklisted_name`]: Remove `bar` from the default configuration
+  [#5712](https://github.com/rust-lang/rust-clippy/pull/5712)
+* [`redundant_pattern_matching`]: Avoid suggesting non-`const fn` calls in const contexts
+  [#5724](https://github.com/rust-lang/rust-clippy/pull/5724)
+
+### Suggestion Fixes/Improvements
+
+* Fix suggestion of [`unit_arg`] lint, so that it suggest semantic equivalent code
+  [#4455](https://github.com/rust-lang/rust-clippy/pull/4455)
+* Add auto applicable suggestion to [`macro_use_imports`]
+  [#5279](https://github.com/rust-lang/rust-clippy/pull/5279)
+
+### ICE Fixes
+
+* Fix ICE in the `consts` module of Clippy [#5709](https://github.com/rust-lang/rust-clippy/pull/5709)
+
+### Documentation Improvements
+
+* Improve code examples across multiple lints [#5664](https://github.com/rust-lang/rust-clippy/pull/5664)
+
+### Others
+
+* Introduce a `--rustc` flag to `clippy-driver`, which turns `clippy-driver`
+  into `rustc` and passes all the given arguments to `rustc`. This is especially
+  useful for tools that need the `rustc` version Clippy was compiled with,
+  instead of the Clippy version. E.g. `clippy-driver --rustc --version` will
+  print the output of `rustc --version`.
+  [#5178](https://github.com/rust-lang/rust-clippy/pull/5178)
+* New issue templates now make it easier to complain if Clippy is too annoying
+  or not annoying enough! [#5735](https://github.com/rust-lang/rust-clippy/pull/5735)
 
 ## Rust 1.45
 
-Current beta, release 2020-07-16
+Current stable, released 2020-07-16
 
 [891e1a8...7ea7cd1](https://github.com/rust-lang/rust-clippy/compare/891e1a8...7ea7cd1)
 
@@ -87,7 +149,7 @@ and [`similar_names`]. [#5651](https://github.com/rust-lang/rust-clippy/pull/565
 
 ## Rust 1.44
 
-Current stable, released 2020-06-04
+Released 2020-06-04
 
 [204bb9b...891e1a8](https://github.com/rust-lang/rust-clippy/compare/204bb9b...891e1a8)
 
@@ -1679,6 +1741,7 @@ Released 2018-09-13
 [`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init
 [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
 [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
+[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints
 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
index 222b81023a7705aa87847ea6fd913d50a380036c..a2984d73641694b500415990e41c25b9b57fbeda 100644 (file)
@@ -42,10 +42,8 @@ Table of contents:
 
 ## Usage
 
-Since this is a tool for helping the developer of a library or application
-write better code, it is recommended not to include Clippy as a hard dependency.
-Options include using it as an optional dependency, as a cargo subcommand, or
-as an included feature during build. These options are detailed below.
+Below are instructions on how to use Clippy as a subcommand, compiled from source
+or in Travis CI.
 
 ### As a cargo subcommand (`cargo clippy`)
 
index 818d8188a787a6608f3071810b539010fea3ffcb..c17a0e8333058fe91497dc9d67f3c0434481fe38 100644 (file)
@@ -153,7 +153,7 @@ macro_rules! declare_deprecated_lint {
     ///
     /// **Deprecation reason:** Associated-constants are now preferred.
     pub REPLACE_CONSTS,
-    "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants"
+    "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants"
 }
 
 declare_deprecated_lint! {
index 102cf597d22e368ee04d86b01ffd5a57de24cbd0..b5fb51af1c7f31f6192ac279d107f274cf5156bc 100644 (file)
@@ -10,7 +10,7 @@
 declare_clippy_lint! {
     /// **What it does:** Checks for explicit `deref()` or `deref_mut()` method calls.
     ///
-    /// **Why is this bad?** Derefencing by `&*x` or `&mut *x` is clearer and more concise,
+    /// **Why is this bad?** Dereferencing by `&*x` or `&mut *x` is clearer and more concise,
     /// when not part of a method chain.
     ///
     /// **Example:**
index bd7ca03883945023458fc4ed6328e3ad14bc6d31..9fb10c7f62768583ec311d0748f68796cf0a5b32 100644 (file)
@@ -55,7 +55,7 @@ fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) {
             ..
         } = item.kind
         {
-            // Remember for each inherent implementation encoutered its span and generics
+            // Remember for each inherent implementation encountered its span and generics
             // but filter out implementations that have generic params (type or lifetime)
             // or are derived from a macro
             if !in_macro(item.span) && generics.params.is_empty() {
index 32e79317f82254119bf9b3075ef15f3b827f3ea7..f371942dbeec57056ca35176bbda2f005d9d8084 100644 (file)
@@ -276,6 +276,7 @@ macro_rules! declare_clippy_lint {
 mod question_mark;
 mod ranges;
 mod redundant_clone;
+mod redundant_closure_call;
 mod redundant_field_names;
 mod redundant_pub_crate;
 mod redundant_static_lifetimes;
@@ -300,6 +301,7 @@ macro_rules! declare_clippy_lint {
 mod try_err;
 mod types;
 mod unicode;
+mod unit_return_expecting_ord;
 mod unnamed_address;
 mod unnecessary_sort_by;
 mod unnested_or_patterns;
@@ -462,7 +464,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     );
     store.register_removed(
         "clippy::replace_consts",
-        "associated-constants `MIN`/`MAX` of integers are prefered to `{min,max}_value()` and module constants",
+        "associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants",
     );
     store.register_removed(
         "clippy::regex_macro",
@@ -701,7 +703,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &misc_early::DOUBLE_NEG,
         &misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
         &misc_early::MIXED_CASE_HEX_LITERALS,
-        &misc_early::REDUNDANT_CLOSURE_CALL,
         &misc_early::REDUNDANT_PATTERN,
         &misc_early::UNNEEDED_FIELD_PATTERN,
         &misc_early::UNNEEDED_WILDCARD_PATTERN,
@@ -758,6 +759,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &ranges::RANGE_ZIP_WITH_LEN,
         &ranges::REVERSED_EMPTY_RANGES,
         &redundant_clone::REDUNDANT_CLONE,
+        &redundant_closure_call::REDUNDANT_CLOSURE_CALL,
         &redundant_field_names::REDUNDANT_FIELD_NAMES,
         &redundant_pub_crate::REDUNDANT_PUB_CRATE,
         &redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES,
@@ -826,6 +828,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &unicode::NON_ASCII_LITERAL,
         &unicode::UNICODE_NOT_NFC,
         &unicode::ZERO_WIDTH_SPACE,
+        &unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
         &unnamed_address::FN_ADDRESS_COMPARISONS,
         &unnamed_address::VTABLE_ADDRESS_COMPARISONS,
         &unnecessary_sort_by::UNNECESSARY_SORT_BY,
@@ -891,6 +894,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box attrs::Attributes);
     store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
     store.register_late_pass(|| box unicode::Unicode);
+    store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
     store.register_late_pass(|| box strings::StringAdd);
     store.register_late_pass(|| box implicit_return::ImplicitReturn);
     store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
@@ -1015,6 +1019,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| box int_plus_one::IntPlusOne);
     store.register_early_pass(|| box formatting::Formatting);
     store.register_early_pass(|| box misc_early::MiscEarlyLints);
+    store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall);
+    store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall);
     store.register_early_pass(|| box returns::Return);
     store.register_late_pass(|| box let_and_return::LetReturn);
     store.register_early_pass(|| box collapsible_if::CollapsibleIf);
@@ -1356,7 +1362,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&misc_early::DOUBLE_NEG),
         LintId::of(&misc_early::DUPLICATE_UNDERSCORE_ARGUMENT),
         LintId::of(&misc_early::MIXED_CASE_HEX_LITERALS),
-        LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL),
         LintId::of(&misc_early::REDUNDANT_PATTERN),
         LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
         LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
@@ -1390,6 +1395,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
         LintId::of(&ranges::REVERSED_EMPTY_RANGES),
         LintId::of(&redundant_clone::REDUNDANT_CLONE),
+        LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL),
         LintId::of(&redundant_field_names::REDUNDANT_FIELD_NAMES),
         LintId::of(&redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES),
         LintId::of(&reference::DEREF_ADDROF),
@@ -1436,6 +1442,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&types::UNNECESSARY_CAST),
         LintId::of(&types::VEC_BOX),
         LintId::of(&unicode::ZERO_WIDTH_SPACE),
+        LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
         LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
         LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
         LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
@@ -1589,7 +1596,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&methods::UNNECESSARY_FILTER_MAP),
         LintId::of(&methods::USELESS_ASREF),
         LintId::of(&misc::SHORT_CIRCUIT_STATEMENT),
-        LintId::of(&misc_early::REDUNDANT_CLOSURE_CALL),
         LintId::of(&misc_early::UNNEEDED_WILDCARD_PATTERN),
         LintId::of(&misc_early::ZERO_PREFIXED_LITERAL),
         LintId::of(&needless_bool::BOOL_COMPARISON),
@@ -1604,6 +1610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&precedence::PRECEDENCE),
         LintId::of(&ptr_offset_with_cast::PTR_OFFSET_WITH_CAST),
         LintId::of(&ranges::RANGE_ZIP_WITH_LEN),
+        LintId::of(&redundant_closure_call::REDUNDANT_CLOSURE_CALL),
         LintId::of(&reference::DEREF_ADDROF),
         LintId::of(&reference::REF_IN_DEREF),
         LintId::of(&repeat_once::REPEAT_ONCE),
@@ -1692,6 +1699,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&types::CAST_REF_TO_MUT),
         LintId::of(&types::UNIT_CMP),
         LintId::of(&unicode::ZERO_WIDTH_SPACE),
+        LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
         LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
         LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
         LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
index ea6fb9e902576ee17d43ffd250a6b5277fd4fbfe..be879dfe28d7038999be8b2be4f0314eb0457d02 100644 (file)
@@ -1512,6 +1512,10 @@ fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Opt
             }
         }
 
+        let result_expr = match &op.kind {
+            ExprKind::AddrOf(_, _, borrowed) => borrowed,
+            _ => op,
+        };
         span_lint_and_then(
             cx,
             REDUNDANT_PATTERN_MATCHING,
@@ -1524,7 +1528,7 @@ fn find_suggestion(cx: &LateContext<'_>, hir_id: HirId, path: &QPath<'_>) -> Opt
 
                 // while let ... = ... { ... }
                 //                 ^^^
-                let op_span = op.span.source_callsite();
+                let op_span = result_expr.span.source_callsite();
 
                 // while let ... = ... { ... }
                 // ^^^^^^^^^^^^^^^^^^^
@@ -1589,17 +1593,21 @@ fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &
             };
 
             if let Some(good_method) = found_good_method {
+                let span = expr.span.to(op.span);
+                let result_expr = match &op.kind {
+                    ExprKind::AddrOf(_, _, borrowed) => borrowed,
+                    _ => op,
+                };
                 span_lint_and_then(
                     cx,
                     REDUNDANT_PATTERN_MATCHING,
                     expr.span,
                     &format!("redundant pattern matching, consider using `{}`", good_method),
                     |diag| {
-                        let span = expr.span.to(op.span);
                         diag.span_suggestion(
                             span,
                             "try this",
-                            format!("{}.{}", snippet(cx, op.span, "_"), good_method),
+                            format!("{}.{}", snippet(cx, result_expr.span, "_"), good_method),
                             Applicability::MaybeIncorrect, // snippet
                         );
                     },
index 4877556a49e37daaf59173ede295f148af2d4895..97cc58023f55e61d62d01d4685e139d909e55c28 100644 (file)
@@ -2354,8 +2354,8 @@ fn lint_iter_nth_zero<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, nth_ar
                 cx,
                 ITER_NTH_ZERO,
                 expr.span,
-                "called `.nth(0)` on a `std::iter::Iterator`",
-                "try calling",
+                "called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent",
+                "try calling `.next()` instead of `.nth(0)`",
                 format!("{}.next()", snippet_with_applicability(cx, nth_args[0].span, "..", &mut applicability)),
                 applicability,
             );
@@ -3290,7 +3290,12 @@ fn lint_option_as_ref_deref<'tcx>(
                         if let hir::ExprKind::Path(qpath) = &args[0].kind;
                         if let hir::def::Res::Local(local_id) = cx.qpath_res(qpath, args[0].hir_id);
                         if closure_body.params[0].pat.hir_id == local_id;
-                        let adj = cx.typeck_results().expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>();
+                        let adj = cx
+                            .typeck_results()
+                            .expr_adjustments(&args[0])
+                            .iter()
+                            .map(|x| &x.kind)
+                            .collect::<Box<[_]>>();
                         if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
                         then {
                             let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
index fc10e5077b8391c429a958d91fed858aab8f88f2..26a1c32b6b3ac229f43aa7e4dff4604a96fd361e 100644 (file)
@@ -99,7 +99,9 @@
     /// if y != x {} // where both are floats
     ///
     /// // Good
-    /// let error = 0.01f64; // Use an epsilon for comparison
+    /// let error = f64::EPSILON; // Use an epsilon for comparison
+    /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
+    /// // let error = std::f64::EPSILON;
     /// if (y - 1.23f64).abs() < error { }
     /// if (y - x).abs() > error { }
     /// ```
     /// const ONE: f64 = 1.00;
     ///
     /// // Bad
-    /// if x == ONE { }  // where both are floats
+    /// if x == ONE { } // where both are floats
     ///
     /// // Good
-    /// let error = 0.1f64; // Use an epsilon for comparison
+    /// let error = f64::EPSILON; // Use an epsilon for comparison
+    /// // Or, if Rust <= 1.42, use `std::f64::EPSILON` constant instead.
+    /// // let error = std::f64::EPSILON;
     /// if (x - ONE).abs() < error { }
     /// ```
     pub FLOAT_CMP_CONST,
index b84a1a3fe249449a81a574ea2be25118976bbd7e..29aba7c121873bbd6c57aa3d24d2758942040ba3 100644 (file)
@@ -1,13 +1,9 @@
-use crate::utils::{
-    constants, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help, span_lint_and_sugg,
-    span_lint_and_then,
-};
-use if_chain::if_chain;
+use crate::utils::{constants, snippet_opt, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use rustc_ast::ast::{
-    BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
-    NodeId, Pat, PatKind, StmtKind, UnOp,
+    BindingMode, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability,
+    NodeId, Pat, PatKind, UnOp,
 };
-use rustc_ast::visit::{walk_expr, FnKind, Visitor};
+use rustc_ast::visit::FnKind;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
     "function arguments having names which only differ by an underscore"
 }
 
-declare_clippy_lint! {
-    /// **What it does:** Detects closures called in the same expression where they
-    /// are defined.
-    ///
-    /// **Why is this bad?** It is unnecessarily adding to the expression's
-    /// complexity.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust,ignore
-    /// // Bad
-    /// let a = (|| 42)()
-    ///
-    /// // Good
-    /// let a = 42
-    /// ```
-    pub REDUNDANT_CLOSURE_CALL,
-    complexity,
-    "throwaway closures called in the expression they are defined"
-}
-
 declare_clippy_lint! {
     /// **What it does:** Detects expressions of the form `--x`.
     ///
 declare_lint_pass!(MiscEarlyLints => [
     UNNEEDED_FIELD_PATTERN,
     DUPLICATE_UNDERSCORE_ARGUMENT,
-    REDUNDANT_CLOSURE_CALL,
     DOUBLE_NEG,
     MIXED_CASE_HEX_LITERALS,
     UNSEPARATED_LITERAL_SUFFIX,
     UNNEEDED_WILDCARD_PATTERN,
 ]);
 
-// Used to find `return` statements or equivalents e.g., `?`
-struct ReturnVisitor {
-    found_return: bool,
-}
-
-impl ReturnVisitor {
-    #[must_use]
-    fn new() -> Self {
-        Self { found_return: false }
-    }
-}
-
-impl<'ast> Visitor<'ast> for ReturnVisitor {
-    fn visit_expr(&mut self, ex: &'ast Expr) {
-        if let ExprKind::Ret(_) = ex.kind {
-            self.found_return = true;
-        } else if let ExprKind::Try(_) = ex.kind {
-            self.found_return = true;
-        }
-
-        walk_expr(self, ex)
-    }
-}
-
 impl EarlyLintPass for MiscEarlyLints {
     fn check_generics(&mut self, cx: &EarlyContext<'_>, gen: &Generics) {
         for param in &gen.params {
@@ -453,30 +402,6 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
             return;
         }
         match expr.kind {
-            ExprKind::Call(ref paren, _) => {
-                if let ExprKind::Paren(ref closure) = paren.kind {
-                    if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind {
-                        let mut visitor = ReturnVisitor::new();
-                        visitor.visit_expr(block);
-                        if !visitor.found_return {
-                            span_lint_and_then(
-                                cx,
-                                REDUNDANT_CLOSURE_CALL,
-                                expr.span,
-                                "Try not to call a closure in the expression where it is declared.",
-                                |diag| {
-                                    if decl.inputs.is_empty() {
-                                        let mut app = Applicability::MachineApplicable;
-                                        let hint =
-                                            snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
-                                        diag.span_suggestion(expr.span, "Try doing something like: ", hint, app);
-                                    }
-                                },
-                            );
-                        }
-                    }
-                }
-            },
             ExprKind::Unary(UnOp::Neg, ref inner) => {
                 if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
                     span_lint(
@@ -491,31 +416,6 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
             _ => (),
         }
     }
-
-    fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) {
-        for w in block.stmts.windows(2) {
-            if_chain! {
-                if let StmtKind::Local(ref local) = w[0].kind;
-                if let Option::Some(ref t) = local.init;
-                if let ExprKind::Closure(..) = t.kind;
-                if let PatKind::Ident(_, ident, _) = local.pat.kind;
-                if let StmtKind::Semi(ref second) = w[1].kind;
-                if let ExprKind::Assign(_, ref call, _) = second.kind;
-                if let ExprKind::Call(ref closure, _) = call.kind;
-                if let ExprKind::Path(_, ref path) = closure.kind;
-                then {
-                    if ident == path.segments[0].ident {
-                        span_lint(
-                            cx,
-                            REDUNDANT_CLOSURE_CALL,
-                            second.span,
-                            "Closure called just once immediately after it was declared",
-                        );
-                    }
-                }
-            }
-        }
-    }
 }
 
 impl MiscEarlyLints {
index bdce1bf15218041506f7f1b2a5301c012109e994..1ad184dfc460b8358069739807854485096311b1 100644 (file)
@@ -131,7 +131,7 @@ fn check_fn(
 /// Returns true if any of the method parameters is a type that implements `Drop`. The method
 /// can't be made const then, because `drop` can't be const-evaluated.
 fn method_accepts_dropable(cx: &LateContext<'_>, param_tys: &[hir::Ty<'_>]) -> bool {
-    // If any of the params are dropable, return true
+    // If any of the params are droppable, return true
     param_tys.iter().any(|hir_ty| {
         let ty_ty = hir_ty_to_ty(cx.tcx, hir_ty);
         has_drop(cx, ty_ty)
index 5d4436bd206d2b48d61edcbbee93b20cd02b26bf..b1d788b5c683f4587cebc071623e2326e001160a 100644 (file)
@@ -8,7 +8,7 @@
 use std::fmt::Display;
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for modulo arithemtic.
+    /// **What it does:** Checks for modulo arithmetic.
     ///
     /// **Why is this bad?** The results of modulo (%) operation might differ
     /// depending on the language, when negative numbers are involved.
index 1d4772bb3d606a41a5dd4af3d1b9d9d8dd332ee1..48ab98418e4fafe62381a541d80296af1fb9b8bc 100644 (file)
@@ -218,12 +218,16 @@ fn check_ident(&mut self, ident: Ident) {
             let mut split_at = None;
             match existing_name.len.cmp(&count) {
                 Ordering::Greater => {
-                    if existing_name.len - count != 1 || levenstein_not_1(&interned_name, &existing_name.interned.as_str()) {
+                    if existing_name.len - count != 1
+                        || levenstein_not_1(&interned_name, &existing_name.interned.as_str())
+                    {
                         continue;
                     }
                 },
                 Ordering::Less => {
-                    if count - existing_name.len != 1 || levenstein_not_1(&existing_name.interned.as_str(), &interned_name) {
+                    if count - existing_name.len != 1
+                        || levenstein_not_1(&existing_name.interned.as_str(), &interned_name)
+                    {
                         continue;
                     }
                 },
index 065f863b8654e0dddac2cf299614c803b59f411a..9494efe736cce2a37f7efafdf211b62a6e075214 100644 (file)
@@ -79,7 +79,7 @@ fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
     }
 }
 
-/// A struct containing information about occurences of the
+/// A struct containing information about occurrences of the
 /// `if let Some(..) = .. else` construct that this lint detects.
 struct OptionIfLetElseOccurence {
     option: String,
index 10f4694640eed99907d31aedd6ee0beaed624aa7..6379dffd22e372ac8305f8fce41fe8a50ad2e555 100644 (file)
@@ -96,23 +96,20 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             if let ExprKind::Block(ref block, _) = expr.kind;
             if let Some(ref ex) = block.expr;
-            if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC);
-            if params.len() == 1;
+            if let Some(params) = match_function_call(cx, ex, &paths::BEGIN_PANIC)
+                .or_else(|| match_function_call(cx, ex, &paths::BEGIN_PANIC_FMT));
             then {
+                let span = get_outer_span(expr);
                 if is_expn_of(expr.span, "unimplemented").is_some() {
-                    let span = get_outer_span(expr);
                     span_lint(cx, UNIMPLEMENTED, span,
                               "`unimplemented` should not be present in production code");
                 } else if is_expn_of(expr.span, "todo").is_some() {
-                    let span = get_outer_span(expr);
                     span_lint(cx, TODO, span,
                               "`todo` should not be present in production code");
                 } else if is_expn_of(expr.span, "unreachable").is_some() {
-                    let span = get_outer_span(expr);
                     span_lint(cx, UNREACHABLE, span,
                               "`unreachable` should not be present in production code");
                 } else if is_expn_of(expr.span, "panic").is_some() {
-                    let span = get_outer_span(expr);
                     span_lint(cx, PANIC, span,
                               "`panic` should not be present in production code");
                     match_panic(params, expr, cx);
index fda7480194dce274089f7c765b78eb2e88e0ecac..7932be0d4b1f260a59b3d839002d3747bb1a9ad1 100644 (file)
@@ -124,6 +124,12 @@ fn check_fn(
                 continue;
             }
 
+            if let ty::Adt(ref def, _) = arg_ty.kind {
+                if match_def_path(cx, def.did, &paths::MEM_MANUALLY_DROP) {
+                    continue;
+                }
+            }
+
             // `{ cloned = &arg; clone(move cloned); }` or `{ cloned = &arg; to_path_buf(cloned); }`
             let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(cx, mir, arg, from_borrow, bb));
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
new file mode 100644 (file)
index 0000000..8aa478e
--- /dev/null
@@ -0,0 +1,151 @@
+use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then};
+use if_chain::if_chain;
+use rustc_ast::ast;
+use rustc_ast::visit as ast_visit;
+use rustc_ast::visit::Visitor as AstVisitor;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::intravisit as hir_visit;
+use rustc_hir::intravisit::Visitor as HirVisitor;
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::map::Map;
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Detects closures called in the same expression where they
+    /// are defined.
+    ///
+    /// **Why is this bad?** It is unnecessarily adding to the expression's
+    /// complexity.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust,ignore
+    /// // Bad
+    /// let a = (|| 42)()
+    ///
+    /// // Good
+    /// let a = 42
+    /// ```
+    pub REDUNDANT_CLOSURE_CALL,
+    complexity,
+    "throwaway closures called in the expression they are defined"
+}
+
+declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]);
+
+// Used to find `return` statements or equivalents e.g., `?`
+struct ReturnVisitor {
+    found_return: bool,
+}
+
+impl ReturnVisitor {
+    #[must_use]
+    fn new() -> Self {
+        Self { found_return: false }
+    }
+}
+
+impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
+    fn visit_expr(&mut self, ex: &'ast ast::Expr) {
+        if let ast::ExprKind::Ret(_) = ex.kind {
+            self.found_return = true;
+        } else if let ast::ExprKind::Try(_) = ex.kind {
+            self.found_return = true;
+        }
+
+        ast_visit::walk_expr(self, ex)
+    }
+}
+
+impl EarlyLintPass for RedundantClosureCall {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+        if in_external_macro(cx.sess(), expr.span) {
+            return;
+        }
+        if_chain! {
+            if let ast::ExprKind::Call(ref paren, _) = expr.kind;
+            if let ast::ExprKind::Paren(ref closure) = paren.kind;
+            if let ast::ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind;
+            then {
+                let mut visitor = ReturnVisitor::new();
+                visitor.visit_expr(block);
+                if !visitor.found_return {
+                    span_lint_and_then(
+                        cx,
+                        REDUNDANT_CLOSURE_CALL,
+                        expr.span,
+                        "try not to call a closure in the expression where it is declared.",
+                        |diag| {
+                            if decl.inputs.is_empty() {
+                                let mut app = Applicability::MachineApplicable;
+                                let hint =
+                                    snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
+                                diag.span_suggestion(expr.span, "try doing something like", hint, app);
+                            }
+                        },
+                    );
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+        fn count_closure_usage<'tcx>(block: &'tcx hir::Block<'_>, path: &'tcx hir::Path<'tcx>) -> usize {
+            struct ClosureUsageCount<'tcx> {
+                path: &'tcx hir::Path<'tcx>,
+                count: usize,
+            };
+            impl<'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'tcx> {
+                type Map = Map<'tcx>;
+
+                fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+                    if_chain! {
+                        if let hir::ExprKind::Call(ref closure, _) = expr.kind;
+                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
+                        if self.path.segments[0].ident == path.segments[0].ident
+                            && self.path.res == path.res;
+                        then {
+                            self.count += 1;
+                        }
+                    }
+                    hir_visit::walk_expr(self, expr);
+                }
+
+                fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
+                    hir_visit::NestedVisitorMap::None
+                }
+            };
+            let mut closure_usage_count = ClosureUsageCount { path, count: 0 };
+            closure_usage_count.visit_block(block);
+            closure_usage_count.count
+        }
+
+        for w in block.stmts.windows(2) {
+            if_chain! {
+                if let hir::StmtKind::Local(ref local) = w[0].kind;
+                if let Option::Some(ref t) = local.init;
+                if let hir::ExprKind::Closure(..) = t.kind;
+                if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
+                if let hir::StmtKind::Semi(ref second) = w[1].kind;
+                if let hir::ExprKind::Assign(_, ref call, _) = second.kind;
+                if let hir::ExprKind::Call(ref closure, _) = call.kind;
+                if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
+                if ident == path.segments[0].ident;
+                if count_closure_usage(block, path) == 1;
+                then {
+                    span_lint(
+                        cx,
+                        REDUNDANT_CLOSURE_CALL,
+                        second.span,
+                        "closure called just once immediately after it was declared",
+                    );
+                }
+            }
+        }
+    }
+}
index 901c0a65d7fef93b06cd208427787235ee4bc76c..6f03e92bde36fcb64a353e23ab731379f14c2ca7 100644 (file)
@@ -295,11 +295,7 @@ fn lint_shadow<'tcx>(
                 cx,
                 SHADOW_UNRELATED,
                 pattern_span,
-                &format!(
-                    "`{}` is shadowed by `{}`",
-                    snippet(cx, pattern_span, "_"),
-                    snippet(cx, expr.span, "..")
-                ),
+                &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
                 |diag| {
                     diag.span_note(expr.span, "initialization happens here");
                     diag.span_note(prev_span, "previous binding is here");
diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
new file mode 100644 (file)
index 0000000..ac6f3d1
--- /dev/null
@@ -0,0 +1,177 @@
+use crate::utils::{get_trait_def_id, paths, span_lint, span_lint_and_help};
+use if_chain::if_chain;
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Expr, ExprKind, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{BytePos, Span};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for functions that expect closures of type
+    /// Fn(...) -> Ord where the implemented closure returns the unit type.
+    /// The lint also suggests to remove the semi-colon at the end of the statement if present.
+    ///
+    /// **Why is this bad?** Likely, returning the unit type is unintentional, and
+    /// could simply be caused by an extra semi-colon. Since () implements Ord
+    /// it doesn't cause a compilation error.
+    /// This is the same reasoning behind the unit_cmp lint.
+    ///
+    /// **Known problems:** If returning unit is intentional, then there is no
+    /// way of specifying this without triggering needless_return lint
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// let mut twins = vec!((1,1), (2,2));
+    /// twins.sort_by_key(|x| { x.1; });
+    /// ```
+    pub UNIT_RETURN_EXPECTING_ORD,
+    correctness,
+    "fn arguments of type Fn(...) -> Ord returning the unit type ()."
+}
+
+declare_lint_pass!(UnitReturnExpectingOrd => [UNIT_RETURN_EXPECTING_ORD]);
+
+fn get_trait_predicates_for_trait_id<'tcx>(
+    cx: &LateContext<'tcx>,
+    generics: GenericPredicates<'tcx>,
+    trait_id: Option<DefId>,
+) -> Vec<TraitPredicate<'tcx>> {
+    let mut preds = Vec::new();
+    for (pred, _) in generics.predicates {
+        if_chain! {
+            if let PredicateKind::Trait(poly_trait_pred, _) = pred.kind();
+            let trait_pred = cx.tcx.erase_late_bound_regions(&poly_trait_pred);
+            if let Some(trait_def_id) = trait_id;
+            if trait_def_id == trait_pred.trait_ref.def_id;
+            then {
+                preds.push(trait_pred);
+            }
+        }
+    }
+    preds
+}
+
+fn get_projection_pred<'tcx>(
+    cx: &LateContext<'tcx>,
+    generics: GenericPredicates<'tcx>,
+    pred: TraitPredicate<'tcx>,
+) -> Option<ProjectionPredicate<'tcx>> {
+    generics.predicates.iter().find_map(|(proj_pred, _)| {
+        if let PredicateKind::Projection(proj_pred) = proj_pred.kind() {
+            let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred);
+            if projection_pred.projection_ty.substs == pred.trait_ref.substs {
+                return Some(projection_pred);
+            }
+        }
+        None
+    })
+}
+
+fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Vec<(usize, String)> {
+    let mut args_to_check = Vec::new();
+    if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
+        let fn_sig = cx.tcx.fn_sig(def_id);
+        let generics = cx.tcx.predicates_of(def_id);
+        let fn_mut_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().fn_mut_trait());
+        let ord_preds = get_trait_predicates_for_trait_id(cx, generics, get_trait_def_id(cx, &paths::ORD));
+        let partial_ord_preds =
+            get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait());
+        // Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error
+        // The trait `rustc::ty::TypeFoldable<'_>` is not implemented for `&[&rustc::ty::TyS<'_>]`
+        let inputs_output = cx.tcx.erase_late_bound_regions(&fn_sig.inputs_and_output());
+        inputs_output
+            .iter()
+            .rev()
+            .skip(1)
+            .rev()
+            .enumerate()
+            .for_each(|(i, inp)| {
+                for trait_pred in &fn_mut_preds {
+                    if_chain! {
+                        if trait_pred.self_ty() == inp;
+                        if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
+                        then {
+                            if ord_preds.iter().any(|ord| ord.self_ty() == return_ty_pred.ty) {
+                                args_to_check.push((i, "Ord".to_string()));
+                            } else if partial_ord_preds.iter().any(|pord| pord.self_ty() == return_ty_pred.ty) {
+                                args_to_check.push((i, "PartialOrd".to_string()));
+                            }
+                        }
+                    }
+                }
+            });
+    }
+    args_to_check
+}
+
+fn check_arg<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'tcx>) -> Option<(Span, Option<Span>)> {
+    if_chain! {
+        if let ExprKind::Closure(_, _fn_decl, body_id, span, _) = arg.kind;
+        if let ty::Closure(_def_id, substs) = &cx.typeck_results().node_type(arg.hir_id).kind;
+        let ret_ty = substs.as_closure().sig().output();
+        let ty = cx.tcx.erase_late_bound_regions(&ret_ty);
+        if ty.is_unit();
+        then {
+            if_chain! {
+                let body = cx.tcx.hir().body(body_id);
+                if let ExprKind::Block(block, _) = body.value.kind;
+                if block.expr.is_none();
+                if let Some(stmt) = block.stmts.last();
+                if let StmtKind::Semi(_) = stmt.kind;
+                then {
+                    let data = stmt.span.data();
+                    // Make a span out of the semicolon for the help message
+                    Some((span, Some(Span::new(data.hi-BytePos(1), data.hi, data.ctxt))))
+                } else {
+                    Some((span, None))
+                }
+            }
+        } else {
+            None
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if let ExprKind::MethodCall(_, _, ref args, _) = expr.kind {
+            let arg_indices = get_args_to_check(cx, expr);
+            for (i, trait_name) in arg_indices {
+                if i < args.len() {
+                    match check_arg(cx, &args[i]) {
+                        Some((span, None)) => {
+                            span_lint(
+                                cx,
+                                UNIT_RETURN_EXPECTING_ORD,
+                                span,
+                                &format!(
+                                    "this closure returns \
+                                   the unit type which also implements {}",
+                                    trait_name
+                                ),
+                            );
+                        },
+                        Some((span, Some(last_semi))) => {
+                            span_lint_and_help(
+                                cx,
+                                UNIT_RETURN_EXPECTING_ORD,
+                                span,
+                                &format!(
+                                    "this closure returns \
+                                   the unit type which also implements {}",
+                                    trait_name
+                                ),
+                                Some(last_semi),
+                                &"probably caused by this trailing semicolon".to_string(),
+                            );
+                        },
+                        None => {},
+                    }
+                }
+            }
+        }
+    }
+}
index a48ad3185e9c2f440de3f95fd5bb0b9eb40e6ae8..1bf37632e326cfa2d7a76be9361983a49fecd731 100644 (file)
@@ -1,6 +1,6 @@
 use crate::utils::{
-    is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet, snippet_with_macro_callsite,
-    span_lint_and_help, span_lint_and_sugg,
+    get_parent_expr, is_type_diagnostic_item, match_def_path, match_trait_method, paths, snippet,
+    snippet_with_macro_callsite, span_lint_and_help, span_lint_and_sugg,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -79,6 +79,13 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
                     }
                 }
                 if match_trait_method(cx, e, &paths::INTO_ITERATOR) && &*name.ident.as_str() == "into_iter" {
+                    if let Some(parent_expr) = get_parent_expr(cx, e) {
+                        if let ExprKind::MethodCall(ref parent_name, ..) = parent_expr.kind {
+                            if &*parent_name.ident.as_str() != "into_iter" {
+                                return;
+                            }
+                        }
+                    }
                     let a = cx.typeck_results().expr_ty(e);
                     let b = cx.typeck_results().expr_ty(&args[0]);
                     if TyS::same_type(a, b) {
index 4b163fba52890a7aa341940f30d61198f732db94..a4bee1c278059a97329ef6a28e6426288ac426ef 100644 (file)
@@ -1346,7 +1346,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
             .predicates
             .iter()
             .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
-    !traits::normalize_and_test_predicates(
+    traits::impossible_predicates(
         cx.tcx,
         traits::elaborate_predicates(cx.tcx, predicates)
             .map(|o| o.predicate)
index 87cb454f654bcfb9a2a8ad70c4cceac6ccbd3253..5e8800d38eb52e9ee82387d5a7071755800bea4e 100644 (file)
@@ -36,7 +36,7 @@ pub struct NumericLiteral<'a> {
     pub integer: &'a str,
     /// The fraction part of the number.
     pub fraction: Option<&'a str>,
-    /// The character used as exponent seperator (b'e' or b'E') and the exponent part.
+    /// The character used as exponent separator (b'e' or b'E') and the exponent part.
     pub exponent: Option<(char, &'a str)>,
 
     /// The type suffix, including preceding underscore if present.
index 4c3462802e9218535b8343bc10b1946a3c3adb87..a515ee29c82adc64e2678302137a26ac40254157 100644 (file)
@@ -59,6 +59,7 @@
 pub const LINT: [&str; 3] = ["rustc_session", "lint", "Lint"];
 pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
 pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
+pub const MEM_MANUALLY_DROP: [&str; 4] = ["core", "mem", "manually_drop", "ManuallyDrop"];
 pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];
 pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"];
 pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
index ad73a1ea1acdfeda18cc022307729c2fc16ad470..58e7c354b27da1e2ab90ec3d74f3028fe891008c 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_hir as hir;
 
 declare_clippy_lint! {
-    /// **What it does:** Finds occurences of `Vec::resize(0, an_int)`
+    /// **What it does:** Finds occurrences of `Vec::resize(0, an_int)`
     ///
     /// **Why is this bad?** This is probably an argument inversion mistake.
     ///
index b89a87128626bc927db31c27665d220c452c52fd..1879aae77fb650783301cd1bc8500cca8551bdb7 100644 (file)
         group: "complexity",
         desc: "throwaway closures called in the expression they are defined",
         deprecation: None,
-        module: "misc_early",
+        module: "redundant_closure_call",
     },
     Lint {
         name: "redundant_closure_for_method_calls",
         deprecation: None,
         module: "types",
     },
+    Lint {
+        name: "unit_return_expecting_ord",
+        group: "correctness",
+        desc: "fn arguments of type Fn(...) -> Ord returning the unit type ().",
+        deprecation: None,
+        module: "unit_return_expecting_ord",
+    },
     Lint {
         name: "unknown_clippy_lints",
         group: "style",
index 2b20a4ceb4ab8d9ffcc3b658348920cbdfe53ad5..29c56f3a94f5f6bc8a13bce3934e46251377b167 100644 (file)
@@ -1,22 +1,22 @@
-error: called `.nth(0)` on a `std::iter::Iterator`
+error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent
   --> $DIR/iter_nth_zero.rs:20:14
    |
 LL |     let _x = s.iter().nth(0);
-   |              ^^^^^^^^^^^^^^^ help: try calling: `s.iter().next()`
+   |              ^^^^^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `s.iter().next()`
    |
    = note: `-D clippy::iter-nth-zero` implied by `-D warnings`
 
-error: called `.nth(0)` on a `std::iter::Iterator`
+error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent
   --> $DIR/iter_nth_zero.rs:25:14
    |
 LL |     let _y = iter.nth(0);
-   |              ^^^^^^^^^^^ help: try calling: `iter.next()`
+   |              ^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter.next()`
 
-error: called `.nth(0)` on a `std::iter::Iterator`
+error: called `.nth(0)` on a `std::iter::Iterator`, when `.next()` is equivalent
   --> $DIR/iter_nth_zero.rs:30:22
    |
 LL |     let _unwrapped = iter2.nth(0).unwrap();
-   |                      ^^^^^^^^^^^^ help: try calling: `iter2.next()`
+   |                      ^^^^^^^^^^^^ help: try calling `.next()` instead of `.nth(0)`: `iter2.next()`
 
 error: aborting due to 3 previous errors
 
index 6bb1032a17299108a9a2603662e5b25531e7114f..27222cc0869c83cf50a37d5c66fb63ee2ff92f62 100644 (file)
@@ -30,7 +30,7 @@ async fn already_async() -> impl Future<Output = i32> {
 struct S {}
 impl S {
     async fn inh_fut() -> i32 {
-        // NOTE: this code is here just to check that the identation is correct in the suggested fix
+        // NOTE: this code is here just to check that the indentation is correct in the suggested fix
         let a = 42;
         let b = 21;
         if a < b {
index d50c919188be13c4ff4111fa17e604771453da13..6a0f1b26c88388e18dfe49375799e928b578b049 100644 (file)
@@ -37,7 +37,7 @@ struct S {}
 impl S {
     fn inh_fut() -> impl Future<Output = i32> {
         async {
-            // NOTE: this code is here just to check that the identation is correct in the suggested fix
+            // NOTE: this code is here just to check that the indentation is correct in the suggested fix
             let a = 42;
             let b = 21;
             if a < b {
index f278ee41aa335607a9f26dd265ddb16bcc9206d7..a1904c904d0f4930672ec80fc40887a33769cf2f 100644 (file)
@@ -57,7 +57,7 @@ LL |     async fn inh_fut() -> i32 {
 help: move the body of the async block to the enclosing function
    |
 LL |     fn inh_fut() -> impl Future<Output = i32> {
-LL |         // NOTE: this code is here just to check that the identation is correct in the suggested fix
+LL |         // NOTE: this code is here just to check that the indentation is correct in the suggested fix
 LL |         let a = 42;
 LL |         let b = 21;
 LL |         if a < b {
index 2ed1b09bece746d1beb7ef6a791946efeee0f681..a82b1159161903d5ba36e427cc2265f2ed5e3c14 100644 (file)
@@ -83,3 +83,13 @@ fn main() {
         println!("{}", arr[i]);
     }
 }
+
+mod issue2277 {
+    pub fn example(list: &[[f64; 3]]) {
+        let mut x: [f64; 3] = [10.; 3];
+
+        for i in 0..3 {
+            x[i] = list.iter().map(|item| item[i]).sum::<f64>();
+        }
+    }
+}
index cbc4ca39161681f3edd71b684a9a91a2d8722d0b..2770eb2b2ab4389e635fd779134d5bfce061a4cd 100644 (file)
@@ -166,7 +166,7 @@ pub fn test14() {
     }
 }
 
-// Issue #1991: the outter loop should not warn.
+// Issue #1991: the outer loop should not warn.
 pub fn test15() {
     'label: loop {
         while false {
index dabb695368dba2b485cdc7de2b26defb1cdee55e..f91ccfaed743d4ac9ceb35e5a7651a9f176aa2e2 100644 (file)
@@ -4,24 +4,32 @@
 fn panic() {
     let a = 2;
     panic!();
+    panic!("message");
+    panic!("{} {}", "panic with", "multiple arguments");
     let b = a + 2;
 }
 
 fn todo() {
     let a = 2;
     todo!();
+    todo!("message");
+    todo!("{} {}", "panic with", "multiple arguments");
     let b = a + 2;
 }
 
 fn unimplemented() {
     let a = 2;
     unimplemented!();
+    unimplemented!("message");
+    unimplemented!("{} {}", "panic with", "multiple arguments");
     let b = a + 2;
 }
 
 fn unreachable() {
     let a = 2;
     unreachable!();
+    unreachable!("message");
+    unreachable!("{} {}", "panic with", "multiple arguments");
     let b = a + 2;
 }
 
index 72319bc7e45846014e6ad49e6669a7cf194e4e8a..37c11d72a574a8fdcb0b4d1dbb0e6498c26faa50 100644 (file)
@@ -6,29 +6,83 @@ LL |     panic!();
    |
    = note: `-D clippy::panic` implied by `-D warnings`
 
+error: `panic` should not be present in production code
+  --> $DIR/panicking_macros.rs:7:5
+   |
+LL |     panic!("message");
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `panic` should not be present in production code
+  --> $DIR/panicking_macros.rs:8:5
+   |
+LL |     panic!("{} {}", "panic with", "multiple arguments");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: `todo` should not be present in production code
-  --> $DIR/panicking_macros.rs:12:5
+  --> $DIR/panicking_macros.rs:14:5
    |
 LL |     todo!();
    |     ^^^^^^^^
    |
    = note: `-D clippy::todo` implied by `-D warnings`
 
+error: `todo` should not be present in production code
+  --> $DIR/panicking_macros.rs:15:5
+   |
+LL |     todo!("message");
+   |     ^^^^^^^^^^^^^^^^^
+
+error: `todo` should not be present in production code
+  --> $DIR/panicking_macros.rs:16:5
+   |
+LL |     todo!("{} {}", "panic with", "multiple arguments");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: `unimplemented` should not be present in production code
-  --> $DIR/panicking_macros.rs:18:5
+  --> $DIR/panicking_macros.rs:22:5
    |
 LL |     unimplemented!();
    |     ^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unimplemented` implied by `-D warnings`
 
-error: `unreachable` should not be present in production code
+error: `unimplemented` should not be present in production code
+  --> $DIR/panicking_macros.rs:23:5
+   |
+LL |     unimplemented!("message");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `unimplemented` should not be present in production code
   --> $DIR/panicking_macros.rs:24:5
    |
+LL |     unimplemented!("{} {}", "panic with", "multiple arguments");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `unreachable` should not be present in production code
+  --> $DIR/panicking_macros.rs:30:5
+   |
 LL |     unreachable!();
    |     ^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::unreachable` implied by `-D warnings`
 
-error: aborting due to 4 previous errors
+error: `unreachable` should not be present in production code
+  --> $DIR/panicking_macros.rs:31:5
+   |
+LL |     unreachable!("message");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `unreachable` should not be present in production code
+  --> $DIR/panicking_macros.rs:32:5
+   |
+LL |     unreachable!("{} {}", "panic with", "multiple arguments");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
index 17b1f1bd0bf300171fd79a797ff0df0a765f1697..4d284ae1319d321a4d867e91f10e71ae317bacd9 100644 (file)
@@ -32,7 +32,7 @@ fn main() {
     let _ = -(1i32.abs());
     let _ = -(1f32.abs());
 
-    // Odd functions shoud not trigger an error
+    // Odd functions should not trigger an error
     let _ = -1f64.asin();
     let _ = -1f64.asinh();
     let _ = -1f64.atan();
index 2d0891fd3c20c1c90631e6a582d14f50eafcdf95..2d08e82f349ade91eb20d8fa8adb3f040a6d2908 100644 (file)
@@ -32,7 +32,7 @@ fn main() {
     let _ = -(1i32.abs());
     let _ = -(1f32.abs());
 
-    // Odd functions shoud not trigger an error
+    // Odd functions should not trigger an error
     let _ = -1f64.asin();
     let _ = -1f64.asinh();
     let _ = -1f64.atan();
index 764c10a6d398feaa87957ed4bdbe7f353f7fb657..cdeefda4c234c071e573445af3e10e1f0e404702 100644 (file)
@@ -52,6 +52,7 @@ fn main() {
     borrower_propagation();
     not_consumed();
     issue_5405();
+    manually_drop();
 }
 
 #[derive(Clone)]
@@ -170,3 +171,17 @@ fn issue_5405() {
     let c: [usize; 2] = [2, 3];
     let _d: usize = c[1].clone();
 }
+
+fn manually_drop() {
+    use std::mem::ManuallyDrop;
+    use std::sync::Arc;
+
+    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
+    let _ = a.clone(); // OK
+
+    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
+    unsafe {
+        Arc::from_raw(p);
+        Arc::from_raw(p);
+    }
+}
index 839747b131d77da22c7d559d0133f7006bd2d246..acb7ffb305f2a8890b981bfed1c4f5303d8da232 100644 (file)
@@ -52,6 +52,7 @@ fn main() {
     borrower_propagation();
     not_consumed();
     issue_5405();
+    manually_drop();
 }
 
 #[derive(Clone)]
@@ -170,3 +171,17 @@ fn issue_5405() {
     let c: [usize; 2] = [2, 3];
     let _d: usize = c[1].clone();
 }
+
+fn manually_drop() {
+    use std::mem::ManuallyDrop;
+    use std::sync::Arc;
+
+    let a = ManuallyDrop::new(Arc::new("Hello!".to_owned()));
+    let _ = a.clone(); // OK
+
+    let p: *const String = Arc::into_raw(ManuallyDrop::into_inner(a));
+    unsafe {
+        Arc::from_raw(p);
+        Arc::from_raw(p);
+    }
+}
index eced198283ce8f5db36ef3fa7c4c2f93d38ec859..89b39254299107df27cc468f9b761d3f07d269f0 100644 (file)
@@ -108,61 +108,61 @@ LL |     let _t = tup.0.clone();
    |              ^^^^^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:61:22
+  --> $DIR/redundant_clone.rs:62:22
    |
 LL |         (a.clone(), a.clone())
    |                      ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:61:21
+  --> $DIR/redundant_clone.rs:62:21
    |
 LL |         (a.clone(), a.clone())
    |                     ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:121:15
+  --> $DIR/redundant_clone.rs:122:15
    |
 LL |     let _s = s.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:121:14
+  --> $DIR/redundant_clone.rs:122:14
    |
 LL |     let _s = s.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:122:15
+  --> $DIR/redundant_clone.rs:123:15
    |
 LL |     let _t = t.clone();
    |               ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:122:14
+  --> $DIR/redundant_clone.rs:123:14
    |
 LL |     let _t = t.clone();
    |              ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:132:19
+  --> $DIR/redundant_clone.rs:133:19
    |
 LL |         let _f = f.clone();
    |                   ^^^^^^^^ help: remove this
    |
 note: this value is dropped without further use
-  --> $DIR/redundant_clone.rs:132:18
+  --> $DIR/redundant_clone.rs:133:18
    |
 LL |         let _f = f.clone();
    |                  ^
 
 error: redundant clone
-  --> $DIR/redundant_clone.rs:144:14
+  --> $DIR/redundant_clone.rs:145:14
    |
 LL |     let y = x.clone().join("matthias");
    |              ^^^^^^^^ help: remove this
    |
 note: cloned value is neither consumed nor mutated
-  --> $DIR/redundant_clone.rs:144:13
+  --> $DIR/redundant_clone.rs:145:13
    |
 LL |     let y = x.clone().join("matthias");
    |             ^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call.rs b/src/tools/clippy/tests/ui/redundant_closure_call.rs
deleted file mode 100644 (file)
index bacd67d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// non rustfixable, see redundant_closure_call_fixable.rs
-
-#![warn(clippy::redundant_closure_call)]
-
-fn main() {
-    let mut i = 1;
-    let mut k = (|m| m + 1)(i);
-
-    k = (|a, b| a * b)(1, 5);
-
-    let closure = || 32;
-    i = closure();
-
-    let closure = |i| i + 1;
-    i = closure(3);
-
-    i = closure(4);
-
-    #[allow(clippy::needless_return)]
-    (|| return 2)();
-    (|| -> Option<i32> { None? })();
-    (|| -> Result<i32, i32> { Err(2)? })();
-}
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call.stderr b/src/tools/clippy/tests/ui/redundant_closure_call.stderr
deleted file mode 100644 (file)
index 68c1416..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error: Closure called just once immediately after it was declared
-  --> $DIR/redundant_closure_call.rs:12:5
-   |
-LL |     i = closure();
-   |     ^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
-
-error: Closure called just once immediately after it was declared
-  --> $DIR/redundant_closure_call.rs:15:5
-   |
-LL |     i = closure(3);
-   |     ^^^^^^^^^^^^^^
-
-error: Try not to call a closure in the expression where it is declared.
-  --> $DIR/redundant_closure_call.rs:7:17
-   |
-LL |     let mut k = (|m| m + 1)(i);
-   |                 ^^^^^^^^^^^^^^
-
-error: Try not to call a closure in the expression where it is declared.
-  --> $DIR/redundant_closure_call.rs:9:9
-   |
-LL |     k = (|a, b| a * b)(1, 5);
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_early.rs b/src/tools/clippy/tests/ui/redundant_closure_call_early.rs
new file mode 100644 (file)
index 0000000..3dd3656
--- /dev/null
@@ -0,0 +1,19 @@
+// non rustfixable, see redundant_closure_call_fixable.rs
+
+#![warn(clippy::redundant_closure_call)]
+
+fn main() {
+    let mut i = 1;
+
+    // lint here
+    let mut k = (|m| m + 1)(i);
+
+    // lint here
+    k = (|a, b| a * b)(1, 5);
+
+    // don't lint these
+    #[allow(clippy::needless_return)]
+    (|| return 2)();
+    (|| -> Option<i32> { None? })();
+    (|| -> Result<i32, i32> { Err(2)? })();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_early.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_early.stderr
new file mode 100644 (file)
index 0000000..79f2766
--- /dev/null
@@ -0,0 +1,16 @@
+error: try not to call a closure in the expression where it is declared.
+  --> $DIR/redundant_closure_call_early.rs:9:17
+   |
+LL |     let mut k = (|m| m + 1)(i);
+   |                 ^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
+
+error: try not to call a closure in the expression where it is declared.
+  --> $DIR/redundant_closure_call_early.rs:12:9
+   |
+LL |     k = (|a, b| a * b)(1, 5);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
index e7737f9dd856fe6719da3275e182d4df6f865e8c..644161d9f5d885eb24da0c187bfcd5e63ffa1352 100644 (file)
@@ -1,8 +1,8 @@
-error: Try not to call a closure in the expression where it is declared.
+error: try not to call a closure in the expression where it is declared.
   --> $DIR/redundant_closure_call_fixable.rs:7:13
    |
 LL |     let a = (|| 42)();
-   |             ^^^^^^^^^ help: Try doing something like: : `42`
+   |             ^^^^^^^^^ help: try doing something like: `42`
    |
    = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
 
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_late.rs b/src/tools/clippy/tests/ui/redundant_closure_call_late.rs
new file mode 100644 (file)
index 0000000..e29a1dc
--- /dev/null
@@ -0,0 +1,27 @@
+// non rustfixable, see redundant_closure_call_fixable.rs
+
+#![warn(clippy::redundant_closure_call)]
+
+fn main() {
+    let mut i = 1;
+
+    // don't lint here, the closure is used more than once
+    let closure = |i| i + 1;
+    i = closure(3);
+    i = closure(4);
+
+    // lint here
+    let redun_closure = || 1;
+    i = redun_closure();
+
+    // shadowed closures are supported, lint here
+    let shadowed_closure = || 1;
+    i = shadowed_closure();
+    let shadowed_closure = || 2;
+    i = shadowed_closure();
+
+    // don't lint here
+    let shadowed_closure = || 2;
+    i = shadowed_closure();
+    i = shadowed_closure();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_late.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_late.stderr
new file mode 100644 (file)
index 0000000..7c8865f
--- /dev/null
@@ -0,0 +1,22 @@
+error: closure called just once immediately after it was declared
+  --> $DIR/redundant_closure_call_late.rs:15:5
+   |
+LL |     i = redun_closure();
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::redundant-closure-call` implied by `-D warnings`
+
+error: closure called just once immediately after it was declared
+  --> $DIR/redundant_closure_call_late.rs:19:5
+   |
+LL |     i = shadowed_closure();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: closure called just once immediately after it was declared
+  --> $DIR/redundant_closure_call_late.rs:21:5
+   |
+LL |     i = shadowed_closure();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
index ce8582d2b221cd21c891bfd38af0d20bfd073ec4..adbff8af8d9ca087d2039df3d8b9855b2018ceaa 100644 (file)
@@ -11,6 +11,9 @@
 )]
 
 fn main() {
+    let result: Result<usize, usize> = Err(5);
+    if result.is_ok() {}
+
     if Ok::<i32, i32>(42).is_ok() {}
 
     if Err::<i32, i32>(42).is_err() {}
index a3a9aa40e3b9c8ec7fd2b7a708c34bf5d93377ab..4c2870e7803cb965d108e09ee3adbf3869e2e401 100644 (file)
@@ -11,6 +11,9 @@
 )]
 
 fn main() {
+    let result: Result<usize, usize> = Err(5);
+    if let Ok(_) = &result {}
+
     if let Ok(_) = Ok::<i32, i32>(42) {}
 
     if let Err(_) = Err::<i32, i32>(42) {}
index 25d1476062e7f599e7fe37dfddab9c1ce80bc1c0..d3c9ceaa3d7c18b0bee5a9cd15e1e451c2f1885d 100644 (file)
@@ -1,73 +1,79 @@
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:14:12
+  --> $DIR/redundant_pattern_matching.rs:15:12
    |
-LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
-   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+LL |     if let Ok(_) = &result {}
+   |     -------^^^^^---------- help: try this: `if result.is_ok()`
    |
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching.rs:17:12
+   |
+LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
+   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:16:12
+  --> $DIR/redundant_pattern_matching.rs:19:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:18:12
+  --> $DIR/redundant_pattern_matching.rs:21:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:20:12
+  --> $DIR/redundant_pattern_matching.rs:23:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:22:12
+  --> $DIR/redundant_pattern_matching.rs:25:12
    |
 LL |     if let Some(_) = Some(42) {
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:28:15
+  --> $DIR/redundant_pattern_matching.rs:31:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:30:15
+  --> $DIR/redundant_pattern_matching.rs:33:15
    |
 LL |     while let None = Some(42) {}
    |     ----------^^^^----------- help: try this: `while Some(42).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:32:15
+  --> $DIR/redundant_pattern_matching.rs:35:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:34:15
+  --> $DIR/redundant_pattern_matching.rs:37:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:36:15
+  --> $DIR/redundant_pattern_matching.rs:39:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:39:15
+  --> $DIR/redundant_pattern_matching.rs:42:15
    |
 LL |     while let Some(_) = v.pop() {
    |     ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:55:5
+  --> $DIR/redundant_pattern_matching.rs:58:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -76,7 +82,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:60:5
+  --> $DIR/redundant_pattern_matching.rs:63:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -85,7 +91,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:65:5
+  --> $DIR/redundant_pattern_matching.rs:68:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -94,7 +100,7 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:70:5
+  --> $DIR/redundant_pattern_matching.rs:73:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -103,7 +109,7 @@ LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:75:5
+  --> $DIR/redundant_pattern_matching.rs:78:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -112,7 +118,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:80:5
+  --> $DIR/redundant_pattern_matching.rs:83:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -121,7 +127,7 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:85:13
+  --> $DIR/redundant_pattern_matching.rs:88:13
    |
 LL |       let _ = match None::<()> {
    |  _____________^
@@ -131,64 +137,64 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:90:20
+  --> $DIR/redundant_pattern_matching.rs:93:20
    |
 LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:93:20
+  --> $DIR/redundant_pattern_matching.rs:96:20
    |
 LL |     let x = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:99:20
+  --> $DIR/redundant_pattern_matching.rs:102:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching.rs:101:19
+  --> $DIR/redundant_pattern_matching.rs:104:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:103:19
+  --> $DIR/redundant_pattern_matching.rs:106:19
    |
 LL |     } else if let Ok(_) = gen_res() {
    |            -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:105:19
+  --> $DIR/redundant_pattern_matching.rs:108:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:138:19
+  --> $DIR/redundant_pattern_matching.rs:141:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:139:16
+  --> $DIR/redundant_pattern_matching.rs:142:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:145:12
+  --> $DIR/redundant_pattern_matching.rs:148:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:146:15
+  --> $DIR/redundant_pattern_matching.rs:149:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
-error: aborting due to 28 previous errors
+error: aborting due to 29 previous errors
 
index 7fa58cf76499b8016b9c062a647ef041cc5d2444..8a831375b412dacdd4f705df37df47b507ca5823 100644 (file)
@@ -104,7 +104,7 @@ note: previous binding is here
 LL |     let x = (1, x);
    |         ^
 
-error: `x` is shadowed by `y`
+error: `x` is being shadowed
   --> $DIR/shadow.rs:34:9
    |
 LL |     let x = y;
diff --git a/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs b/src/tools/clippy/tests/ui/unit_return_expecting_ord.rs
new file mode 100644 (file)
index 0000000..bdb4710
--- /dev/null
@@ -0,0 +1,36 @@
+#![warn(clippy::unit_return_expecting_ord)]
+#![allow(clippy::needless_return)]
+#![allow(clippy::unused_unit)]
+#![feature(is_sorted)]
+
+struct Struct {
+    field: isize,
+}
+
+fn double(i: isize) -> isize {
+    i * 2
+}
+
+fn unit(_i: isize) {}
+
+fn main() {
+    let mut structs = vec![Struct { field: 2 }, Struct { field: 1 }];
+    structs.sort_by_key(|s| {
+        double(s.field);
+    });
+    structs.sort_by_key(|s| double(s.field));
+    structs.is_sorted_by_key(|s| {
+        double(s.field);
+    });
+    structs.is_sorted_by_key(|s| {
+        if s.field > 0 {
+            ()
+        } else {
+            return ();
+        }
+    });
+    structs.sort_by_key(|s| {
+        return double(s.field);
+    });
+    structs.sort_by_key(|s| unit(s.field));
+}
diff --git a/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr b/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
new file mode 100644 (file)
index 0000000..e63d587
--- /dev/null
@@ -0,0 +1,39 @@
+error: this closure returns the unit type which also implements Ord
+  --> $DIR/unit_return_expecting_ord.rs:18:25
+   |
+LL |     structs.sort_by_key(|s| {
+   |                         ^^^
+   |
+   = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings`
+help: probably caused by this trailing semicolon
+  --> $DIR/unit_return_expecting_ord.rs:19:24
+   |
+LL |         double(s.field);
+   |                        ^
+
+error: this closure returns the unit type which also implements PartialOrd
+  --> $DIR/unit_return_expecting_ord.rs:22:30
+   |
+LL |     structs.is_sorted_by_key(|s| {
+   |                              ^^^
+   |
+help: probably caused by this trailing semicolon
+  --> $DIR/unit_return_expecting_ord.rs:23:24
+   |
+LL |         double(s.field);
+   |                        ^
+
+error: this closure returns the unit type which also implements PartialOrd
+  --> $DIR/unit_return_expecting_ord.rs:25:30
+   |
+LL |     structs.is_sorted_by_key(|s| {
+   |                              ^^^
+
+error: this closure returns the unit type which also implements Ord
+  --> $DIR/unit_return_expecting_ord.rs:35:25
+   |
+LL |     structs.sort_by_key(|s| unit(s.field));
+   |                         ^^^
+
+error: aborting due to 4 previous errors
+
index fdd4bc581f305a21281c8d6da8e642cc54dbf455..813cdaecaa91a8864f8f285a8f3c3130c0cb5bc4 100644 (file)
@@ -32,11 +32,20 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn test_issue_5833() -> Result<(), ()> {
+    let text = "foo\r\nbar\n\nbaz\n";
+    let lines = text.lines();
+    if Some("ok") == lines.into_iter().next() {}
+
+    Ok(())
+}
+
 fn main() {
     test_generic(10i32);
     test_generic2::<i32, i32>(10i32);
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
+    test_issue_5833().unwrap();
 
     let _: String = "foo".into();
     let _: String = From::from("foo");
index 4cae745e7c0211f2a886c21760451f459192fd59..540fea23b36b98e0061e4a7566b0666e04254516 100644 (file)
@@ -32,11 +32,20 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn test_issue_5833() -> Result<(), ()> {
+    let text = "foo\r\nbar\n\nbaz\n";
+    let lines = text.lines();
+    if Some("ok") == lines.into_iter().next() {}
+
+    Ok(())
+}
+
 fn main() {
     test_generic(10i32);
     test_generic2::<i32, i32>(10i32);
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
+    test_issue_5833().unwrap();
 
     let _: String = "foo".into();
     let _: String = From::from("foo");
index 84ec53702788c12592f02387ec2deaef7f5c36c0..b958b0354520326577fdfcf17d56e932a6b813df 100644 (file)
@@ -23,43 +23,43 @@ LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:51:21
+  --> $DIR/useless_conversion.rs:60:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:52:21
+  --> $DIR/useless_conversion.rs:61:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:53:13
+  --> $DIR/useless_conversion.rs:62:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:54:13
+  --> $DIR/useless_conversion.rs:63:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:55:13
+  --> $DIR/useless_conversion.rs:64:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:56:13
+  --> $DIR/useless_conversion.rs:65:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type
-  --> $DIR/useless_conversion.rs:57:21
+  --> $DIR/useless_conversion.rs:66:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
index 0263e2f5f20c113920111ee6b41e62f89a1944ed..7ed27439ec6e4432372224dd696d485024918b96 100644 (file)
@@ -7,7 +7,7 @@ fn main() {
     // not applicable
     vec![1, 2, 3, 4, 5].resize(2, 5);
 
-    // applicable here, but only implemented for integer litterals for now
+    // applicable here, but only implemented for integer literals for now
     vec!["foo", "bar", "baz"].resize(0, "bar");
 
     // not applicable
index 5f7373be6594636540e3ba6845bbd5e8a4505cf8..9269a63b41aab9d29f3904c534b6538e213cd4bc 100644 (file)
@@ -271,13 +271,13 @@ pub struct Config {
     pub gdb_native_rust: bool,
 
     /// Version of LLDB
-    pub lldb_version: Option<String>,
+    pub lldb_version: Option<u32>,
 
     /// Whether LLDB has native rust support
     pub lldb_native_rust: bool,
 
     /// Version of LLVM
-    pub llvm_version: Option<String>,
+    pub llvm_version: Option<u32>,
 
     /// Is LLVM a system LLVM
     pub system_llvm: bool,
index d6e28e93c96676aaf5ba632d17916e40d06c4b2f..2ab764eb9207c4fc96680aa20e99a1caac67e39d 100644 (file)
@@ -132,72 +132,46 @@ pub fn from_reader<R: Read>(config: &Config, testfile: &Path, rdr: R) -> Self {
 
         fn ignore_gdb(config: &Config, line: &str) -> bool {
             if let Some(actual_version) = config.gdb_version {
-                if line.starts_with("min-gdb-version") {
-                    let (start_ver, end_ver) = extract_gdb_version_range(line);
+                if let Some(rest) = line.strip_prefix("min-gdb-version:").map(str::trim) {
+                    let (start_ver, end_ver) = extract_version_range(rest, extract_gdb_version)
+                        .unwrap_or_else(|| {
+                            panic!("couldn't parse version range: {:?}", rest);
+                        });
 
                     if start_ver != end_ver {
                         panic!("Expected single GDB version")
                     }
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    actual_version < start_ver
-                } else if line.starts_with("ignore-gdb-version") {
-                    let (min_version, max_version) = extract_gdb_version_range(line);
+                    return actual_version < start_ver;
+                } else if let Some(rest) = line.strip_prefix("ignore-gdb-version:").map(str::trim) {
+                    let (min_version, max_version) =
+                        extract_version_range(rest, extract_gdb_version).unwrap_or_else(|| {
+                            panic!("couldn't parse version range: {:?}", rest);
+                        });
 
                     if max_version < min_version {
                         panic!("Malformed GDB version range: max < min")
                     }
 
-                    actual_version >= min_version && actual_version <= max_version
-                } else {
-                    false
-                }
-            } else {
-                false
-            }
-        }
-
-        // Takes a directive of the form "ignore-gdb-version <version1> [- <version2>]",
-        // returns the numeric representation of <version1> and <version2> as
-        // tuple: (<version1> as u32, <version2> as u32)
-        // If the <version2> part is omitted, the second component of the tuple
-        // is the same as <version1>.
-        fn extract_gdb_version_range(line: &str) -> (u32, u32) {
-            const ERROR_MESSAGE: &'static str = "Malformed GDB version directive";
-
-            let range_components = line
-                .split(&[' ', '-'][..])
-                .filter(|word| !word.is_empty())
-                .map(extract_gdb_version)
-                .skip_while(Option::is_none)
-                .take(3) // 3 or more = invalid, so take at most 3.
-                .collect::<Vec<Option<u32>>>();
-
-            match range_components.len() {
-                1 => {
-                    let v = range_components[0].unwrap();
-                    (v, v)
-                }
-                2 => {
-                    let v_min = range_components[0].unwrap();
-                    let v_max = range_components[1].expect(ERROR_MESSAGE);
-                    (v_min, v_max)
+                    return actual_version >= min_version && actual_version <= max_version;
                 }
-                _ => panic!(ERROR_MESSAGE),
             }
+            false
         }
 
         fn ignore_lldb(config: &Config, line: &str) -> bool {
-            if let Some(ref actual_version) = config.lldb_version {
-                if line.starts_with("min-lldb-version") {
-                    let min_version = line
-                        .trim_end()
-                        .rsplit(' ')
-                        .next()
-                        .expect("Malformed lldb version directive");
+            if let Some(actual_version) = config.lldb_version {
+                if let Some(min_version) = line.strip_prefix("min-lldb-version:").map(str::trim) {
+                    let min_version = min_version.parse().unwrap_or_else(|e| {
+                        panic!(
+                            "Unexpected format of LLDB version string: {}\n{:?}",
+                            min_version, e
+                        );
+                    });
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    lldb_version_to_int(actual_version) < lldb_version_to_int(min_version)
+                    actual_version < min_version
                 } else if line.starts_with("rust-lldb") && !config.lldb_native_rust {
                     true
                 } else {
@@ -212,48 +186,31 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
             if config.system_llvm && line.starts_with("no-system-llvm") {
                 return true;
             }
-            if let Some(ref actual_version) = config.llvm_version {
-                let actual_version = version_to_int(actual_version);
-                if line.starts_with("min-llvm-version") {
-                    let min_version = line
-                        .trim_end()
-                        .rsplit(' ')
-                        .next()
-                        .expect("Malformed llvm version directive");
+            if let Some(actual_version) = config.llvm_version {
+                if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
+                    let min_version = extract_llvm_version(rest).unwrap();
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    actual_version < version_to_int(min_version)
-                } else if line.starts_with("min-system-llvm-version") {
-                    let min_version = line
-                        .trim_end()
-                        .rsplit(' ')
-                        .next()
-                        .expect("Malformed llvm version directive");
+                    actual_version < min_version
+                } else if let Some(rest) =
+                    line.strip_prefix("min-system-llvm-version:").map(str::trim)
+                {
+                    let min_version = extract_llvm_version(rest).unwrap();
                     // Ignore if using system LLVM and actual version
                     // is smaller the minimum required version
-                    config.system_llvm && actual_version < version_to_int(min_version)
-                } else if line.starts_with("ignore-llvm-version") {
-                    // Syntax is: "ignore-llvm-version <version1> [- <version2>]"
-                    let range_components = line
-                        .split(' ')
-                        .skip(1) // Skip the directive.
-                        .map(|s| s.trim())
-                        .filter(|word| !word.is_empty() && word != &"-")
-                        .take(3) // 3 or more = invalid, so take at most 3.
-                        .collect::<Vec<&str>>();
-                    match range_components.len() {
-                        1 => actual_version == version_to_int(range_components[0]),
-                        2 => {
-                            let v_min = version_to_int(range_components[0]);
-                            let v_max = version_to_int(range_components[1]);
-                            if v_max < v_min {
-                                panic!("Malformed LLVM version range: max < min")
-                            }
-                            // Ignore if version lies inside of range.
-                            actual_version >= v_min && actual_version <= v_max
-                        }
-                        _ => panic!("Malformed LLVM version directive"),
+                    config.system_llvm && actual_version < min_version
+                } else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim)
+                {
+                    // Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
+                    let (v_min, v_max) = extract_version_range(rest, extract_llvm_version)
+                        .unwrap_or_else(|| {
+                            panic!("couldn't parse version range: {:?}", rest);
+                        });
+                    if v_max < v_min {
+                        panic!("Malformed LLVM version range: max < min")
                     }
+                    // Ignore if version lies inside of range.
+                    actual_version >= v_min && actual_version <= v_max
                 } else {
                     false
                 }
@@ -261,20 +218,6 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
                 false
             }
         }
-
-        fn version_to_int(version: &str) -> u32 {
-            let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap();
-            let components: Vec<u32> = version_without_suffix
-                .split('.')
-                .map(|s| s.parse().expect("Malformed version component"))
-                .collect();
-            match components.len() {
-                1 => components[0] * 10000,
-                2 => components[0] * 10000 + components[1] * 100,
-                3 => components[0] * 10000 + components[1] * 100 + components[2],
-                _ => panic!("Malformed version"),
-            }
-        }
     }
 }
 
@@ -944,12 +887,6 @@ fn parse_edition(&self, line: &str) -> Option<String> {
     }
 }
 
-pub fn lldb_version_to_int(version_string: &str) -> isize {
-    let error_string =
-        format!("Encountered LLDB version string with unexpected format: {}", version_string);
-    version_string.parse().expect(&error_string)
-}
-
 fn expand_variables(mut value: String, config: &Config) -> String {
     const CWD: &'static str = "{{cwd}}";
     const SRC_BASE: &'static str = "{{src-base}}";
@@ -990,3 +927,49 @@ fn parse_normalization_string(line: &mut &str) -> Option<String> {
     *line = &line[end + 1..];
     Some(result)
 }
+
+pub fn extract_llvm_version(version: &str) -> Option<u32> {
+    let version_without_suffix = version.trim_end_matches("git").split('-').next().unwrap();
+    let components: Vec<u32> = version_without_suffix
+        .split('.')
+        .map(|s| s.parse().expect("Malformed version component"))
+        .collect();
+    let version = match *components {
+        [a] => a * 10_000,
+        [a, b] => a * 10_000 + b * 100,
+        [a, b, c] => a * 10_000 + b * 100 + c,
+        _ => panic!("Malformed version"),
+    };
+    Some(version)
+}
+
+// Takes a directive of the form "<version1> [- <version2>]",
+// returns the numeric representation of <version1> and <version2> as
+// tuple: (<version1> as u32, <version2> as u32)
+// If the <version2> part is omitted, the second component of the tuple
+// is the same as <version1>.
+fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
+where
+    F: Fn(&str) -> Option<u32>,
+{
+    let mut splits = line.splitn(2, "- ").map(str::trim);
+    let min = splits.next().unwrap();
+    if min.ends_with('-') {
+        return None;
+    }
+
+    let max = splits.next();
+
+    if min.is_empty() {
+        return None;
+    }
+
+    let min = parse(min)?;
+    let max = match max {
+        Some(max) if max.is_empty() => return None,
+        Some(max) => parse(max)?,
+        _ => min,
+    };
+
+    Some((min, max))
+}
index 72af34d78260ba6007a385300ba0c8be2aeb8622..1f82b137ee6cf1fb312375882c9fbc4e64678157 100644 (file)
@@ -119,17 +119,17 @@ fn no_system_llvm() {
 fn llvm_version() {
     let mut config = config();
 
-    config.llvm_version = Some("8.1.2-rust".to_owned());
-    assert!(parse_rs(&config, "// min-llvm-version 9.0").ignore);
+    config.llvm_version = Some(80102);
+    assert!(parse_rs(&config, "// min-llvm-version: 9.0").ignore);
 
-    config.llvm_version = Some("9.0.1-rust-1.43.0-dev".to_owned());
-    assert!(parse_rs(&config, "// min-llvm-version 9.2").ignore);
+    config.llvm_version = Some(90001);
+    assert!(parse_rs(&config, "// min-llvm-version: 9.2").ignore);
 
-    config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned());
-    assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore);
+    config.llvm_version = Some(90301);
+    assert!(!parse_rs(&config, "// min-llvm-version: 9.2").ignore);
 
-    config.llvm_version = Some("10.0.0-rust".to_owned());
-    assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore);
+    config.llvm_version = Some(100000);
+    assert!(!parse_rs(&config, "// min-llvm-version: 9.0").ignore);
 }
 
 #[test]
@@ -220,3 +220,18 @@ fn sanitizers() {
     assert!(parse_rs(&config, "// needs-sanitizer-memory").ignore);
     assert!(parse_rs(&config, "// needs-sanitizer-thread").ignore);
 }
+
+#[test]
+fn test_extract_version_range() {
+    use super::{extract_llvm_version, extract_version_range};
+
+    assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
+    assert_eq!(extract_version_range("0   - 4.5.6", extract_llvm_version), Some((0, 40506)));
+    assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
+    assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
+    assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
+    assert_eq!(extract_version_range("-", extract_llvm_version), None);
+    assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
+    assert_eq!(extract_version_range("   - 4.5.6", extract_llvm_version), None);
+    assert_eq!(extract_version_range("0  -", extract_llvm_version), None);
+}
index 07eba22c6eeb3a048f0a0322bfd492217ce389d2..bf3510ea0894bfeb74b01b7de1a5fb731dbdc61d 100644 (file)
@@ -166,14 +166,20 @@ fn make_absolute(path: PathBuf) -> PathBuf {
     let cdb = analyze_cdb(matches.opt_str("cdb"), &target);
     let (gdb, gdb_version, gdb_native_rust) =
         analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path);
-    let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version"));
-
-    let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
+    let (lldb_version, lldb_native_rust) = matches
+        .opt_str("lldb-version")
+        .as_deref()
+        .and_then(extract_lldb_version)
+        .map(|(v, b)| (Some(v), b))
+        .unwrap_or((None, false));
+    let color = match matches.opt_str("color").as_deref() {
         Some("auto") | None => ColorConfig::AutoColor,
         Some("always") => ColorConfig::AlwaysColor,
         Some("never") => ColorConfig::NeverColor,
         Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
     };
+    let llvm_version =
+        matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version);
 
     let src_base = opt_path(matches, "src-base");
     let run_ignored = matches.opt_present("ignored");
@@ -215,7 +221,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         gdb_native_rust,
         lldb_version,
         lldb_native_rust,
-        llvm_version: matches.opt_str("llvm-version"),
+        llvm_version,
         system_llvm: matches.opt_present("system-llvm"),
         android_cross_path,
         adb_path: opt_str2(matches.opt_str("adb-path")),
@@ -254,7 +260,7 @@ pub fn log_config(config: &Config) {
     logv(c, format!("stage_id: {}", config.stage_id));
     logv(c, format!("mode: {}", config.mode));
     logv(c, format!("run_ignored: {}", config.run_ignored));
-    logv(c, format!("filter: {}", opt_str(&config.filter.as_ref().map(|re| re.to_owned()))));
+    logv(c, format!("filter: {}", opt_str(&config.filter)));
     logv(c, format!("filter_exact: {}", config.filter_exact));
     logv(
         c,
@@ -403,17 +409,14 @@ fn configure_lldb(config: &Config) -> Option<Config> {
         return None;
     }
 
-    if let Some(lldb_version) = config.lldb_version.as_ref() {
-        if lldb_version == "350" {
-            println!(
-                "WARNING: The used version of LLDB ({}) has a \
-                 known issue that breaks debuginfo tests. See \
-                 issue #32520 for more information. Skipping all \
-                 LLDB-based tests!",
-                lldb_version
-            );
-            return None;
-        }
+    if let Some(350) = config.lldb_version {
+        println!(
+            "WARNING: The used version of LLDB (350) has a \
+             known issue that breaks debuginfo tests. See \
+             issue #32520 for more information. Skipping all \
+             LLDB-based tests!",
+        );
+        return None;
     }
 
     // Some older versions of LLDB seem to have problems with multiple
@@ -727,9 +730,7 @@ fn make_test_closure(
     let config = config.clone();
     let testpaths = testpaths.clone();
     let revision = revision.cloned();
-    test::DynTestFn(Box::new(move || {
-        runtest::run(config, &testpaths, revision.as_ref().map(|s| s.as_str()))
-    }))
+    test::DynTestFn(Box::new(move || runtest::run(config, &testpaths, revision.as_deref())))
 }
 
 /// Returns `true` if the given target is an Android target for the
@@ -845,75 +846,40 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
     // This particular form is documented in the GNU coding standards:
     // https://www.gnu.org/prep/standards/html_node/_002d_002dversion.html#g_t_002d_002dversion
 
-    // don't start parsing in the middle of a number
-    let mut prev_was_digit = false;
-    let mut in_parens = false;
-    for (pos, c) in full_version_line.char_indices() {
-        if in_parens {
-            if c == ')' {
-                in_parens = false;
-            }
-            continue;
-        } else if c == '(' {
-            in_parens = true;
-            continue;
-        }
-
-        if prev_was_digit || !c.is_digit(10) {
-            prev_was_digit = c.is_digit(10);
-            continue;
+    let mut splits = full_version_line.rsplit(' ');
+    let version_string = splits.next().unwrap();
+
+    let mut splits = version_string.split('.');
+    let major = splits.next().unwrap();
+    let minor = splits.next().unwrap();
+    let patch = splits.next();
+
+    let major: u32 = major.parse().unwrap();
+    let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
+        None => {
+            let minor = minor.parse().unwrap();
+            let patch: u32 = match patch {
+                Some(patch) => match patch.find(not_a_digit) {
+                    None => patch.parse().unwrap(),
+                    Some(idx) if idx > 3 => 0,
+                    Some(idx) => patch[..idx].parse().unwrap(),
+                },
+                None => 0,
+            };
+            (minor, patch)
         }
-
-        prev_was_digit = true;
-
-        let line = &full_version_line[pos..];
-
-        let next_split = match line.find(|c: char| !c.is_digit(10)) {
-            Some(idx) => idx,
-            None => continue, // no minor version
-        };
-
-        if line.as_bytes()[next_split] != b'.' {
-            continue; // no minor version
+        // There is no patch version after minor-date (e.g. "4-2012").
+        Some(idx) => {
+            let minor = minor[..idx].parse().unwrap();
+            (minor, 0)
         }
+    };
 
-        let major = &line[..next_split];
-        let line = &line[next_split + 1..];
-
-        let (minor, patch) = match line.find(|c: char| !c.is_digit(10)) {
-            Some(idx) => {
-                if line.as_bytes()[idx] == b'.' {
-                    let patch = &line[idx + 1..];
-
-                    let patch_len =
-                        patch.find(|c: char| !c.is_digit(10)).unwrap_or_else(|| patch.len());
-                    let patch = &patch[..patch_len];
-                    let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) };
-
-                    (&line[..idx], patch)
-                } else {
-                    (&line[..idx], None)
-                }
-            }
-            None => (line, None),
-        };
-
-        if minor.is_empty() {
-            continue;
-        }
-
-        let major: u32 = major.parse().unwrap();
-        let minor: u32 = minor.parse().unwrap();
-        let patch: u32 = patch.unwrap_or("0").parse().unwrap();
-
-        return Some(((major * 1000) + minor) * 1000 + patch);
-    }
-
-    None
+    Some(((major * 1000) + minor) * 1000 + patch)
 }
 
 /// Returns (LLDB version, LLDB is rust-enabled)
-fn extract_lldb_version(full_version_line: Option<String>) -> (Option<String>, bool) {
+fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> {
     // Extract the major LLDB version from the given version string.
     // LLDB version strings are different for Apple and non-Apple platforms.
     // The Apple variant looks like this:
@@ -922,7 +888,7 @@ fn extract_lldb_version(full_version_line: Option<String>) -> (Option<String>, b
     // lldb-300.2.51 (new versions)
     //
     // We are only interested in the major version number, so this function
-    // will return `Some("179")` and `Some("300")` respectively.
+    // will return `Some(179)` and `Some(300)` respectively.
     //
     // Upstream versions look like:
     // lldb version 6.0.1
@@ -934,53 +900,24 @@ fn extract_lldb_version(full_version_line: Option<String>) -> (Option<String>, b
     // normally fine because the only non-Apple version we test is
     // rust-enabled.
 
-    if let Some(ref full_version_line) = full_version_line {
-        if !full_version_line.trim().is_empty() {
-            let full_version_line = full_version_line.trim();
-
-            for (pos, l) in full_version_line.char_indices() {
-                if l != 'l' && l != 'L' {
-                    continue;
-                }
-                if pos + 5 >= full_version_line.len() {
-                    continue;
-                }
-                let l = full_version_line[pos + 1..].chars().next().unwrap();
-                if l != 'l' && l != 'L' {
-                    continue;
-                }
-                let d = full_version_line[pos + 2..].chars().next().unwrap();
-                if d != 'd' && d != 'D' {
-                    continue;
-                }
-                let b = full_version_line[pos + 3..].chars().next().unwrap();
-                if b != 'b' && b != 'B' {
-                    continue;
-                }
-                let dash = full_version_line[pos + 4..].chars().next().unwrap();
-                if dash != '-' {
-                    continue;
-                }
-
-                let vers = full_version_line[pos + 5..]
-                    .chars()
-                    .take_while(|c| c.is_digit(10))
-                    .collect::<String>();
-                if !vers.is_empty() {
-                    return (Some(vers), full_version_line.contains("rust-enabled"));
-                }
-            }
+    let full_version_line = full_version_line.trim();
 
-            if full_version_line.starts_with("lldb version ") {
-                let vers = full_version_line[13..]
-                    .chars()
-                    .take_while(|c| c.is_digit(10))
-                    .collect::<String>();
-                if !vers.is_empty() {
-                    return (Some(vers + "00"), full_version_line.contains("rust-enabled"));
-                }
-            }
+    if let Some(apple_ver) =
+        full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
+    {
+        if let Some(idx) = apple_ver.find(not_a_digit) {
+            let version: u32 = apple_ver[..idx].parse().unwrap();
+            return Some((version, full_version_line.contains("rust-enabled")));
+        }
+    } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
+        if let Some(idx) = lldb_ver.find(not_a_digit) {
+            let version: u32 = lldb_ver[..idx].parse().unwrap();
+            return Some((version * 100, full_version_line.contains("rust-enabled")));
         }
     }
-    (None, false)
+    None
+}
+
+fn not_a_digit(c: char) -> bool {
+    !c.is_digit(10)
 }
index f09f7621aa170ebc453b0508ee89f0fddaae0acf..21fb7673ce061c9eb1b2fffd812edafde83cb576 100644 (file)
@@ -3135,14 +3135,47 @@ fn check_mir_dump(&self) {
         }
         for l in test_file_contents.lines() {
             if l.starts_with("// EMIT_MIR ") {
-                let test_name = l.trim_start_matches("// EMIT_MIR ");
-                let expected_file = test_dir.join(test_name);
-
-                let dumped_string = if test_name.ends_with(".diff") {
-                    let test_name = test_name.trim_end_matches(".diff");
-                    let before = format!("{}.before.mir", test_name);
-                    let after = format!("{}.after.mir", test_name);
-                    let before = self.get_mir_dump_dir().join(before);
+                let test_name = l.trim_start_matches("// EMIT_MIR ").trim();
+                let mut test_names = test_name.split(' ');
+                // sometimes we specify two files so that we get a diff between the two files
+                let test_name = test_names.next().unwrap();
+                let expected_file;
+                let from_file;
+                let to_file;
+
+                if test_name.ends_with(".diff") {
+                    let trimmed = test_name.trim_end_matches(".diff");
+                    let test_against = format!("{}.after.mir", trimmed);
+                    from_file = format!("{}.before.mir", trimmed);
+                    expected_file = test_name.to_string();
+                    assert!(
+                        test_names.next().is_none(),
+                        "two mir pass names specified for MIR diff"
+                    );
+                    to_file = Some(test_against);
+                } else if let Some(first_pass) = test_names.next() {
+                    let second_pass = test_names.next().unwrap();
+                    assert!(
+                        test_names.next().is_none(),
+                        "three mir pass names specified for MIR diff"
+                    );
+                    expected_file = format!("{}.{}-{}.diff", test_name, first_pass, second_pass);
+                    let second_file = format!("{}.{}.mir", test_name, second_pass);
+                    from_file = format!("{}.{}.mir", test_name, first_pass);
+                    to_file = Some(second_file);
+                } else {
+                    expected_file = test_name.to_string();
+                    from_file = test_name.to_string();
+                    assert!(
+                        test_names.next().is_none(),
+                        "two mir pass names specified for MIR dump"
+                    );
+                    to_file = None;
+                };
+                let expected_file = test_dir.join(expected_file);
+
+                let dumped_string = if let Some(after) = to_file {
+                    let before = self.get_mir_dump_dir().join(from_file);
                     let after = self.get_mir_dump_dir().join(after);
                     debug!(
                         "comparing the contents of: {} with {}",
@@ -3166,7 +3199,7 @@ fn check_mir_dump(&self) {
                 } else {
                     let mut output_file = PathBuf::new();
                     output_file.push(self.get_mir_dump_dir());
-                    output_file.push(test_name);
+                    output_file.push(&from_file);
                     debug!(
                         "comparing the contents of: {} with {}",
                         output_file.display(),
@@ -3179,7 +3212,7 @@ fn check_mir_dump(&self) {
                             output_file.parent().unwrap().display()
                         );
                     }
-                    self.check_mir_test_timestamp(test_name, &output_file);
+                    self.check_mir_test_timestamp(&from_file, &output_file);
                     let dumped_string = fs::read_to_string(&output_file).unwrap();
                     self.normalize_output(&dumped_string, &[])
                 };
index 31c151d29e916c75bc2607870bfa354ac5ecc0c3..ea9bc1c1a5b7f5a7413c26b0939db1bec0767d98 100644 (file)
@@ -1,8 +1,9 @@
+use super::header::extract_llvm_version;
 use super::*;
 
 #[test]
 fn test_extract_gdb_version() {
-    macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$(
+    macro_rules! test { ($($expectation:literal: $input:literal,)*) => {{$(
         assert_eq!(extract_gdb_version($input), Some($expectation));
     )*}}}
 
@@ -41,6 +42,17 @@ macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$(
     }
 }
 
+#[test]
+fn test_extract_lldb_version() {
+    // Apple variants
+    assert_eq!(extract_lldb_version("LLDB-179.5"), Some((179, false)));
+    assert_eq!(extract_lldb_version("lldb-300.2.51"), Some((300, false)));
+
+    // Upstream versions
+    assert_eq!(extract_lldb_version("lldb version 6.0.1"), Some((600, false)));
+    assert_eq!(extract_lldb_version("lldb version 9.0.0"), Some((900, false)));
+}
+
 #[test]
 fn is_test_test() {
     assert_eq!(true, is_test(&OsString::from("a_test.rs")));
@@ -49,3 +61,11 @@ fn is_test_test() {
     assert_eq!(false, is_test(&OsString::from("#a_dog_gif")));
     assert_eq!(false, is_test(&OsString::from("~a_temp_file")));
 }
+
+#[test]
+fn test_extract_llvm_version() {
+    assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
+    assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
+    assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
+    assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
+}
index 992af261b8352f1495f91e8f3d3d01515df40440..787e08404e1c61581768d4425129d939b96cbfb0 100644 (file)
@@ -3,7 +3,6 @@ authors = ["The Rust Project Developers"]
 name = "error_index_generator"
 version = "0.0.0"
 edition = "2018"
-build = "build.rs"
 
 [dependencies]
 rustdoc = { path = "../../librustdoc" }
index 72437e070044ce7aaf173136309d4fce87136a6f..c0631fcedd34973d259fce507d914851284e1eac 100755 (executable)
@@ -26,7 +26,7 @@ except ImportError:
 MAINTAINERS = {
     'miri': {'oli-obk', 'RalfJung', 'eddyb'},
     'rls': {'Xanewok'},
-    'rustfmt': {'topecongiro'},
+    'rustfmt': {'topecongiro', 'calebcartwright'},
     'book': {'carols10cents', 'steveklabnik'},
     'nomicon': {'frewsxcv', 'Gankra'},
     'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
index dd341d53075411cf0f71c5853c98facda35112ef..a0e80a9783b1485fe8935d5de4dec34fe6bb5f10 160000 (submodule)
@@ -1 +1 @@
-Subproject commit dd341d53075411cf0f71c5853c98facda35112ef
+Subproject commit a0e80a9783b1485fe8935d5de4dec34fe6bb5f10
index 8b0983e89ad9a28b142eccf3755a8c9aaeb37852..c9c518e5e9761bf35d466c47c57c3a1358b56b3c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8b0983e89ad9a28b142eccf3755a8c9aaeb37852
+Subproject commit c9c518e5e9761bf35d466c47c57c3a1358b56b3c
index c1e9b7b87493c5197c4330693bdf4ccb30a90971..cef1c0d5ebde015d72d830e655ca1b4079a08494 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c1e9b7b87493c5197c4330693bdf4ccb30a90971
+Subproject commit cef1c0d5ebde015d72d830e655ca1b4079a08494
index 36bd1ab6c1078b686fea8bc215651f99720386d1..559267a494f29a009954f07d66b8f02399e1f8ac 100644 (file)
@@ -17,7 +17,6 @@
     "MIT",
     "Unlicense/MIT",
     "Unlicense OR MIT",
-    "0BSD OR MIT OR Apache-2.0", // adler license
 ];
 
 /// These are exceptions to Rust's permissive licensing policy, and
@@ -37,6 +36,7 @@
     ("ryu", "Apache-2.0 OR BSL-1.0"),       // rls/cargo/... (because of serde)
     ("bytesize", "Apache-2.0"),             // cargo
     ("im-rc", "MPL-2.0+"),                  // cargo
+    ("adler32", "BSD-3-Clause AND Zlib"),   // cargo dep that isn't used
     ("constant_time_eq", "CC0-1.0"),        // rustfmt
     ("sized-chunks", "MPL-2.0+"),           // cargo via im-rc
     ("bitmaps", "MPL-2.0+"),                // cargo via im-rc
@@ -57,8 +57,7 @@
 /// This list is here to provide a speed-bump to adding a new dependency to
 /// rustc. Please check with the compiler team before adding an entry.
 const PERMITTED_DEPENDENCIES: &[&str] = &[
-    "addr2line",
-    "adler",
+    "adler32",
     "aho-corasick",
     "annotate-snippets",
     "ansi_term",
@@ -66,6 +65,7 @@
     "atty",
     "autocfg",
     "backtrace",
+    "backtrace-sys",
     "bitflags",
     "block-buffer",
     "block-padding",
@@ -98,7 +98,6 @@
     "generic-array",
     "getopts",
     "getrandom",
-    "gimli",
     "hashbrown",
     "hermit-abi",
     "humantime",
     "miniz_oxide",
     "nodrop",
     "num_cpus",
-    "object",
     "once_cell",
     "opaque-debug",
     "parking_lot",
index c0671596e19f1b365a990243d3b02ad7a1b51389..b4aafb815fc6b6b169a0caa91aa21de9a8c5b8dc 100644 (file)
@@ -60,7 +60,6 @@ fn filter_dirs(path: &Path) -> bool {
         "src/tools/rust-installer",
         "src/tools/rustfmt",
         "src/doc/book",
-        "src/backtrace",
         // Filter RLS output directories
         "target/rls",
     ];
index 51a29553fdb3dc1f5de8a071bd16326f64a3b7f9..ce4ea895400acdd6dde24a8ec104cc559d538f88 100644 (file)
@@ -81,7 +81,7 @@ topic = "I-prioritize #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* issue #{number} has been requested for prioritization.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#Unprioritized-I-prioritize)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#assign-priority-to-unprioritized-issues-with-i-prioritize-label)
 - Priority?
 - Regression?
 - Notify people/groups?
@@ -96,7 +96,7 @@ topic = "I-nominated #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#I-nominated)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-i-nominated-issues)
 - Already discussed?
 - Worth the meeting time?
 - Add agenda entry:
@@ -113,7 +113,7 @@ topic = "Backport #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* PR #{number} has been requested for beta backport.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#StableBeta-nominations)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
 Prepare agenda entry:
 - Why nominated?
 - Author, assignee?
@@ -127,7 +127,7 @@ topic = "Backport #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* PR #{number} has been requested for stable backport.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#StableBeta-nominations)
+# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
 Prepare agenda entry:
 - Why nominated?
 - Author, assignee?
@@ -142,7 +142,7 @@ topic = "S-waiting-on-team #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* PR #{number} is waiting on `T-compiler`.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#PR%E2%80%99s-waiting-on-team)
+# [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?
@@ -156,7 +156,7 @@ topic = "P-critical #{number} {title}"
 message_on_add = """\
 @*WG-prioritization/alerts* issue #{number} has been assigned `P-critical`.
 
-# [Procedure](https://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#P-critical-and-Unassigned-P-high-regressions)
+# [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:
@@ -172,7 +172,7 @@ 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://hackmd.io/WJ0G17DHTHGgv0OW9I2PxA?view#P-critical-and-Unassigned-P-high-regressions)
+# [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: